aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkumarashishg <kumarashishg@google.com>2023-09-27 10:46:51 +0000
committerkumarashishg <kumarashishg@google.com>2023-09-27 10:50:34 +0000
commitc9a8e744a91219fda0827d81ff650e9940ad3a24 (patch)
tree5fbebb9b63b922969aa2ff57532740cd790c7bfc
parent6405ac73f02c42a7a59751d50b89b0f9bccd743c (diff)
downloadpdfium-c9a8e744a91219fda0827d81ff650e9940ad3a24.tar.gz
Updated pdfium to df6fed9f3cbc13b656562b4775ea330c91732c71 (Chrome 117.0.5938.60)
Bug: 301504387 Test: Build the code, flash the device and check if it is working fine Change-Id: If3540f2e20a31c43516adaab8851f2ad215208f8
-rw-r--r--.gn3
-rw-r--r--.vpython34
-rw-r--r--AUTHORS3
-rw-r--r--BUILD.gn99
-rw-r--r--DEPS174
-rw-r--r--PRESUBMIT.py4
-rw-r--r--README.md7
-rw-r--r--build_overrides/BUILDCONFIG.gn4
-rw-r--r--build_overrides/build.gni5
-rw-r--r--build_overrides/partition_alloc.gni14
-rw-r--r--core/fdrm/fx_crypt.h2
-rw-r--r--core/fpdfapi/cmaps/fpdf_cmaps.h8
-rw-r--r--core/fpdfapi/edit/BUILD.gn1
-rw-r--r--core/fpdfapi/edit/DEPS5
-rw-r--r--core/fpdfapi/edit/cpdf_contentstream_write_utils.cpp213
-rw-r--r--core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp31
-rw-r--r--core/fpdfapi/edit/cpdf_stringarchivestream.cpp3
-rw-r--r--core/fpdfapi/edit/cpdf_stringarchivestream.h3
-rw-r--r--core/fpdfapi/font/cfx_cttgsubtable.cpp389
-rw-r--r--core/fpdfapi/font/cfx_cttgsubtable.h185
-rw-r--r--core/fpdfapi/font/cfx_stockfontarray.cpp8
-rw-r--r--core/fpdfapi/font/cpdf_cid2unicodemap.h2
-rw-r--r--core/fpdfapi/font/cpdf_cidfont.cpp34
-rw-r--r--core/fpdfapi/font/cpdf_cmap.h2
-rw-r--r--core/fpdfapi/font/cpdf_font.h3
-rw-r--r--core/fpdfapi/font/cpdf_fontglobals.cpp5
-rw-r--r--core/fpdfapi/font/cpdf_fontglobals.h12
-rw-r--r--core/fpdfapi/font/cpdf_tounicodemap.cpp24
-rw-r--r--core/fpdfapi/font/cpdf_tounicodemap.h2
-rw-r--r--core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp10
-rw-r--r--core/fpdfapi/font/cpdf_truetypefont.cpp1
-rw-r--r--core/fpdfapi/font/cpdf_type3char.h2
-rw-r--r--core/fpdfapi/page/BUILD.gn6
-rw-r--r--core/fpdfapi/page/DEPS5
-rw-r--r--core/fpdfapi/page/cpdf_allstates.cpp7
-rw-r--r--core/fpdfapi/page/cpdf_allstates.h4
-rw-r--r--core/fpdfapi/page/cpdf_color.h2
-rw-r--r--core/fpdfapi/page/cpdf_colorspace.cpp5
-rw-r--r--core/fpdfapi/page/cpdf_colorspace.h2
-rw-r--r--core/fpdfapi/page/cpdf_colorstate.h2
-rw-r--r--core/fpdfapi/page/cpdf_contentmarkitem.cpp1
-rw-r--r--core/fpdfapi/page/cpdf_contentmarkitem.h6
-rw-r--r--core/fpdfapi/page/cpdf_contentmarks.h8
-rw-r--r--core/fpdfapi/page/cpdf_contentparser.cpp20
-rw-r--r--core/fpdfapi/page/cpdf_contentparser.h9
-rw-r--r--core/fpdfapi/page/cpdf_devicecs.cpp3
-rw-r--r--core/fpdfapi/page/cpdf_dib.cpp30
-rw-r--r--core/fpdfapi/page/cpdf_dib.h4
-rw-r--r--core/fpdfapi/page/cpdf_expintfunc.h2
-rw-r--r--core/fpdfapi/page/cpdf_form.cpp12
-rw-r--r--core/fpdfapi/page/cpdf_form.h14
-rw-r--r--core/fpdfapi/page/cpdf_function.cpp6
-rw-r--r--core/fpdfapi/page/cpdf_function.h2
-rw-r--r--core/fpdfapi/page/cpdf_iccprofile.h2
-rw-r--r--core/fpdfapi/page/cpdf_image.cpp4
-rw-r--r--core/fpdfapi/page/cpdf_image.h4
-rw-r--r--core/fpdfapi/page/cpdf_imageobject.cpp7
-rw-r--r--core/fpdfapi/page/cpdf_indexedcs.cpp2
-rw-r--r--core/fpdfapi/page/cpdf_meshstream.cpp2
-rw-r--r--core/fpdfapi/page/cpdf_pageimagecache.cpp100
-rw-r--r--core/fpdfapi/page/cpdf_pageobject.cpp7
-rw-r--r--core/fpdfapi/page/cpdf_pageobject.h17
-rw-r--r--core/fpdfapi/page/cpdf_pattern.h3
-rw-r--r--core/fpdfapi/page/cpdf_psengine.h2
-rw-r--r--core/fpdfapi/page/cpdf_sampledfunc.cpp6
-rw-r--r--core/fpdfapi/page/cpdf_streamcontentparser.cpp47
-rw-r--r--core/fpdfapi/page/cpdf_streamcontentparser.h8
-rw-r--r--core/fpdfapi/page/cpdf_streamparser.h2
-rw-r--r--core/fpdfapi/page/cpdf_textobject.cpp2
-rw-r--r--core/fpdfapi/page/cpdf_textstate.h2
-rw-r--r--core/fpdfapi/page/cpdf_transferfunc.h2
-rw-r--r--core/fpdfapi/page/cpdf_transferfuncdib.h2
-rw-r--r--core/fpdfapi/parser/cfdf_document.cpp2
-rw-r--r--core/fpdfapi/parser/cfdf_document.h2
-rw-r--r--core/fpdfapi/parser/cpdf_cross_ref_avail.cpp6
-rw-r--r--core/fpdfapi/parser/cpdf_cross_ref_table.cpp22
-rw-r--r--core/fpdfapi/parser/cpdf_cross_ref_table.h5
-rw-r--r--core/fpdfapi/parser/cpdf_crypto_handler.cpp5
-rw-r--r--core/fpdfapi/parser/cpdf_crypto_handler.h2
-rw-r--r--core/fpdfapi/parser/cpdf_data_avail.cpp12
-rw-r--r--core/fpdfapi/parser/cpdf_encryptor.h2
-rw-r--r--core/fpdfapi/parser/cpdf_flateencoder.h2
-rw-r--r--core/fpdfapi/parser/cpdf_hint_tables.cpp2
-rw-r--r--core/fpdfapi/parser/cpdf_linearized_header.cpp2
-rw-r--r--core/fpdfapi/parser/cpdf_object_stream.cpp2
-rw-r--r--core/fpdfapi/parser/cpdf_parser.cpp52
-rw-r--r--core/fpdfapi/parser/cpdf_parser.h1
-rw-r--r--core/fpdfapi/parser/cpdf_parser_unittest.cpp452
-rw-r--r--core/fpdfapi/parser/cpdf_security_handler.cpp6
-rw-r--r--core/fpdfapi/parser/cpdf_security_handler_embeddertest.cpp5
-rw-r--r--core/fpdfapi/parser/cpdf_simple_parser.h2
-rw-r--r--core/fpdfapi/parser/cpdf_simple_parser_unittest.cpp7
-rw-r--r--core/fpdfapi/parser/cpdf_stream_acc.h2
-rw-r--r--core/fpdfapi/parser/cpdf_syntax_parser.h2
-rw-r--r--core/fpdfapi/parser/fpdf_parser_decode.cpp58
-rw-r--r--core/fpdfapi/parser/fpdf_parser_decode.h2
-rw-r--r--core/fpdfapi/parser/fpdf_parser_decode_unittest.cpp185
-rw-r--r--core/fpdfapi/parser/fpdf_parser_utility.cpp6
-rw-r--r--core/fpdfapi/parser/fpdf_parser_utility.h12
-rw-r--r--core/fpdfapi/parser/object_tree_traversal_util.cpp5
-rw-r--r--core/fpdfapi/parser/object_tree_traversal_util_embeddertest.cpp16
-rw-r--r--core/fpdfapi/render/charposlist.h2
-rw-r--r--core/fpdfapi/render/cpdf_imagerenderer.cpp32
-rw-r--r--core/fpdfapi/render/cpdf_progressiverenderer.h2
-rw-r--r--core/fpdfapi/render/cpdf_rendershading.cpp10
-rw-r--r--core/fpdfapi/render/cpdf_renderstatus.cpp12
-rw-r--r--core/fpdfapi/render/cpdf_rendertiling.cpp1
-rw-r--r--core/fpdfapi/render/cpdf_rendertiling.h2
-rw-r--r--core/fpdfapi/render/cpdf_textrenderer.h2
-rw-r--r--core/fpdfapi/render/fpdf_progressive_render_embeddertest.cpp26
-rw-r--r--core/fpdfdoc/BUILD.gn1
-rw-r--r--core/fpdfdoc/cpdf_annotlist.cpp17
-rw-r--r--core/fpdfdoc/cpdf_annotlist_unittest.cpp125
-rw-r--r--core/fpdfdoc/cpdf_defaultappearance.cpp26
-rw-r--r--core/fpdfdoc/cpdf_defaultappearance_unittest.cpp2
-rw-r--r--core/fpdfdoc/cpdf_generateap.cpp1
-rw-r--r--core/fpdfdoc/cpdf_interactiveform.h2
-rw-r--r--core/fpdfdoc/cpdf_metadata.cpp20
-rw-r--r--core/fpdfdoc/cpdf_metadata_unittest.cpp33
-rw-r--r--core/fpdfdoc/cpdf_nametree.cpp2
-rw-r--r--core/fpdfdoc/cpdf_structelement.cpp49
-rw-r--r--core/fpdfdoc/cpdf_structelement.h6
-rw-r--r--core/fpdfdoc/cpdf_structtree.cpp14
-rw-r--r--core/fpdfdoc/cpvt_fontmap.cpp9
-rw-r--r--core/fpdfdoc/cpvt_section.cpp5
-rw-r--r--core/fpdfdoc/cpvt_variabletext.cpp7
-rw-r--r--core/fpdftext/cpdf_textpage.cpp11
-rw-r--r--core/fpdftext/cpdf_textpagefind.cpp2
-rw-r--r--core/fxcodec/basic/basicmodule.h2
-rw-r--r--core/fxcodec/bmp/bmp_decoder.h2
-rw-r--r--core/fxcodec/bmp/cfx_bmpdecompressor.h2
-rw-r--r--core/fxcodec/cfx_codec_memory.cpp9
-rw-r--r--core/fxcodec/cfx_codec_memory.h2
-rw-r--r--core/fxcodec/fax/faxmodule.cpp7
-rw-r--r--core/fxcodec/fax/faxmodule.h2
-rw-r--r--core/fxcodec/flate/flatemodule.cpp2
-rw-r--r--core/fxcodec/flate/flatemodule.h2
-rw-r--r--core/fxcodec/gif/cfx_gifcontext.cpp1
-rw-r--r--core/fxcodec/gif/cfx_gifcontext.h2
-rw-r--r--core/fxcodec/gif/gif_decoder.h2
-rw-r--r--core/fxcodec/gif/lzw_decompressor.cpp2
-rw-r--r--core/fxcodec/icc/icc_transform.cpp6
-rw-r--r--core/fxcodec/icc/icc_transform.h2
-rw-r--r--core/fxcodec/jbig2/JBig2_ArithDecoder.cpp3
-rw-r--r--core/fxcodec/jbig2/JBig2_BitStream.cpp2
-rw-r--r--core/fxcodec/jbig2/JBig2_BitStream.h2
-rw-r--r--core/fxcodec/jbig2/JBig2_Context.cpp2
-rw-r--r--core/fxcodec/jbig2/JBig2_Context.h2
-rw-r--r--core/fxcodec/jbig2/JBig2_GrdProc.h5
-rw-r--r--core/fxcodec/jbig2/JBig2_HtrdProc.cpp4
-rw-r--r--core/fxcodec/jbig2/JBig2_HtrdProc.h6
-rw-r--r--core/fxcodec/jbig2/JBig2_HuffmanTable.cpp3
-rw-r--r--core/fxcodec/jbig2/JBig2_Image.h2
-rw-r--r--core/fxcodec/jbig2/JBig2_SddProc.h5
-rw-r--r--core/fxcodec/jbig2/JBig2_TrdProc.h3
-rw-r--r--core/fxcodec/jbig2/jbig2_decoder.h5
-rw-r--r--core/fxcodec/jpeg/jpeg_progressive_decoder.cpp2
-rw-r--r--core/fxcodec/jpeg/jpegmodule.h2
-rw-r--r--core/fxcodec/jpx/cjpx_decoder.cpp11
-rw-r--r--core/fxcodec/jpx/cjpx_decoder.h2
-rw-r--r--core/fxcodec/jpx/jpx_unittest.cpp7
-rw-r--r--core/fxcodec/progressive_decoder.cpp6
-rw-r--r--core/fxcodec/progressive_decoder.h5
-rw-r--r--core/fxcodec/progressive_decoder_unittest.cpp2
-rw-r--r--core/fxcodec/scanlinedecoder.h2
-rw-r--r--core/fxcrt/BUILD.gn35
-rw-r--r--core/fxcrt/autonuller.h3
-rw-r--r--core/fxcrt/autorestorer.h3
-rw-r--r--core/fxcrt/binary_buffer.h2
-rw-r--r--core/fxcrt/bytestring.cpp43
-rw-r--r--core/fxcrt/bytestring.h9
-rw-r--r--core/fxcrt/bytestring_unittest.cpp2
-rw-r--r--core/fxcrt/cfx_bitstream.h2
-rw-r--r--core/fxcrt/cfx_datetime.cpp2
-rw-r--r--core/fxcrt/cfx_fileaccess_windows.h3
-rw-r--r--core/fxcrt/cfx_memorystream.h2
-rw-r--r--core/fxcrt/cfx_read_only_span_stream.h2
-rw-r--r--core/fxcrt/cfx_read_only_string_stream.cpp2
-rw-r--r--core/fxcrt/cfx_read_only_vector_stream.cpp2
-rw-r--r--core/fxcrt/cfx_seekablestreamproxy.cpp6
-rw-r--r--core/fxcrt/cfx_seekablestreamproxy_unittest.cpp2
-rw-r--r--core/fxcrt/cfx_utf8decoder.cpp58
-rw-r--r--core/fxcrt/cfx_utf8decoder.h29
-rw-r--r--core/fxcrt/cfx_utf8encoder.cpp43
-rw-r--r--core/fxcrt/cfx_utf8encoder.h32
-rw-r--r--core/fxcrt/code_point_view.h91
-rw-r--r--core/fxcrt/code_point_view_unittest.cpp55
-rw-r--r--core/fxcrt/css/cfx_cssdata.cpp33
-rw-r--r--core/fxcrt/css/cfx_cssrulecollection.cpp2
-rw-r--r--core/fxcrt/css/cfx_cssrulecollection.h6
-rw-r--r--core/fxcrt/css/cfx_csssyntaxparser.cpp4
-rw-r--r--core/fxcrt/fixed_size_data_vector.h2
-rw-r--r--core/fxcrt/fixed_try_alloc_zeroed_data_vector_unittest.cpp2
-rw-r--r--core/fxcrt/fixed_uninit_data_vector_unittest.cpp2
-rw-r--r--core/fxcrt/fixed_zeroed_data_vector_unittest.cpp2
-rw-r--r--core/fxcrt/fx_codepage.h5
-rw-r--r--core/fxcrt/fx_coordinates.h68
-rw-r--r--core/fxcrt/fx_extension.cpp14
-rw-r--r--core/fxcrt/fx_folder_posix.cpp2
-rw-r--r--core/fxcrt/fx_folder_windows.cpp2
-rw-r--r--core/fxcrt/fx_memcpy_wrappers.h86
-rw-r--r--core/fxcrt/fx_memcpy_wrappers_unittest.cpp57
-rw-r--r--core/fxcrt/fx_memory.h9
-rw-r--r--core/fxcrt/fx_memory_malloc.cpp12
-rw-r--r--core/fxcrt/fx_memory_pa.cpp65
-rw-r--r--core/fxcrt/fx_memory_unittest.cpp41
-rw-r--r--core/fxcrt/fx_memory_wrappers.h19
-rw-r--r--core/fxcrt/fx_number.cpp7
-rw-r--r--core/fxcrt/fx_number_unittest.cpp12
-rw-r--r--core/fxcrt/fx_stream.h2
-rw-r--r--core/fxcrt/fx_string.cpp119
-rw-r--r--core/fxcrt/fx_string.h2
-rw-r--r--core/fxcrt/fx_string_unittest.cpp123
-rw-r--r--core/fxcrt/fx_system.h26
-rw-r--r--core/fxcrt/observed_ptr.h3
-rw-r--r--core/fxcrt/pdfium_span_unittest.cpp2
-rw-r--r--core/fxcrt/scoped_set_insertion.h3
-rw-r--r--core/fxcrt/shared_copy_on_write_unittest.cpp8
-rw-r--r--core/fxcrt/span_util.h13
-rw-r--r--core/fxcrt/string_data_template.cpp17
-rw-r--r--core/fxcrt/string_test_support.cpp20
-rw-r--r--core/fxcrt/string_view_template.h5
-rw-r--r--core/fxcrt/tree_node.h11
-rw-r--r--core/fxcrt/unowned_ptr.h63
-rw-r--r--core/fxcrt/unowned_ptr_exclusion.h17
-rw-r--r--core/fxcrt/unowned_ptr_unittest.cpp41
-rw-r--r--core/fxcrt/utf16.h107
-rw-r--r--core/fxcrt/utf16_unittest.cpp61
-rw-r--r--core/fxcrt/widestring.cpp31
-rw-r--r--core/fxcrt/widestring.h10
-rw-r--r--core/fxcrt/widestring_unittest.cpp2
-rw-r--r--core/fxcrt/widetext_buffer.h2
-rw-r--r--core/fxcrt/xml/cfx_xmlparser.cpp5
-rw-r--r--core/fxcrt/xml/cfx_xmlparser.h3
-rw-r--r--core/fxge/BUILD.gn9
-rw-r--r--core/fxge/DEPS8
-rw-r--r--core/fxge/agg/fx_agg_driver.cpp84
-rw-r--r--core/fxge/agg/fx_agg_driver.h6
-rw-r--r--core/fxge/android/cfpf_skiafont.h2
-rw-r--r--core/fxge/android/cfx_androidfontinfo.h2
-rw-r--r--core/fxge/android/fx_android_impl.cpp3
-rw-r--r--core/fxge/apple/fx_apple_impl.cpp2
-rw-r--r--core/fxge/apple/fx_quartz_device.cpp4
-rw-r--r--core/fxge/apple/fx_quartz_device.h2
-rw-r--r--core/fxge/cfx_color.cpp9
-rw-r--r--core/fxge/cfx_defaultrenderdevice.h12
-rw-r--r--core/fxge/cfx_face.h2
-rw-r--r--core/fxge/cfx_font.cpp53
-rw-r--r--core/fxge/cfx_font.h9
-rw-r--r--core/fxge/cfx_fontmapper.cpp6
-rw-r--r--core/fxge/cfx_fontmgr.h4
-rw-r--r--core/fxge/cfx_gemodule.h7
-rw-r--r--core/fxge/cfx_glyphcache.cpp2
-rw-r--r--core/fxge/cfx_glyphcache.h4
-rw-r--r--core/fxge/cfx_renderdevice.cpp13
-rw-r--r--core/fxge/cfx_renderdevice.h14
-rw-r--r--core/fxge/dib/cfx_bitmapcomposer.cpp2
-rw-r--r--core/fxge/dib/cfx_bitmapstorer.h2
-rw-r--r--core/fxge/dib/cfx_dibbase.cpp18
-rw-r--r--core/fxge/dib/cfx_dibbase.h32
-rw-r--r--core/fxge/dib/cfx_dibextractor.cpp28
-rw-r--r--core/fxge/dib/cfx_dibextractor.h26
-rw-r--r--core/fxge/dib/cfx_dibitmap.cpp32
-rw-r--r--core/fxge/dib/cfx_dibitmap.h25
-rw-r--r--core/fxge/dib/cfx_dibitmap_unittest.cpp58
-rw-r--r--core/fxge/dib/cfx_imagestretcher.cpp2
-rw-r--r--core/fxge/dib/cfx_imagetransformer.cpp28
-rw-r--r--core/fxge/dib/cfx_imagetransformer.h7
-rw-r--r--core/fxge/dib/cfx_scanlinecompositor.h2
-rw-r--r--core/fxge/dib/cstretchengine.cpp7
-rw-r--r--core/fxge/dib/cstretchengine.h2
-rw-r--r--core/fxge/dib/scanlinecomposer_iface.h2
-rw-r--r--core/fxge/freetype/fx_freetype.cpp31
-rw-r--r--core/fxge/freetype/fx_freetype.h25
-rw-r--r--core/fxge/fx_font.h2
-rw-r--r--core/fxge/renderdevicedriver_iface.h2
-rw-r--r--core/fxge/skia/DEPS8
-rw-r--r--core/fxge/skia/cfx_dibbase_skia.cpp288
-rw-r--r--core/fxge/skia/fx_skia_device.cpp397
-rw-r--r--core/fxge/skia/fx_skia_device.h12
-rw-r--r--core/fxge/skia/fx_skia_device_embeddertest.cpp119
-rw-r--r--core/fxge/systemfontinfo_iface.h2
-rw-r--r--core/fxge/win32/cfx_psrenderer.cpp7
-rw-r--r--core/fxge/win32/cfx_psrenderer.h2
-rw-r--r--core/fxge/win32/cfx_psrenderer_unittest.cpp2
-rw-r--r--core/fxge/win32/cgdi_device_driver.cpp137
-rw-r--r--core/fxge/win32/cgdi_device_driver.h8
-rw-r--r--core/fxge/win32/cgdi_display_driver.cpp31
-rw-r--r--core/fxge/win32/cgdi_plus_ext.cpp38
-rw-r--r--core/fxge/win32/cgdi_plus_ext.h4
-rw-r--r--core/fxge/win32/cgdi_printer_driver.cpp27
-rw-r--r--core/fxge/win32/cpsoutput.cpp2
-rw-r--r--core/fxge/win32/cwin32_platform.cpp2
-rw-r--r--fpdfsdk/BUILD.gn5
-rw-r--r--fpdfsdk/DEPS7
-rw-r--r--fpdfsdk/cpdfsdk_appstream.cpp6
-rw-r--r--fpdfsdk/cpdfsdk_baannot.cpp2
-rw-r--r--fpdfsdk/cpdfsdk_formfillenvironment.cpp3
-rw-r--r--fpdfsdk/cpdfsdk_formfillenvironment.h2
-rw-r--r--fpdfsdk/cpdfsdk_helpers.h2
-rw-r--r--fpdfsdk/cpdfsdk_renderpage.cpp1
-rw-r--r--fpdfsdk/cpdfsdk_widget.cpp1
-rw-r--r--fpdfsdk/formfiller/cffl_interactiveformfiller.cpp5
-rw-r--r--fpdfsdk/formfiller/cffl_perwindowdata.cpp2
-rw-r--r--fpdfsdk/fpdf_annot.cpp2
-rw-r--r--fpdfsdk/fpdf_annot_embeddertest.cpp72
-rw-r--r--fpdfsdk/fpdf_dataavail.cpp7
-rw-r--r--fpdfsdk/fpdf_edit_embeddertest.cpp255
-rw-r--r--fpdfsdk/fpdf_editimg.cpp1
-rw-r--r--fpdfsdk/fpdf_editpage.cpp7
-rw-r--r--fpdfsdk/fpdf_editpage_embeddertest.cpp47
-rw-r--r--fpdfsdk/fpdf_editpath.cpp2
-rw-r--r--fpdfsdk/fpdf_edittext.cpp13
-rw-r--r--fpdfsdk/fpdf_flatten.cpp3
-rw-r--r--fpdfsdk/fpdf_flatten_embeddertest.cpp13
-rw-r--r--fpdfsdk/fpdf_formfill.cpp34
-rw-r--r--fpdfsdk/fpdf_formfill_embeddertest.cpp21
-rw-r--r--fpdfsdk/fpdf_ppo.cpp2
-rw-r--r--fpdfsdk/fpdf_progressive.cpp21
-rw-r--r--fpdfsdk/fpdf_structtree.cpp13
-rw-r--r--fpdfsdk/fpdf_structtree_embeddertest.cpp40
-rw-r--r--fpdfsdk/fpdf_transformpage.cpp2
-rw-r--r--fpdfsdk/fpdf_view.cpp140
-rw-r--r--fpdfsdk/fpdf_view_c_api_test.c4
-rw-r--r--fpdfsdk/fpdf_view_embeddertest.cpp72
-rw-r--r--fpdfsdk/pwl/cpwl_caret.cpp2
-rw-r--r--fpdfsdk/pwl/cpwl_cblistbox.cpp1
-rw-r--r--fpdfsdk/pwl/cpwl_combo_box.cpp62
-rw-r--r--fpdfsdk/pwl/cpwl_combo_box.h2
-rw-r--r--fpdfsdk/pwl/cpwl_edit.cpp33
-rw-r--r--fpdfsdk/pwl/cpwl_edit.h2
-rw-r--r--fpdfsdk/pwl/cpwl_edit_impl.cpp17
-rw-r--r--fpdfsdk/pwl/cpwl_list_box.cpp28
-rw-r--r--fpdfsdk/pwl/cpwl_list_box.h4
-rw-r--r--fpdfsdk/pwl/cpwl_list_ctrl.cpp40
-rw-r--r--fpdfsdk/pwl/cpwl_list_ctrl.h4
-rw-r--r--fpdfsdk/pwl/cpwl_sbbutton.cpp32
-rw-r--r--fpdfsdk/pwl/cpwl_scroll_bar.cpp32
-rw-r--r--fpdfsdk/pwl/cpwl_scroll_bar.h4
-rw-r--r--fpdfsdk/pwl/cpwl_wnd.cpp144
-rw-r--r--fpdfsdk/pwl/cpwl_wnd.h25
-rw-r--r--fxbarcode/BC_TwoDimWriter.h2
-rw-r--r--fxbarcode/cfx_barcode.cpp5
-rw-r--r--fxbarcode/common/BC_CommonByteMatrix.h2
-rw-r--r--fxbarcode/datamatrix/BC_SymbolInfo.cpp6
-rw-r--r--fxbarcode/oned/BC_OneDimWriter.h2
-rw-r--r--fxbarcode/pdf417/BC_PDF417BarcodeRow.h2
-rw-r--r--fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h2
-rw-r--r--fxbarcode/qrcode/BC_QRCoderBitVector.h2
-rw-r--r--fxbarcode/qrcode/BC_QRCoderMaskUtil.cpp3
-rw-r--r--fxjs/cfx_globaldata.cpp30
-rw-r--r--fxjs/cfx_globaldata.h2
-rw-r--r--fxjs/cjs_field.cpp6
-rw-r--r--fxjs/cjs_global.cpp7
-rw-r--r--fxjs/cjs_object.h2
-rw-r--r--fxjs/fxv8.h2
-rw-r--r--fxjs/js_resources.cpp5
-rw-r--r--fxjs/xfa/cfxjse_class.cpp2
-rw-r--r--fxjs/xfa/cfxjse_context.cpp2
-rw-r--r--fxjs/xfa/cfxjse_engine.cpp3
-rw-r--r--fxjs/xfa/cfxjse_formcalc_context.cpp609
-rw-r--r--fxjs/xfa/cfxjse_formcalc_context.h28
-rw-r--r--fxjs/xfa/cfxjse_formcalc_context_embeddertest.cpp5
-rw-r--r--fxjs/xfa/cfxjse_formcalc_context_unittest.cpp69
-rw-r--r--fxjs/xfa/cjx_eventpseudomodel.cpp13
-rw-r--r--fxjs/xfa/cjx_exclgroup.cpp4
-rw-r--r--fxjs/xfa/cjx_form.cpp3
-rw-r--r--fxjs/xfa/cjx_hostpseudomodel.cpp38
-rw-r--r--fxjs/xfa/cjx_instancemanager.cpp6
-rw-r--r--fxjs/xfa/cjx_model.cpp6
-rw-r--r--fxjs/xfa/cjx_node.cpp7
-rw-r--r--fxjs/xfa/cjx_object.cpp16
-rw-r--r--fxjs/xfa/cjx_object.h5
-rw-r--r--fxjs/xfa/cjx_tree.cpp15
-rw-r--r--fxjs/xfa/cjx_treelist.cpp3
-rw-r--r--fxjs/xfa/fxjse.h3
-rw-r--r--pdfium.gni9
-rw-r--r--public/DEPS10
-rw-r--r--public/fpdf_formfill.h20
-rw-r--r--public/fpdfview.h78
-rw-r--r--samples/BUILD.gn25
-rw-r--r--samples/helpers/dump.cc (renamed from samples/pdfium_test_dump_helper.cc)20
-rw-r--r--samples/helpers/dump.h (renamed from samples/pdfium_test_dump_helper.h)6
-rw-r--r--samples/helpers/event.cc (renamed from samples/pdfium_test_event_helper.cc)28
-rw-r--r--samples/helpers/event.h (renamed from samples/pdfium_test_event_helper.h)6
-rw-r--r--samples/helpers/page_renderer.cc16
-rw-r--r--samples/helpers/page_renderer.h47
-rw-r--r--samples/helpers/win32/com_factory.cc51
-rw-r--r--samples/helpers/win32/com_factory.h25
-rw-r--r--samples/helpers/write.cc (renamed from samples/pdfium_test_write_helper.cc)201
-rw-r--r--samples/helpers/write.h (renamed from samples/pdfium_test_write_helper.h)17
-rw-r--r--samples/pdfium_test.cc850
-rw-r--r--skia/BUILD.gn45
-rw-r--r--testing/BUILD.gn11
-rw-r--r--testing/DEPS1
-rw-r--r--testing/SUPPRESSIONS391
-rw-r--r--testing/SUPPRESSIONS_EXACT_MATCHING2
-rw-r--r--testing/SUPPRESSIONS_IMAGE_DIFF2
-rw-r--r--testing/allocator_shim_config.cpp25
-rw-r--r--testing/allocator_shim_config.h18
-rw-r--r--testing/embedder_test.cpp40
-rw-r--r--testing/embedder_test.h2
-rw-r--r--testing/embedder_test_constants.cpp22
-rw-r--r--testing/embedder_test_main.cpp8
-rw-r--r--testing/fuzzers/BUILD.gn10
-rw-r--r--testing/fuzzers/DEPS3
-rw-r--r--testing/fuzzers/pdf_cmap_fuzzer.cc2
-rw-r--r--testing/fuzzers/pdf_codec_icc_fuzzer.cc2
-rw-r--r--testing/fuzzers/pdf_codec_jbig2_fuzzer.cc2
-rw-r--r--testing/fuzzers/pdf_fuzzer_init_public.cc5
-rw-r--r--testing/fuzzers/pdf_hint_table_fuzzer.cc2
-rw-r--r--testing/fuzzers/pdf_jpx_fuzzer.cc4
-rw-r--r--testing/fuzzers/pdf_nametree_fuzzer.cc2
-rw-r--r--testing/fuzzers/pdf_psengine_fuzzer.cc2
-rw-r--r--testing/fuzzers/pdf_streamparser_fuzzer.cc2
-rw-r--r--testing/fuzzers/pdf_xfa_fdp_fuzzer.cc3
-rw-r--r--testing/fuzzers/pdf_xml_fuzzer.cc2
-rw-r--r--testing/fuzzers/pdfium_fuzzer.cc12
-rw-r--r--testing/fuzzers/pdfium_fuzzer_helper.cc12
-rw-r--r--testing/fuzzers/xfa_codec_fuzzer.h2
-rw-r--r--testing/fx_string_testhelpers.cpp4
-rw-r--r--testing/image_diff/image_diff.cpp19
-rw-r--r--testing/image_diff/image_diff_png.cpp20
-rw-r--r--testing/image_diff/image_diff_png.h2
-rw-r--r--testing/resources/bug_1658.in65
-rw-r--r--testing/resources/bug_1658.pdf78
-rw-r--r--testing/resources/bug_2034.idatbin0 -> 25533 bytes
-rw-r--r--testing/resources/bug_2034.in65
-rw-r--r--testing/resources/bug_2034.pdfbin0 -> 26547 bytes
-rw-r--r--testing/resources/javascript/bug_1447268.evt2
-rw-r--r--testing/resources/javascript/bug_1447268.in209
-rw-r--r--testing/resources/javascript/bug_1447268_expected.txt3
-rw-r--r--testing/resources/multiple_graphics_states.in58
-rw-r--r--testing/resources/multiple_graphics_states.pdf71
-rw-r--r--testing/resources/pixel/bug_1021762_expected_skia_linux.pdf.0.pngbin0 -> 627 bytes
-rw-r--r--testing/resources/pixel/bug_1021762_expected_skia_win.pdf.0.pngbin0 -> 627 bytes
-rw-r--r--testing/resources/pixel/bug_1072440_expected_skia.pdf.0.pngbin463 -> 423 bytes
-rw-r--r--testing/resources/pixel/bug_1098.evt2
-rw-r--r--testing/resources/pixel/bug_1098.in60
-rw-r--r--testing/resources/pixel/bug_1098_expected.pdf.0.pngbin0 -> 2327 bytes
-rw-r--r--testing/resources/pixel/bug_1098_expected_mac.pdf.0.pngbin0 -> 1863 bytes
-rw-r--r--testing/resources/pixel/bug_1098_expected_skia.pdf.0.pngbin0 -> 1786 bytes
-rw-r--r--testing/resources/pixel/bug_1098_expected_skia_mac.pdf.0.pngbin0 -> 1865 bytes
-rw-r--r--testing/resources/pixel/bug_1131694.in125
-rw-r--r--testing/resources/pixel/bug_1131694_expected.pdf.0.pngbin0 -> 847 bytes
-rw-r--r--testing/resources/pixel/bug_113910_expected_skia.pdf.0.pngbin849 -> 812 bytes
-rw-r--r--testing/resources/pixel/bug_1271578_expected_skia.pdf.0.pngbin0 -> 168 bytes
-rw-r--r--testing/resources/pixel/bug_1286_expected_gdi.pdf.0.pngbin0 -> 645 bytes
-rw-r--r--testing/resources/pixel/bug_1287409_expected_gdi.pdf.0.pngbin0 -> 421 bytes
-rw-r--r--testing/resources/pixel/bug_1288_2_expected_gdi.pdf.0.pngbin0 -> 161 bytes
-rw-r--r--testing/resources/pixel/bug_1296_expected_gdi.pdf.0.pngbin0 -> 1137 bytes
-rw-r--r--testing/resources/pixel/bug_1308_1_expected_skia_linux.pdf.0.pngbin0 -> 219 bytes
-rw-r--r--testing/resources/pixel/bug_1308_1_expected_skia_win.pdf.0.pngbin0 -> 219 bytes
-rw-r--r--testing/resources/pixel/bug_1308_expected_skia_linux.pdf.0.pngbin0 -> 1850 bytes
-rw-r--r--testing/resources/pixel/bug_1308_expected_skia_win.pdf.0.pngbin0 -> 1850 bytes
-rw-r--r--testing/resources/pixel/bug_1338_expected_gdi.pdf.0.pngbin0 -> 3072 bytes
-rw-r--r--testing/resources/pixel/bug_1355_expected_skia.pdf.0.pngbin897 -> 844 bytes
-rw-r--r--testing/resources/pixel/bug_1355_expected_skia_mac.pdf.0.pngbin0 -> 897 bytes
-rw-r--r--testing/resources/pixel/bug_1356149_expected_skia.pdf.0.pngbin0 -> 386 bytes
-rw-r--r--testing/resources/pixel/bug_1372651_expected_skia.pdf.0.pngbin2468 -> 2266 bytes
-rw-r--r--testing/resources/pixel/bug_1388_2_expected_skia.pdf.0.pngbin0 -> 403 bytes
-rw-r--r--testing/resources/pixel/bug_1388_3_expected_skia.pdf.0.pngbin0 -> 236 bytes
-rw-r--r--testing/resources/pixel/bug_1388_expected_gdi.pdf.0.pngbin0 -> 362 bytes
-rw-r--r--testing/resources/pixel/bug_1395648_expected_skia.pdf.0.pngbin499 -> 500 bytes
-rw-r--r--testing/resources/pixel/bug_1396266_expected_skia.pdf.0.pngbin1322 -> 1322 bytes
-rw-r--r--testing/resources/pixel/bug_1402_expected_skia.pdf.0.pngbin708 -> 603 bytes
-rw-r--r--testing/resources/pixel/bug_1402_expected_skia_mac.pdf.0.pngbin0 -> 708 bytes
-rw-r--r--testing/resources/pixel/bug_1442723.in80
-rw-r--r--testing/resources/pixel/bug_1442723_expected.pdf.0.pngbin0 -> 436 bytes
-rw-r--r--testing/resources/pixel/bug_1442723_expected_agg_mac.pdf.0.pngbin0 -> 416 bytes
-rw-r--r--testing/resources/pixel/bug_1442723_expected_skia.pdf.0.pngbin0 -> 403 bytes
-rw-r--r--testing/resources/pixel/bug_1491_expected_gdi.pdf.0.pngbin0 -> 228 bytes
-rw-r--r--testing/resources/pixel/bug_1638_expected_gdi.pdf.0.pngbin0 -> 1151 bytes
-rw-r--r--testing/resources/pixel/bug_1639_1_expected_gdi.pdf.0.pngbin0 -> 589 bytes
-rw-r--r--testing/resources/pixel/bug_1752_expected_gdi.pdf.0.pngbin0 -> 1806 bytes
-rw-r--r--testing/resources/pixel/bug_1752_expected_skia.pdf.0.pngbin1710 -> 2242 bytes
-rw-r--r--testing/resources/pixel/bug_1772_expected_gdi.pdf.0.pngbin0 -> 257 bytes
-rw-r--r--testing/resources/pixel/bug_1774_expected_gdi.pdf.0.pngbin0 -> 128 bytes
-rw-r--r--testing/resources/pixel/bug_1883_expected_gdi.pdf.0.pngbin0 -> 1882 bytes
-rw-r--r--testing/resources/pixel/bug_1883_expected_gdi.pdf.1.pngbin0 -> 1984 bytes
-rw-r--r--testing/resources/pixel/bug_1883_expected_gdi.pdf.2.pngbin0 -> 1957 bytes
-rw-r--r--testing/resources/pixel/bug_1883_expected_gdi.pdf.3.pngbin0 -> 1950 bytes
-rw-r--r--testing/resources/pixel/bug_1922_expected.pdf.0.pngbin2732 -> 928 bytes
-rw-r--r--testing/resources/pixel/bug_1922_expected_skia.pdf.0.pngbin0 -> 827 bytes
-rw-r--r--testing/resources/pixel/bug_1963_expected_gdi.pdf.0.pngbin0 -> 169 bytes
-rw-r--r--testing/resources/pixel/bug_1972_2_expected_gdi.pdf.0.pngbin0 -> 474 bytes
-rw-r--r--testing/resources/pixel/bug_1983_expected_gdi.pdf.0.pngbin0 -> 325 bytes
-rw-r--r--testing/resources/pixel/bug_491_invisible_expected_gdi.pdf.0.pngbin0 -> 204 bytes
-rw-r--r--testing/resources/pixel/bug_491_unspecified_expected_gdi.pdf.0.pngbin0 -> 213 bytes
-rw-r--r--testing/resources/pixel/bug_491_visible_expected_gdi.pdf.0.pngbin0 -> 213 bytes
-rw-r--r--testing/resources/pixel/bug_524043_1_expected_skia.pdf.0.pngbin0 -> 1647 bytes
-rw-r--r--testing/resources/pixel/bug_524043_2_expected_skia.pdf.0.pngbin0 -> 699 bytes
-rw-r--r--testing/resources/pixel/bug_524043_3_expected_skia.pdf.0.pngbin0 -> 1647 bytes
-rw-r--r--testing/resources/pixel/bug_524043_4_expected_skia.pdf.0.pngbin0 -> 1647 bytes
-rw-r--r--testing/resources/pixel/bug_524043_5_expected_skia.pdf.0.pngbin0 -> 1647 bytes
-rw-r--r--testing/resources/pixel/bug_524043_7_expected_skia.pdf.0.pngbin0 -> 699 bytes
-rw-r--r--testing/resources/pixel/bug_528103_expected_skia.pdf.0.pngbin0 -> 1308 bytes
-rw-r--r--testing/resources/pixel/bug_543018_1_expected_skia.pdf.0.pngbin0 -> 1647 bytes
-rw-r--r--testing/resources/pixel/bug_543018_2_expected_skia.pdf.0.pngbin0 -> 1647 bytes
-rw-r--r--testing/resources/pixel/bug_551258_1_expected_skia.pdf.0.pngbin0 -> 1647 bytes
-rw-r--r--testing/resources/pixel/bug_585_expected_gdi.pdf.0.pngbin0 -> 1130 bytes
-rw-r--r--testing/resources/pixel/bug_601362_expected_gdi.pdf.0.pngbin0 -> 501 bytes
-rw-r--r--testing/resources/pixel/bug_632_expected_skia.pdf.1.pngbin591 -> 591 bytes
-rw-r--r--testing/resources/pixel/bug_665467_expected_skia.pdf.0.pngbin202 -> 203 bytes
-rw-r--r--testing/resources/pixel/bug_714187_expected_gdi.pdf.0.pngbin0 -> 1325 bytes
-rw-r--r--testing/resources/pixel/bug_725389_expected_skia.pdf.0.pngbin442 -> 384 bytes
-rw-r--r--testing/resources/pixel/bug_725389_expected_skia_mac.pdf.0.pngbin522 -> 451 bytes
-rw-r--r--testing/resources/pixel/bug_725555_expected_gdi.pdf.0.pngbin0 -> 2345 bytes
-rw-r--r--testing/resources/pixel/bug_733528_expected_skia.pdf.0.pngbin1195 -> 1086 bytes
-rw-r--r--testing/resources/pixel/bug_736695_2_expected_skia.pdf.0.pngbin1555 -> 1503 bytes
-rw-r--r--testing/resources/pixel/bug_736695_3_expected_skia.pdf.0.pngbin1461 -> 1418 bytes
-rw-r--r--testing/resources/pixel/bug_736703_expected_skia.pdf.0.pngbin0 -> 1407 bytes
-rw-r--r--testing/resources/pixel/bug_820345_expected_skia.pdf.0.pngbin0 -> 1531 bytes
-rw-r--r--testing/resources/pixel/bug_843_expected_gdi.pdf.0.pngbin0 -> 406 bytes
-rw-r--r--testing/resources/pixel/bug_845697_expected_skia.pdf.0.pngbin0 -> 743 bytes
-rw-r--r--testing/resources/pixel/bug_846_expected_skia.pdf.0.pngbin1233 -> 1172 bytes
-rw-r--r--testing/resources/pixel/bug_846_expected_skia_mac.pdf.0.pngbin1175 -> 1043 bytes
-rw-r--r--testing/resources/pixel/bug_846_expected_skia_win.pdf.0.pngbin1175 -> 1043 bytes
-rw-r--r--testing/resources/pixel/bug_909762_expected_skia_linux.pdf.0.pngbin0 -> 701 bytes
-rw-r--r--testing/resources/pixel/bug_909762_expected_skia_win.pdf.0.pngbin0 -> 701 bytes
-rw-r--r--testing/resources/pixel/bug_925736_expected_skia.pdf.0.pngbin0 -> 1635 bytes
-rw-r--r--testing/resources/pixel/bug_972999_expected_gdi.pdf.0.pngbin0 -> 421 bytes
-rw-r--r--testing/resources/pixel/bug_983289_expected_gdi.pdf.0.pngbin0 -> 3518 bytes
-rw-r--r--testing/resources/pixel/bug_984811_expected_skia.pdf.0.pngbin0 -> 1143 bytes
-rw-r--r--testing/resources/pixel/font_size_expected_skia.pdf.0.pngbin0 -> 3303 bytes
-rw-r--r--testing/resources/pixel/generation_numbers1_expected_skia.pdf.0.pngbin0 -> 1388 bytes
-rw-r--r--testing/resources/pixel/generation_numbers2_expected_skia.pdf.0.pngbin0 -> 1388 bytes
-rw-r--r--testing/resources/pixel/matte_expected_skia.pdf.0.pngbin316 -> 316 bytes
-rw-r--r--testing/resources/pixel/password_expected_skia.pdf.0.pngbin2049 -> 2404 bytes
-rw-r--r--testing/resources/pixel/rectangles_wrong_xref_size.in48
-rw-r--r--testing/resources/pixel/rectangles_wrong_xref_size_expected.pdf.0.pngbin0 -> 404 bytes
-rw-r--r--testing/resources/pixel/rectangles_wrong_xref_size_expected_gdi.pdf.0.pngbin0 -> 421 bytes
-rw-r--r--testing/resources/pixel/rectangles_wrong_xref_size_expected_skia.pdf.0.pngbin0 -> 564 bytes
-rw-r--r--testing/resources/pixel/scrollable_widgets1_expected_skia.pdf.0.pngbin3240 -> 3133 bytes
-rw-r--r--testing/resources/pixel/scrollable_widgets2_expected_skia.pdf.0.pngbin3476 -> 3323 bytes
-rw-r--r--testing/resources/pixel/text_form_custom_font_expected_skia.pdf.0.pngbin451 -> 395 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/barcode_test_expected_skia.pdf.0.pngbin7424 -> 6957 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/dynamic_list_box_allow_multiple_selection_expected_skia.pdf.0.pngbin10089 -> 9288 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/dynamic_list_box_allow_multiple_selection_expected_skia_mac.pdf.0.pngbin10091 -> 9294 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/dynamic_password_field_background_fill_expected_skia.pdf.0.pngbin33017 -> 31528 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/dynamic_table_color_and_width_expected_skia.pdf.0.pngbin12728 -> 12007 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/resolve_nodes_0_expected_skia.pdf.0.pngbin62206 -> 60208 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/static_list_box_caption_expected_skia.pdf.0.pngbin6943 -> 12089 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/static_list_box_caption_expected_skia_mac.pdf.0.pngbin0 -> 12579 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/static_password_field_rotate_expected_skia.pdf.0.pngbin33033 -> 30256 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/static_password_field_rotate_expected_skia.pdf.1.pngbin30246 -> 27436 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/static_password_field_rotate_expected_skia_mac.pdf.0.pngbin0 -> 30725 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/static_password_field_rotate_expected_skia_mac.pdf.1.pngbin0 -> 27588 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/use_ahem/xfa_textfield_expected_skia.pdf.0.pngbin1177 -> 1621 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia.pdf.0.pngbin18985 -> 18513 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia.pdf.1.pngbin22312 -> 21489 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_mac.pdf.0.pngbin18169 -> 17681 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_mac.pdf.1.pngbin21094 -> 20225 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_win.pdf.0.pngbin19003 -> 18036 bytes
-rw-r--r--testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_win.pdf.1.pngbin21831 -> 20461 bytes
-rw-r--r--testing/resources/rectangles_object_zero.in45
-rw-r--r--testing/resources/rectangles_object_zero.pdf56
-rw-r--r--testing/resources/tagged_table.in18
-rw-r--r--testing/resources/tagged_table.pdf26
-rw-r--r--testing/resources/tagged_table_bad_parent.in217
-rw-r--r--testing/resources/tagged_table_bad_parent.pdf241
-rw-r--r--testing/test_loader.cpp10
-rw-r--r--testing/test_loader.h2
-rw-r--r--testing/tools/BUILD.gn47
-rw-r--r--testing/tools/generate_cas_paths.py105
-rwxr-xr-xtesting/tools/pngdiffer.py14
-rw-r--r--testing/tools/skia_gold/pdfium_skia_gold_properties.py17
-rw-r--r--testing/tools/skia_gold/skia_gold.py8
-rwxr-xr-xtesting/tools/suppressor.py10
-rw-r--r--testing/tools/test_runner.py70
-rw-r--r--testing/unit_test_main.cpp8
-rw-r--r--testing/utils/hash.h2
-rw-r--r--third_party/BUILD.gn39
-rw-r--r--third_party/NotoSansCJK/README.pdfium1
-rw-r--r--third_party/agg23/0015-include-string-h.patch26
-rw-r--r--third_party/agg23/README.pdfium2
-rw-r--r--third_party/agg23/agg_array.h2
-rw-r--r--third_party/agg23/agg_path_storage.cpp2
-rw-r--r--third_party/android_sdk/BUILD.gn29
-rw-r--r--third_party/base/containers/span.h (renamed from third_party/base/span.h)26
-rw-r--r--third_party/base/cxx17_backports.h34
-rw-r--r--third_party/base/memory/ptr_util.h (renamed from third_party/base/ptr_util.h)6
-rw-r--r--third_party/base/numerics/README.pdfium2
-rw-r--r--third_party/cpu_features/BUILD.gn61
-rw-r--r--third_party/cpu_features/README.pdfium15
-rw-r--r--third_party/freetype/README.pdfium7
-rw-r--r--third_party/fuchsia-sdk/README.chromium1
-rw-r--r--third_party/googletest/BUILD.gn2
-rw-r--r--third_party/googletest/README.pdfium2
-rw-r--r--third_party/googletest/custom/gtest/internal/custom/gtest-printers.h35
-rw-r--r--third_party/lcms/0035-func-ptr-mixup.patch29
-rw-r--r--third_party/lcms/README.pdfium2
-rw-r--r--third_party/lcms/src/cmsopt.c11
-rw-r--r--third_party/libopenjpeg/0046-func-ptr-mixup.patch1449
-rw-r--r--third_party/libopenjpeg/README.pdfium2
-rw-r--r--third_party/libopenjpeg/j2k.c71
-rw-r--r--third_party/libopenjpeg/j2k.h72
-rw-r--r--third_party/libopenjpeg/jp2.c86
-rw-r--r--third_party/libopenjpeg/jp2.h64
-rw-r--r--third_party/libopenjpeg/openjpeg.c247
-rw-r--r--third_party/libtiff/0000-build-config.patch12
-rw-r--r--third_party/libtiff/METADATA17
-rw-r--r--third_party/libtiff/README.pdfium5
-rw-r--r--third_party/libtiff/tif_close.c32
-rw-r--r--third_party/libtiff/tif_dir.c125
-rw-r--r--third_party/libtiff/tif_dir.h12
-rw-r--r--third_party/libtiff/tif_dirinfo.c983
-rw-r--r--third_party/libtiff/tif_dirread.c194
-rw-r--r--third_party/libtiff/tif_dirwrite.c12
-rw-r--r--third_party/libtiff/tif_fax3.c2
-rw-r--r--third_party/libtiff/tif_hash_set.c4
-rw-r--r--third_party/libtiff/tif_hash_set.h4
-rw-r--r--third_party/libtiff/tif_luv.c7
-rw-r--r--third_party/libtiff/tif_lzw.c5
-rw-r--r--third_party/libtiff/tif_open.c8
-rw-r--r--third_party/libtiff/tiff.h1034
-rw-r--r--third_party/libtiff/tiffio.h6
-rw-r--r--third_party/libtiff/tiffiop.h15
-rw-r--r--third_party/libtiff/tiffvers.h6
-rw-r--r--third_party/ninja/README.pdfium1
-rw-r--r--third_party/pymock/README.chromium4
-rw-r--r--third_party/skia_shared/SkFloatToDecimal.cpp181
-rw-r--r--third_party/skia_shared/SkFloatToDecimal.h40
-rw-r--r--xfa/fde/cfde_texteditengine.cpp8
-rw-r--r--xfa/fde/cfde_textout.cpp5
-rw-r--r--xfa/fde/cfde_textout.h2
-rw-r--r--xfa/fde/cfde_textout_unittest.cpp14
-rw-r--r--xfa/fgas/crt/cfgas_stringformatter.cpp7
-rw-r--r--xfa/fgas/crt/cfgas_stringformatter.h2
-rw-r--r--xfa/fgas/font/cfgas_fontmgr.cpp2
-rw-r--r--xfa/fgas/font/cfgas_fontmgr.h4
-rw-r--r--xfa/fgas/font/fgas_fontutils.cpp18
-rw-r--r--xfa/fgas/graphics/cfgas_gegraphics.cpp12
-rw-r--r--xfa/fgas/graphics/cfgas_gegraphics.h2
-rw-r--r--xfa/fgas/layout/cfgas_rtfbreak.cpp1
-rw-r--r--xfa/fgas/layout/cfgas_txtbreak.cpp1
-rw-r--r--xfa/fgas/layout/cfgas_txtbreak.h8
-rw-r--r--xfa/fwl/cfwl_edit.cpp3
-rw-r--r--xfa/fwl/cfwl_event.h5
-rw-r--r--xfa/fwl/cfwl_listbox.cpp7
-rw-r--r--xfa/fwl/cfwl_listbox.h5
-rw-r--r--xfa/fwl/cfwl_monthcalendar.cpp6
-rw-r--r--xfa/fwl/cfwl_notedriver.cpp2
-rw-r--r--xfa/fwl/cfwl_scrollbar.cpp5
-rw-r--r--xfa/fxfa/cxfa_ffline.cpp9
-rw-r--r--xfa/fxfa/cxfa_textlayout.cpp6
-rw-r--r--xfa/fxfa/cxfa_textparser.cpp3
-rw-r--r--xfa/fxfa/formcalc/cxfa_fmparser.h4
-rw-r--r--xfa/fxfa/layout/cxfa_contentlayoutprocessor.cpp5
-rw-r--r--xfa/fxfa/layout/cxfa_viewlayoutprocessor.h9
-rw-r--r--xfa/fxfa/parser/cxfa_box.cpp4
-rw-r--r--xfa/fxfa/parser/cxfa_document.cpp3
-rw-r--r--xfa/fxfa/parser/cxfa_document.h2
-rw-r--r--xfa/fxfa/parser/cxfa_document_builder.cpp3
-rw-r--r--xfa/fxfa/parser/cxfa_localemgr.cpp1
-rw-r--r--xfa/fxfa/parser/cxfa_localevalue.cpp2
-rw-r--r--xfa/fxfa/parser/cxfa_measurement.cpp3
-rw-r--r--xfa/fxfa/parser/cxfa_node.cpp14
-rw-r--r--xfa/fxfa/parser/cxfa_node.h5
-rw-r--r--xfa/fxfa/parser/cxfa_node_unittest.cpp11
-rw-r--r--xfa/fxfa/parser/cxfa_object.h3
-rw-r--r--xfa/fxfa/parser/cxfa_rectangle.cpp3
-rw-r--r--xfa/fxfa/parser/cxfa_xmllocale.h2
663 files changed, 11898 insertions, 5666 deletions
diff --git a/.gn b/.gn
index b2bf99d0c..e39d6f7f7 100644
--- a/.gn
+++ b/.gn
@@ -11,6 +11,9 @@ buildconfig = "//build_overrides/BUILDCONFIG.gn"
script_executable = "python3"
default_args = {
+ # Required for the Fuchsia SDK
+ fuchsia_target_api_level = 11
+
# PDFs only need to run JavaScript.
v8_enable_webassembly = false
diff --git a/.vpython3 b/.vpython3
index b6cb1b556..52840c65f 100644
--- a/.vpython3
+++ b/.vpython3
@@ -45,8 +45,8 @@ wheel: <
version: "version:2.10"
>
wheel: <
- name: "infra/python/wheels/requests-py2_py3"
- version: "version:2.26.0"
+ name: "infra/python/wheels/requests-py3"
+ version: "version:2.31.0"
>
wheel: <
name: "infra/python/wheels/urllib3-py2_py3"
diff --git a/AUTHORS b/AUTHORS
index f8e3ed9ea..5b982879f 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -17,10 +17,12 @@ Antonio Gomes <tonikitoo@igalia.com>
Chery Cherian <cherycherian@gmail.com>
Claudio DeSouza <claudiomdsjr@gmail.com>
Dan Ilan <danilan@gmail.com>
+Dorian Rudolph <dorianrudo97@gmail.com>
Felix Kauselmann <licorn@gmail.com>
GiWan Go <gogil@stealien.com>
Huy Ngo <huyna89@gmail.com>
Jiang Jiang <jiangj@opera.com>
+Justin Pierce <brkfstmnchr@gmail.com>
Ke Liu <stackexploit@gmail.com>
Luật Nguyễn <manhluat93.php@gmail.com>
Manuel Geißer <geisserml@gmail.com>
@@ -44,6 +46,7 @@ DocsCorp Pty Ltd. <*@docscorp.com>
Dropbox <*@dropbox.com>
Foxit Software Inc <*@foxitsoftware.com>
Google Inc. <*@google.com>
+Igalia S.L. <*@igalia.com>
LG Electronics, Inc. <*@lge.com>
Loongson Technology Corporation Limited. <*@loongson.cn>
Microsoft <*@microsoft.com>
diff --git a/BUILD.gn b/BUILD.gn
index cb1da47df..07a5b933a 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -9,7 +9,10 @@ import("pdfium.gni")
group("default") {
testonly = true
- deps = [ ":pdfium_all" ]
+ deps = [ ":pdfium" ]
+ if (pdf_is_standalone) {
+ deps += [ ":pdfium_all" ]
+ }
}
group("freetype_common") {
@@ -164,8 +167,7 @@ config("pdfium_common_config") {
# signed/unsigned mismatch
"/wd4267", # 'var' : conversion from 'size_t' to 'type', possible loss
- # of
- # data
+ # of data
"/wd4305", # 'identifier' : truncation from 'type1' to 'type2'
"/wd4389", # 'operator' : signed/unsigned mismatch
@@ -197,14 +199,6 @@ config("pdfium_common_config") {
]
if (current_cpu == "x86") {
- cflags += [
- # VC++ 2015 changes 32-bit size_t truncation warnings from 4244 to
- # 4267. Example: short TruncTest(size_t x) { return x; }
- # Since we disable 4244 we need to disable 4267 during migration.
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- "/wd4267",
- ]
-
if (msvc_use_sse2) {
cflags += [ "/arch:SSE2" ]
}
@@ -221,16 +215,6 @@ config("pdfium_common_config") {
# May flag some issues when converting int to size_t.
cflags += [ "-Wtautological-unsigned-zero-compare" ]
-
- # Catch misuse of cppgc in XFA.
- if (pdf_enable_xfa && clang_use_chrome_plugins) {
- cflags += [
- "-Xclang",
- "-add-plugin",
- "-Xclang",
- "blink-gc-plugin",
- ]
- }
}
if (!is_win && !is_clang) {
@@ -288,11 +272,59 @@ config("pdfium_core_config") {
"/wd4577",
]
}
+ if (is_clang) {
+ cflags += [ "-Wcovered-switch-default" ]
+ }
+}
+
+config("pdfium_plugin_config") {
+ cflags = []
+ defines = []
+ if (clang_use_chrome_plugins) {
+ # Catch misuse of C-style pointers.
+ # TODO(tsepez): enable for windows, too.
+ if (!is_win) {
+ cflags += [
+ "-Xclang",
+ "-plugin-arg-find-bad-constructs",
+ "-Xclang",
+ "check-raw-ptr-fields",
+
+ "-Xclang",
+ "-plugin-arg-find-bad-constructs",
+ "-Xclang",
+ "raw-ptr-exclude-path=public",
+
+ "-Xclang",
+ "-plugin-arg-find-bad-constructs",
+ "-Xclang",
+ "raw-ptr-exclude-path=test",
+
+ # TODO(tsepez): enforce raw_ref<> as well.
+ # "-Xclang",
+ # "-plugin-arg-find-bad-constructs",
+ # "-Xclang",
+ # "check-raw-ref-fields",
+ ]
+ defines += [ "PDF_ENABLE_UNOWNED_PTR_EXCLUSION" ]
+ }
+
+ # Catch misuse of cppgc in XFA.
+ if (pdf_enable_xfa) {
+ cflags += [
+ "-Xclang",
+ "-add-plugin",
+ "-Xclang",
+ "blink-gc-plugin",
+ ]
+ }
+ }
}
config("pdfium_strict_config") {
configs = [
":pdfium_core_config",
+ ":pdfium_plugin_config",
"//build/config/compiler:wexit_time_destructors",
"//build/config/compiler:wglobal_constructors",
]
@@ -359,7 +391,6 @@ component("pdfium") {
"fpdfsdk/formfiller",
"fxjs",
"third_party:pdfium_base",
- "third_party:skia_shared",
]
public_deps = [
@@ -439,18 +470,15 @@ test("pdfium_unittests") {
"//testing/gtest",
]
configs += [ ":pdfium_core_config" ]
-
if (is_android) {
use_raw_android_executable = true
}
-
if (pdf_enable_v8) {
configs += [ "//v8:external_startup_data" ]
deps += [
"fxjs:unittests",
"//v8",
]
-
if (pdf_enable_xfa) {
deps += [
"core/fxcrt/css:unittests",
@@ -530,6 +558,7 @@ test("pdfium_embeddertests") {
}
executable("pdfium_diff") {
+ visibility += [ "testing/tools:test_runner_py" ]
testonly = true
sources = [ "testing/image_diff/image_diff.cpp" ]
deps = [
@@ -541,30 +570,18 @@ executable("pdfium_diff") {
configs += [ ":pdfium_strict_config" ]
}
-if (pdf_is_standalone) {
- source_set("samples") {
- testonly = true
- deps = [ "//samples" ]
- }
-
- group("fuzzers") {
- testonly = true
- deps = [ "//testing/fuzzers" ]
- }
-}
-
group("pdfium_all") {
testonly = true
deps = [
":pdfium_diff",
":pdfium_embeddertests",
":pdfium_unittests",
+ "samples",
+ "testing/fuzzers",
]
+
if (pdf_is_standalone) {
- deps += [
- ":fuzzers",
- ":samples",
- ]
+ deps += [ "testing/tools:test_runner_py" ]
}
}
diff --git a/DEPS b/DEPS
index e5aa4d851..5a55c16dd 100644
--- a/DEPS
+++ b/DEPS
@@ -25,7 +25,19 @@ vars = {
'checkout_v8': 'checkout_configuration != "minimal"',
# By default, download the fuchsia sdk from the public sdk directory.
- 'fuchsia_sdk_cipd_prefix': 'fuchsia/sdk/gn/',
+ 'fuchsia_sdk_cipd_prefix': 'fuchsia/sdk/core/',
+
+ # Fetch configuration files required for the 'use_remoteexec' gn arg
+ 'download_remoteexec_cfg': False,
+ # RBE instance to use for running remote builds
+ 'rbe_instance': Str('projects/rbe-chrome-untrusted/instances/default_instance'),
+ # RBE project to download rewrapper config files for. Only needed if
+ # different from the project used in 'rbe_instance'
+ 'rewrapper_cfg_project': Str(''),
+ # reclient CIPD package
+ 'reclient_package': 'infra/rbe/client/',
+ # reclient CIPD package version
+ 'reclient_version': 're_client_version:0.109.0.927890d-gomaip',
'chromium_git': 'https://chromium.googlesource.com',
'pdfium_git': 'https://pdfium.googlesource.com',
@@ -34,51 +46,59 @@ vars = {
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling abseil
# and whatever else without interference from each other.
- 'abseil_revision': '20c8ae002db022653b94e80dec69306558818ebf',
+ 'abseil_revision': '2288062eef9624e8b48070ed2447139d3fd4a1c5',
# Three lines of non-changing comments so that
- # the commit queue can handle CLs rolling android_ndk
+ # the commit queue can handle CLs rolling android_toolchain
# and whatever else without interference from each other.
- 'android_ndk_revision': '8388a2be5421311dc75c5f937aae13d821a27f3d',
+ 'android_toolchain_version': 'R_8suM8m0oHbZ1awdxGXvKEFpAOETscbfZxkkMthyk8C',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling build
# and whatever else without interference from each other.
- 'build_revision': 'c44ccbfc028a136e7d39bf79e45a92a91d7b5beb',
+ 'build_revision': '336e34d44c88d1160d150bd6c8d93e203a424b42',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling buildtools
# and whatever else without interference from each other.
- 'buildtools_revision': '3ee69a5c6bc8d115dea09bbf8e536f529e7e12a8',
+ 'buildtools_revision': '16be42a9ff1f7e4a3e53b93b3adc181fa7ff9161',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling catapult
# and whatever else without interference from each other.
- 'catapult_revision': 'ac30cc4bc7d30e574625e1f6a77fba5df0719ed6',
+ 'catapult_revision': '220cbb13b5a7485be09813e7da4123088419a76a',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling clang format
# and whatever else without interference from each other.
- 'clang_format_revision': 'f97059df7f8b205064625cdb5f97b56668a125ef',
+ 'clang_format_revision': 'e5337933f2951cacd3aeacd238ce4578163ca0b9',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling clang
# and whatever else without interference from each other.
- 'clang_revision': 'f6862472607fa628642713b615a9e119d51bd43d',
+ 'clang_revision': '236e66ffd61f3bd710d20d20a67e71a1f1f55cba',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling code_coverage
# and whatever else without interference from each other.
- 'code_coverage_revision': '9b51524c4f7575ee90d9173507e6f13f814d7001',
+ 'code_coverage_revision': 'bce4cdc2309e9a7f1e0ff1d9310e0d0302aa67e0',
+ # Three lines of non-changing comments so that
+ # the commit queue can handle CLs rolling code_coverage
+ # and whatever else without interference from each other.
+ 'cpu_features_revision': '936b9ab5515dead115606559502e3864958f7f6e',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling depot_tools
# and whatever else without interference from each other.
- 'depot_tools_revision': 'ab117384e6c0384ba5aab66c13d8f1008d964655',
+ 'depot_tools_revision': '59e10115417ac77f47e42c3f13a4f6b58ebe70c2',
+ # Three lines of non-changing comments so that
+ # the commit queue can handle CLs rolling freetype
+ # and whatever else without interference from each other.
+ 'freetype_revision': 'b2584c738f1a92e6369890cff0504cc044315b38',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling freetype
# and whatever else without interference from each other.
- 'freetype_revision': 'b0a4f99278aa7e14bd1d0d9e40ad28dce543fde6',
+ 'fuchsia_gn_sdk_revision': '0d6902558d92fe3d49ba9a8f638ddea829be595b',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling Fuchsia sdk
# and whatever else without interference from each other.
- 'fuchsia_version': 'version:12.20230330.3.1',
+ 'fuchsia_version': 'version:14.20230727.2.1',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling GN CIPD package version
# and whatever else without interference from each other.
- 'gn_version': 'git_revision:41fef642de70ecdcaaa26be96d56a0398f95abd4',
+ 'gn_version': 'git_revision:3fccef9033b950e8935e8debeba9fbd71617bc74',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling gtest
# and whatever else without interference from each other.
@@ -86,29 +106,29 @@ vars = {
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling icu
# and whatever else without interference from each other.
- 'icu_revision': '1e49ac26ddc712b1ab702f69023cbc57e9ae6628',
+ 'icu_revision': 'de4ce0071eb47ed54cbda54869001210cf3a8ae5',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling instrumented_lib
# and whatever else without interference from each other.
- 'instrumented_lib_revision': '0f536d22dbed454b1254c7e6d7130eab28fba1fa',
+ 'instrumented_lib_revision': '032e9c850ab975f7c088a625dcf2256917dbdfa6',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling jinja2
# and whatever else without interference from each other.
- 'jinja2_revision': '264c07d7e64f2874434a3b8039e101ddf1b01e7e',
+ 'jinja2_revision': '515dd10de9bf63040045902a4a310d2ba25213a0',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling jpeg_turbo
# and whatever else without interference from each other.
- 'jpeg_turbo_revision': 'aa4075f116e4312537d0d3e9dbd5e31096539f94',
+ 'jpeg_turbo_revision': '30bdb85e302ecfc52593636b2f44af438e05e784',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling libc++
# and whatever else without interference from each other.
# If you change this, also update the libc++ revision in
# //buildtools/deps_revisions.gni.
- 'libcxx_revision': 'ab37483b426c16ce33f8f0064be571513d5a8c34',
+ 'libcxx_revision': '84fb809dd6dae36d556dc0bb702c6cc2ce9d4b80',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling libc++abi
# and whatever else without interference from each other.
- 'libcxxabi_revision': '4a9d0560b481a96821bec591325b50a5063f4a32',
+ 'libcxxabi_revision': 'd4760c0af99ccc9bce077960d5ddde4d66146c05',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling libpng
# and whatever else without interference from each other.
@@ -116,15 +136,11 @@ vars = {
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling libunwind
# and whatever else without interference from each other.
- 'libunwind_revision': 'f3464caa6aa83a5eb924a5ae3779e974bd1bebf4',
- # Three lines of non-changing comments so that
- # the commit queue can handle CLs rolling lss
- # and whatever else without interference from each other.
- 'lss_revision': 'ce877209e11aa69dcfffbd53ef90ea1d07136521',
+ 'libunwind_revision': 'e5a9c50e5e0b620a8886df1c4677b12404620fb6',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling markupsafe
# and whatever else without interference from each other.
- 'markupsafe_revision': '13f4e8c9e206567eeb13bf585406ddc574005748',
+ 'markupsafe_revision': '006709ba3ed87660a17bd4548c45663628f5ed85',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling nasm_source
# and whatever else without interference from each other.
@@ -136,11 +152,11 @@ vars = {
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling partition_allocator
# and whatever else without interference from each other.
- 'partition_allocator_revision': '118936d6793d0c259bd9023717d37367a7b04320',
+ 'partition_allocator_revision': 'f91d5ba232cbe61b9740b4101a5b5bea3cd631ed',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling pdfium_tests
# and whatever else without interference from each other.
- 'pdfium_tests_revision': 'd1386521f5d606b9110143aa40b23651b17aded2',
+ 'pdfium_tests_revision': 'dc2cd9afdd1bad8666072416c340ad1c6a01e388',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling resultdb
# and whatever else without interference from each other.
@@ -148,7 +164,7 @@ vars = {
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling skia
# and whatever else without interference from each other.
- 'skia_revision': 'ad459a5b8df474d881209696b3fb4f038e0d3a55',
+ 'skia_revision': '6119b059f50a1858f882068cc6738571240b4f5d',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling test_fonts
# and whatever else without interference from each other.
@@ -156,7 +172,7 @@ vars = {
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling tools_memory
# and whatever else without interference from each other.
- 'tools_memory_revision': '13f0b81ce581364c5f0f2e9e16d6120073dc56a6',
+ 'tools_memory_revision': '2a4c4ba1f4a94231b01280a0c63d3fe4404cc9c2',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling trace_event
# and whatever else without interference from each other.
@@ -164,11 +180,11 @@ vars = {
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling v8
# and whatever else without interference from each other.
- 'v8_revision': 'f66b0bc93b1edc09a6ff66c2e0ae0f2848d90be7',
+ 'v8_revision': '41ff48bd620584b425618e7f8b51617c46c4d67f',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling zlib
# and whatever else without interference from each other.
- 'zlib_revision': 'b890619bc2b193b8fbe9c1c053f4cd19a9791d92',
+ 'zlib_revision': '526382e41c9c5275dc329db4328b54e4f344a204',
}
# Only these hosts are allowed for dependencies in this DEPS file.
@@ -224,6 +240,18 @@ deps = {
'condition': 'host_os == "mac"',
},
+ 'buildtools/reclient': {
+ 'packages': [
+ {
+ 'package': Var('reclient_package') + '${{platform}}',
+ 'version': Var('reclient_version'),
+ }
+ ],
+ 'dep_type': 'cipd',
+ },
+
+ # TODO(chromium:1458042): Remove these paths, when chromium builds files
+ # have moved to third_party/lib*/src paths.
'buildtools/third_party/libc++/trunk':
Var('chromium_git') +
'/external/github.com/llvm/llvm-project/libcxx.git@' +
@@ -259,10 +287,15 @@ deps = {
Var('chromium_git') + '/chromium/src/third_party/abseil-cpp.git@' +
Var('abseil_revision'),
- 'third_party/android_ndk': {
- 'url': Var('chromium_git') + '/android_ndk.git@' +
- Var('android_ndk_revision'),
- 'condition': 'checkout_android',
+ 'third_party/android_toolchain': {
+ 'packages': [
+ {
+ 'package': 'chromium/third_party/android_toolchain/android_toolchain',
+ 'version': Var('android_toolchain_version'),
+ },
+ ],
+ 'condition': 'checkout_android_native_support',
+ 'dep_type': 'cipd',
},
'third_party/catapult': {
@@ -270,6 +303,13 @@ deps = {
'condition': 'checkout_android',
},
+ 'third_party/cpu_features/src': {
+ 'url': Var('chromium_git') +
+ '/external/github.com/google/cpu_features.git@' +
+ Var('cpu_features_revision'),
+ 'condition': 'checkout_android',
+ },
+
'third_party/depot_tools':
Var('chromium_git') + '/chromium/tools/depot_tools.git@' +
Var('depot_tools_revision'),
@@ -278,15 +318,11 @@ deps = {
Var('chromium_git') + '/chromium/src/third_party/freetype2.git@' +
Var('freetype_revision'),
- 'third_party/fuchsia-sdk/sdk': {
- 'packages': [
- {
- 'package': Var('fuchsia_sdk_cipd_prefix') + '${{platform}}',
- 'version': Var('fuchsia_version'),
- },
- ],
- 'condition': 'checkout_fuchsia',
- 'dep_type': 'cipd',
+ 'third_party/fuchsia-gn-sdk': {
+ 'url': Var('chromium_git') +
+ '/chromium/src/third_party/fuchsia-gn-sdk.git@' +
+ Var('fuchsia_gn_sdk_revision'),
+ 'condition': 'checkout_fuchsia',
},
'third_party/googletest/src':
@@ -305,6 +341,21 @@ deps = {
Var('chromium_git') + '/chromium/src/third_party/jinja2.git@' +
Var('jinja2_revision'),
+ 'third_party/libc++/src':
+ Var('chromium_git') +
+ '/external/github.com/llvm/llvm-project/libcxx.git@' +
+ Var('libcxx_revision'),
+
+ 'third_party/libc++abi/src':
+ Var('chromium_git') +
+ '/external/github.com/llvm/llvm-project/libcxxabi.git@' +
+ Var('libcxxabi_revision'),
+
+ 'third_party/libunwind/src':
+ Var('chromium_git') +
+ '/external/github.com/llvm/llvm-project/libunwind.git@' +
+ Var('libunwind_revision'),
+
'third_party/libjpeg_turbo':
Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git@' +
Var('jpeg_turbo_revision'),
@@ -313,11 +364,6 @@ deps = {
Var('chromium_git') + '/chromium/src/third_party/libpng.git@' +
Var('libpng_revision'),
- 'third_party/lss': {
- 'url': Var('chromium_git') + '/linux-syscall-support.git' + '@' + Var('lss_revision'),
- 'condition': 'checkout_android or checkout_linux',
- },
-
'third_party/markupsafe':
Var('chromium_git') + '/chromium/src/third_party/markupsafe.git@' +
Var('markupsafe_revision'),
@@ -651,4 +697,32 @@ hooks = [
'action': ['python3', 'build/util/lastchange.py',
'-o', 'build/util/LASTCHANGE'],
},
+ {
+ 'name': 'Download Fuchsia SDK from GCS',
+ 'pattern': '.',
+ 'condition': 'checkout_fuchsia',
+ 'action': [
+ 'python3',
+ 'build/fuchsia/update_sdk.py',
+ '--cipd-prefix={fuchsia_sdk_cipd_prefix}',
+ '--version={fuchsia_version}',
+ ],
+ },
+ # Download remote exec cfg files
+ {
+ 'name': 'fetch_reclient_cfgs',
+ 'pattern': '.',
+ 'condition': 'download_remoteexec_cfg',
+ 'action': ['python3',
+ 'buildtools/reclient_cfgs/fetch_reclient_cfgs.py',
+ '--rbe_instance',
+ Var('rbe_instance'),
+ '--reproxy_cfg_template',
+ 'reproxy.cfg.template',
+ '--rewrapper_cfg_project',
+ Var('rewrapper_cfg_project'),
+ '--quiet',
+ '--hook',
+ ],
+ },
]
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 236f8964e..14c050683 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -428,12 +428,12 @@ def _CheckPngNames(input_api, output_api):
"""Checks that .png files have the right file name format, which must be in
the form:
- NAME_expected(_(agg|skia))?(_(linux|mac|win))?.pdf.\d+.png
+ NAME_expected(_(agg|gdi|skia))?(_(linux|mac|win))?.pdf.\d+.png
This must be the same format as the one in testing/corpus's PRESUBMIT.py.
"""
expected_pattern = input_api.re.compile(
- r'.+_expected(_(agg|skia))?(_(linux|mac|win))?\.pdf\.\d+.png')
+ r'.+_expected(_(agg|gdi|skia))?(_(linux|mac|win))?\.pdf\.\d+.png')
results = []
for f in input_api.AffectedFiles(include_deletes=False):
if not f.LocalPath().endswith('.png'):
diff --git a/README.md b/README.md
index 657cfda9b..d867e4cce 100644
--- a/README.md
+++ b/README.md
@@ -78,7 +78,7 @@ support code only works if one follows this convention.
A typical `<directory>` name is `out/Debug`.
```
-use_goma = true # Googlers only. Make sure goma is installed and running first.
+use_goma = false # Googlers only. Ensure goma is installed and running first.
is_debug = true # Enable debugging features.
# Set true to enable experimental Skia backend.
@@ -95,6 +95,11 @@ For sample applications like `pdfium_test` to build, one must set
By default, the entire project builds with C++17.
+By default, PDFium expects to build with a clang compiler that provides
+additional chrome plugins. To build against a vanilla one lacking these,
+one must set
+`clang_use_chrome_plugins = false`.
+
When complete the arguments will be stored in `<directory>/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
diff --git a/build_overrides/BUILDCONFIG.gn b/build_overrides/BUILDCONFIG.gn
index 2b9bbd611..d5ced94b9 100644
--- a/build_overrides/BUILDCONFIG.gn
+++ b/build_overrides/BUILDCONFIG.gn
@@ -369,6 +369,10 @@ if (is_win) {
]
}
+if (is_apple) {
+ default_compiler_configs += [ "//build/config/compiler:enable_arc2" ]
+}
+
if (is_posix) {
if (current_os != "aix") {
default_compiler_configs +=
diff --git a/build_overrides/build.gni b/build_overrides/build.gni
index 446fa8989..b10e6811e 100644
--- a/build_overrides/build.gni
+++ b/build_overrides/build.gni
@@ -6,11 +6,6 @@
# Chromium specific targets in a client project's GN file etc.
build_with_chromium = false
-# Support different NDK locations in non-Chromium builds.
-default_android_ndk_root = "//third_party/android_ndk"
-default_android_ndk_version = "r16"
-default_android_ndk_major_version = 16
-
# PDFium builds don't support building java targets.
enable_java_templates = false
diff --git a/build_overrides/partition_alloc.gni b/build_overrides/partition_alloc.gni
index 0cf700902..56f913c7f 100644
--- a/build_overrides/partition_alloc.gni
+++ b/build_overrides/partition_alloc.gni
@@ -2,10 +2,20 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/config/sanitizers/sanitizers.gni")
+
+# Sanitizers replace the allocator, don't use our own allocator.
+_is_using_sanitizers = is_asan || is_hwasan || is_lsan || is_tsan || is_msan
+
+# The allocator shim isn't working standalone on Windows at the moment.
+# TODO(https://crbug.com/pdfium/2068) - make work with windows.
+_use_shim = !_is_using_sanitizers && !is_win
+
# See base/allocator/partition_allocator/external_builds.md
-use_partition_alloc_as_malloc_default = false
+use_allocator_shim_default = _use_shim
+use_partition_alloc_as_malloc_default = _use_shim
+enable_backup_ref_ptr_support_default = _use_shim
enable_mte_checked_ptr_support_default = false
-enable_backup_ref_ptr_support_default = false
put_ref_count_in_previous_slot_default = false
enable_backup_ref_ptr_slow_checks_default = false
enable_dangling_raw_ptr_checks_default = false
diff --git a/core/fdrm/fx_crypt.h b/core/fdrm/fx_crypt.h
index f3171c7c0..511972f5f 100644
--- a/core/fdrm/fx_crypt.h
+++ b/core/fdrm/fx_crypt.h
@@ -9,7 +9,7 @@
#include <stdint.h>
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
struct CRYPT_rc4_context {
static constexpr int32_t kPermutationLength = 256;
diff --git a/core/fpdfapi/cmaps/fpdf_cmaps.h b/core/fpdfapi/cmaps/fpdf_cmaps.h
index 079459a2d..795427f33 100644
--- a/core/fpdfapi/cmaps/fpdf_cmaps.h
+++ b/core/fpdfapi/cmaps/fpdf_cmaps.h
@@ -9,6 +9,8 @@
#include <stdint.h>
+#include "core/fxcrt/unowned_ptr_exclusion.h"
+
namespace fxcmap {
struct DWordCIDMap {
@@ -21,9 +23,9 @@ struct DWordCIDMap {
struct CMap {
enum class Type : bool { kSingle, kRange };
- const char* m_Name; // Raw, POD struct.
- const uint16_t* m_pWordMap; // Raw, POD struct.
- const DWordCIDMap* m_pDWordMap; // Raw, POD struct.
+ UNOWNED_PTR_EXCLUSION const char* m_Name; // POD struct.
+ UNOWNED_PTR_EXCLUSION const uint16_t* m_pWordMap; // POD struct.
+ UNOWNED_PTR_EXCLUSION const DWordCIDMap* m_pDWordMap; // POD struct.
uint16_t m_WordCount;
uint16_t m_DWordCount;
Type m_WordMapType;
diff --git a/core/fpdfapi/edit/BUILD.gn b/core/fpdfapi/edit/BUILD.gn
index 721dff809..f6af621d5 100644
--- a/core/fpdfapi/edit/BUILD.gn
+++ b/core/fpdfapi/edit/BUILD.gn
@@ -24,7 +24,6 @@ source_set("edit") {
]
deps = [
"../../../constants",
- "../../../third_party:skia_shared",
"../../fxcrt",
"../font",
"../page",
diff --git a/core/fpdfapi/edit/DEPS b/core/fpdfapi/edit/DEPS
deleted file mode 100644
index bcfd0a220..000000000
--- a/core/fpdfapi/edit/DEPS
+++ /dev/null
@@ -1,5 +0,0 @@
-specific_include_rules = {
- "cpdf_contentstream_write_utils.cpp": [
- '+third_party/skia_shared',
- ]
-}
diff --git a/core/fpdfapi/edit/cpdf_contentstream_write_utils.cpp b/core/fpdfapi/edit/cpdf_contentstream_write_utils.cpp
index af6a16931..d1fede99d 100644
--- a/core/fpdfapi/edit/cpdf_contentstream_write_utils.cpp
+++ b/core/fpdfapi/edit/cpdf_contentstream_write_utils.cpp
@@ -4,13 +4,220 @@
#include "core/fpdfapi/edit/cpdf_contentstream_write_utils.h"
+#include <cassert>
+#include <cfloat>
+#include <climits>
+#include <cmath>
#include <ostream>
-#include "third_party/skia_shared/SkFloatToDecimal.h"
+namespace {
+
+constexpr unsigned kMaximumSkFloatToDecimalLength = 49;
+
+// Return pow(10.0, e), optimized for common cases.
+double pow10(int e) {
+ switch (e) {
+ case 0:
+ return 1.0; // common cases
+ case 1:
+ return 10.0;
+ case 2:
+ return 100.0;
+ case 3:
+ return 1e+03;
+ case 4:
+ return 1e+04;
+ case 5:
+ return 1e+05;
+ case 6:
+ return 1e+06;
+ case 7:
+ return 1e+07;
+ case 8:
+ return 1e+08;
+ case 9:
+ return 1e+09;
+ case 10:
+ return 1e+10;
+ case 11:
+ return 1e+11;
+ case 12:
+ return 1e+12;
+ case 13:
+ return 1e+13;
+ case 14:
+ return 1e+14;
+ case 15:
+ return 1e+15;
+ default:
+ if (e > 15) {
+ double value = 1e+15;
+ while (e-- > 15) {
+ value *= 10.0;
+ }
+ return value;
+ } else {
+ assert(e < 0);
+ double value = 1.0;
+ while (e++ < 0) {
+ value /= 10.0;
+ }
+ return value;
+ }
+ }
+}
+
+// SkFloatToDecimal
+//
+// Convert a float into a decimal string.
+//
+// The resulting string will be in the form `[-]?([0-9]*\.)?[0-9]+` (It does
+// not use scientific notation.) and `sscanf(output, "%f", &x)` will return
+// the original value if the value is finite. This function accepts all
+// possible input values.
+//
+// INFINITY and -INFINITY are rounded to FLT_MAX and -FLT_MAX.
+//
+// NAN values are converted to 0.
+//
+// This function will always add a terminating '\0' to the output.
+//
+// @param value Any floating-point number
+// @param output The buffer to write the string into. Must be non-null.
+//
+// @return strlen(output)
+//
+// Write a string into output, including a terminating '\0' (for
+// unit testing). Return strlen(output) (for SkWStream::write) The
+// resulting string will be in the form /[-]?([0-9]*.)?[0-9]+/ and
+// sscanf(output, "%f", &x) will return the original value iff the
+// value is finite. This function accepts all possible input values.
+//
+// Motivation: "PDF does not support [numbers] in exponential format
+// (such as 6.02e23)." Otherwise, this function would rely on a
+// sprintf-type function from the standard library.
+unsigned SkFloatToDecimal(float value,
+ char output[kMaximumSkFloatToDecimalLength]) {
+ // The longest result is -FLT_MIN.
+ // We serialize it as "-.0000000000000000000000000000000000000117549435"
+ // which has 48 characters plus a terminating '\0'.
+
+ static_assert(kMaximumSkFloatToDecimalLength == 49, "");
+ // 3 = '-', '.', and '\0' characters.
+ // 9 = number of significant digits
+ // abs(FLT_MIN_10_EXP) = number of zeros in FLT_MIN
+ static_assert(kMaximumSkFloatToDecimalLength == 3 + 9 - FLT_MIN_10_EXP, "");
+
+ // section C.1 of the PDF 1.4 spec (http://goo.gl/0SCswJ) says that
+ // most PDF rasterizers will use fixed-point scalars that lack the
+ // dynamic range of floats. Even if this is the case, I want to
+ // serialize these (uncommon) very small and very large scalar
+ // values with enough precision to allow a floating-point
+ // rasterizer to read them in with perfect accuracy.
+ // Experimentally, rasterizers such as pdfium do seem to benefit
+ // from this. Rasterizers that rely on fixed-point scalars should
+ // gracefully ignore these values that they can not parse.
+ char* output_ptr = &output[0];
+ const char* const end = &output[kMaximumSkFloatToDecimalLength - 1];
+ // subtract one to leave space for '\0'.
+
+ // This function is written to accept any possible input value,
+ // including non-finite values such as INF and NAN. In that case,
+ // we ignore value-correctness and output a syntacticly-valid
+ // number.
+ if (value == INFINITY) {
+ value = FLT_MAX; // nearest finite float.
+ }
+ if (value == -INFINITY) {
+ value = -FLT_MAX; // nearest finite float.
+ }
+ if (!std::isfinite(value) || value == 0.0f) {
+ // NAN is unsupported in PDF. Always output a valid number.
+ // Also catch zero here, as a special case.
+ *output_ptr++ = '0';
+ *output_ptr = '\0';
+ return static_cast<unsigned>(output_ptr - output);
+ }
+ if (value < 0.0) {
+ *output_ptr++ = '-';
+ value = -value;
+ }
+ assert(value >= 0.0f);
+
+ int binaryExponent;
+ (void)std::frexp(value, &binaryExponent);
+ static const double kLog2 = 0.3010299956639812; // log10(2.0);
+ int decimalExponent = static_cast<int>(std::floor(kLog2 * binaryExponent));
+ int decimalShift = decimalExponent - 8;
+ double power = pow10(-decimalShift);
+ assert(value * power <= (double)INT_MAX);
+ int d = static_cast<int>(value * power + 0.5);
+ // assert(value == (float)(d * pow(10.0, decimalShift)));
+ assert(d <= 999999999);
+ if (d > 167772159) { // floor(pow(10,1+log10(1<<24)))
+ // need one fewer decimal digits for 24-bit precision.
+ decimalShift = decimalExponent - 7;
+ // assert(power * 0.1 = pow10(-decimalShift));
+ // recalculate to get rounding right.
+ d = static_cast<int>(value * (power * 0.1) + 0.5);
+ assert(d <= 99999999);
+ }
+ while (d % 10 == 0) {
+ d /= 10;
+ ++decimalShift;
+ }
+ assert(d > 0);
+ // assert(value == (float)(d * pow(10.0, decimalShift)));
+ unsigned char buffer[9]; // decimal value buffer.
+ int bufferIndex = 0;
+ do {
+ buffer[bufferIndex++] = d % 10;
+ d /= 10;
+ } while (d != 0);
+ assert(bufferIndex <= (int)sizeof(buffer) && bufferIndex > 0);
+ if (decimalShift >= 0) {
+ do {
+ --bufferIndex;
+ *output_ptr++ = '0' + buffer[bufferIndex];
+ } while (bufferIndex);
+ for (int i = 0; i < decimalShift; ++i) {
+ *output_ptr++ = '0';
+ }
+ } else {
+ int placesBeforeDecimal = bufferIndex + decimalShift;
+ if (placesBeforeDecimal > 0) {
+ while (placesBeforeDecimal-- > 0) {
+ --bufferIndex;
+ *output_ptr++ = '0' + buffer[bufferIndex];
+ }
+ *output_ptr++ = '.';
+ } else {
+ *output_ptr++ = '.';
+ int placesAfterDecimal = -placesBeforeDecimal;
+ while (placesAfterDecimal-- > 0) {
+ *output_ptr++ = '0';
+ }
+ }
+ while (bufferIndex > 0) {
+ --bufferIndex;
+ *output_ptr++ = '0' + buffer[bufferIndex];
+ if (output_ptr == end) {
+ break; // denormalized: don't need extra precision.
+ // Note: denormalized numbers will not have the same number of
+ // significantDigits, but do not need them to round-trip.
+ }
+ }
+ }
+ assert(output_ptr <= end);
+ *output_ptr = '\0';
+ return static_cast<unsigned>(output_ptr - output);
+}
+
+} // namespace
std::ostream& WriteFloat(std::ostream& stream, float value) {
- char buffer[pdfium::skia::kMaximumSkFloatToDecimalLength];
- unsigned size = pdfium::skia::SkFloatToDecimal(value, buffer);
+ char buffer[kMaximumSkFloatToDecimalLength];
+ unsigned size = SkFloatToDecimal(value, buffer);
stream.write(buffer, size);
return stream;
}
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
index 871702843..be87afaea 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
@@ -41,9 +41,9 @@
#include "core/fpdfapi/parser/object_tree_traversal_util.h"
#include "third_party/base/check.h"
#include "third_party/base/containers/contains.h"
+#include "third_party/base/containers/span.h"
#include "third_party/base/notreached.h"
#include "third_party/base/numerics/safe_conversions.h"
-#include "third_party/base/span.h"
namespace {
@@ -81,10 +81,9 @@ void RecordPageObjectResourceUsage(const CPDF_PageObject* page_object,
break;
}
}
- const ByteString& graphics_resource_name =
- page_object->GetGraphicsResourceName();
- if (!graphics_resource_name.IsEmpty()) {
- seen_resources["ExtGState"].insert(graphics_resource_name);
+ for (const auto& name : page_object->GetGraphicsResourceNames()) {
+ CHECK(!name.IsEmpty());
+ seen_resources["ExtGState"].insert(name);
}
}
@@ -362,9 +361,8 @@ const CPDF_ContentMarks* CPDF_PageContentGenerator::ProcessContentMarks(
*buf << "/" << item->GetPropertyName() << " ";
break;
}
- default:
- NOTREACHED();
- break;
+ case CPDF_ContentMarkItem::kNone:
+ NOTREACHED_NORETURN();
}
// Write BDC (begin dictionary content) operator.
@@ -548,6 +546,18 @@ void CPDF_PageContentGenerator::ProcessGraphics(fxcrt::ostringstream* buf,
CFX_GraphStateData::LineJoin lineJoin = pPageObj->m_GraphState.GetLineJoin();
if (lineJoin != CFX_GraphStateData::LineJoin::kMiter)
*buf << static_cast<int>(lineJoin) << " j ";
+ std::vector<float> dash_array = pPageObj->m_GraphState.GetLineDashArray();
+ if (dash_array.size()) {
+ *buf << "[";
+ for (size_t i = 0; i < dash_array.size(); ++i) {
+ if (i > 0) {
+ *buf << " ";
+ }
+ WriteFloat(*buf, dash_array[i]);
+ }
+ *buf << "] ";
+ WriteFloat(*buf, pPageObj->m_GraphState.GetLineDashPhase()) << " d ";
+ }
const CPDF_ClipPath& clip_path = pPageObj->m_ClipPath;
if (clip_path.HasRef()) {
@@ -562,8 +572,7 @@ void CPDF_PageContentGenerator::ProcessGraphics(fxcrt::ostringstream* buf,
*buf << " W* ";
break;
case CFX_FillRenderOptions::FillType::kNoFill:
- NOTREACHED();
- break;
+ NOTREACHED_NORETURN();
}
// Use a no-op path-painting operator to terminate the path without
@@ -600,7 +609,7 @@ void CPDF_PageContentGenerator::ProcessGraphics(fxcrt::ostringstream* buf,
}
m_pDocument->AddIndirectObject(gsDict);
name = RealizeResource(std::move(gsDict), "ExtGState");
- pPageObj->SetGraphicsResourceName(name);
+ pPageObj->SetGraphicsResourceNames({name});
m_pObjHolder->GraphicsMapInsert(graphD, name);
}
*buf << "/" << PDF_NameEncode(name) << " gs ";
diff --git a/core/fpdfapi/edit/cpdf_stringarchivestream.cpp b/core/fpdfapi/edit/cpdf_stringarchivestream.cpp
index 4d9f7f2aa..48033b0ee 100644
--- a/core/fpdfapi/edit/cpdf_stringarchivestream.cpp
+++ b/core/fpdfapi/edit/cpdf_stringarchivestream.cpp
@@ -14,8 +14,7 @@ CPDF_StringArchiveStream::CPDF_StringArchiveStream(fxcrt::ostringstream* stream)
CPDF_StringArchiveStream::~CPDF_StringArchiveStream() = default;
FX_FILESIZE CPDF_StringArchiveStream::CurrentOffset() const {
- NOTREACHED();
- return false;
+ NOTREACHED_NORETURN();
}
bool CPDF_StringArchiveStream::WriteBlock(pdfium::span<const uint8_t> buffer) {
diff --git a/core/fpdfapi/edit/cpdf_stringarchivestream.h b/core/fpdfapi/edit/cpdf_stringarchivestream.h
index 130634390..3907e2c4a 100644
--- a/core/fpdfapi/edit/cpdf_stringarchivestream.h
+++ b/core/fpdfapi/edit/cpdf_stringarchivestream.h
@@ -7,6 +7,7 @@
#include "core/fxcrt/fx_stream.h"
#include "core/fxcrt/fx_string_wrappers.h"
+#include "core/fxcrt/unowned_ptr.h"
class CPDF_StringArchiveStream final : public IFX_ArchiveStream {
public:
@@ -18,7 +19,7 @@ class CPDF_StringArchiveStream final : public IFX_ArchiveStream {
FX_FILESIZE CurrentOffset() const override;
private:
- fxcrt::ostringstream* stream_;
+ UnownedPtr<fxcrt::ostringstream> stream_;
};
#endif // CORE_FPDFAPI_EDIT_CPDF_STRINGARCHIVESTREAM_H_
diff --git a/core/fpdfapi/font/cfx_cttgsubtable.cpp b/core/fpdfapi/font/cfx_cttgsubtable.cpp
index ae5a84126..c19649e56 100644
--- a/core/fpdfapi/font/cfx_cttgsubtable.cpp
+++ b/core/fpdfapi/font/cfx_cttgsubtable.cpp
@@ -27,44 +27,53 @@ bool IsVerticalFeatureTag(uint32_t tag) {
} // namespace
-CFX_CTTGSUBTable::CFX_CTTGSUBTable(FT_Bytes gsub) {
+CFX_CTTGSUBTable::CFX_CTTGSUBTable(pdfium::span<const uint8_t> gsub) {
if (!LoadGSUBTable(gsub))
return;
- for (const TScriptRecord& script : ScriptList) {
- for (const auto& record : script.LangSysRecords) {
- for (uint16_t index : record.FeatureIndices) {
- if (IsVerticalFeatureTag(FeatureList[index].FeatureTag))
- m_featureSet.insert(index);
+ for (const auto& script : script_list_) {
+ for (const auto& record : script) {
+ for (uint16_t index : record) {
+ if (IsVerticalFeatureTag(feature_list_[index].feature_tag)) {
+ feature_set_.insert(index);
+ }
}
}
}
- if (!m_featureSet.empty())
+ if (!feature_set_.empty()) {
return;
+ }
int i = 0;
- for (const TFeatureRecord& feature : FeatureList) {
- if (IsVerticalFeatureTag(feature.FeatureTag))
- m_featureSet.insert(i);
+ for (const FeatureRecord& feature : feature_list_) {
+ if (IsVerticalFeatureTag(feature.feature_tag)) {
+ feature_set_.insert(i);
+ }
++i;
}
}
CFX_CTTGSUBTable::~CFX_CTTGSUBTable() = default;
-bool CFX_CTTGSUBTable::LoadGSUBTable(FT_Bytes gsub) {
+bool CFX_CTTGSUBTable::LoadGSUBTable(pdfium::span<const uint8_t> gsub) {
if (FXSYS_UINT32_GET_MSBFIRST(gsub) != 0x00010000)
return false;
- return Parse(&gsub[FXSYS_UINT16_GET_MSBFIRST(gsub + 4)],
- &gsub[FXSYS_UINT16_GET_MSBFIRST(gsub + 6)],
- &gsub[FXSYS_UINT16_GET_MSBFIRST(gsub + 8)]);
+ auto scriptlist_span = gsub.subspan(4, 2);
+ auto featurelist_span = gsub.subspan(6, 2);
+ auto lookuplist_span = gsub.subspan(8, 2);
+ size_t scriptlist_index = FXSYS_UINT16_GET_MSBFIRST(scriptlist_span);
+ size_t featurelist_index = FXSYS_UINT16_GET_MSBFIRST(featurelist_span);
+ size_t lookuplist_index = FXSYS_UINT16_GET_MSBFIRST(lookuplist_span);
+ Parse(gsub.subspan(scriptlist_index), gsub.subspan(featurelist_index),
+ gsub.subspan(lookuplist_index));
+ return true;
}
uint32_t CFX_CTTGSUBTable::GetVerticalGlyph(uint32_t glyphnum) const {
- for (uint32_t item : m_featureSet) {
+ for (uint32_t item : feature_set_) {
absl::optional<uint32_t> result =
- GetVerticalGlyphSub(FeatureList[item], glyphnum);
+ GetVerticalGlyphSub(feature_list_[item], glyphnum);
if (result.has_value())
return result.value();
}
@@ -72,15 +81,17 @@ uint32_t CFX_CTTGSUBTable::GetVerticalGlyph(uint32_t glyphnum) const {
}
absl::optional<uint32_t> CFX_CTTGSUBTable::GetVerticalGlyphSub(
- const TFeatureRecord& feature,
+ const FeatureRecord& feature,
uint32_t glyphnum) const {
- for (int index : feature.LookupListIndices) {
- if (!fxcrt::IndexInBounds(LookupList, index))
+ for (int index : feature.lookup_list_indices) {
+ if (!fxcrt::IndexInBounds(lookup_list_, index)) {
continue;
- if (LookupList[index].LookupType != 1)
+ }
+ if (lookup_list_[index].lookup_type != 1) {
continue;
+ }
absl::optional<uint32_t> result =
- GetVerticalGlyphSub2(LookupList[index], glyphnum);
+ GetVerticalGlyphSub2(lookup_list_[index], glyphnum);
if (result.has_value())
return result.value();
}
@@ -88,272 +99,244 @@ absl::optional<uint32_t> CFX_CTTGSUBTable::GetVerticalGlyphSub(
}
absl::optional<uint32_t> CFX_CTTGSUBTable::GetVerticalGlyphSub2(
- const TLookup& lookup,
+ const Lookup& lookup,
uint32_t glyphnum) const {
- for (const auto& subTable : lookup.SubTables) {
- switch (subTable->SubstFormat) {
- case 1: {
- auto* tbl1 = static_cast<TSubTable1*>(subTable.get());
- if (GetCoverageIndex(tbl1->Coverage.get(), glyphnum) >= 0) {
- return glyphnum + tbl1->DeltaGlyphID;
- }
- break;
+ for (const auto& sub_table : lookup.sub_tables) {
+ if (absl::holds_alternative<absl::monostate>(sub_table.table_data)) {
+ continue;
+ }
+ int index = GetCoverageIndex(sub_table.coverage, glyphnum);
+ if (absl::holds_alternative<int16_t>(sub_table.table_data)) {
+ if (index >= 0) {
+ return glyphnum + absl::get<int16_t>(sub_table.table_data);
}
- case 2: {
- auto* tbl2 = static_cast<TSubTable2*>(subTable.get());
- int index = GetCoverageIndex(tbl2->Coverage.get(), glyphnum);
- if (fxcrt::IndexInBounds(tbl2->Substitutes, index)) {
- return tbl2->Substitutes[index];
- }
- break;
+ } else {
+ const auto& substitutes =
+ absl::get<DataVector<uint16_t>>(sub_table.table_data);
+ if (fxcrt::IndexInBounds(substitutes, index)) {
+ return substitutes[index];
}
}
}
return absl::nullopt;
}
-int CFX_CTTGSUBTable::GetCoverageIndex(TCoverageFormatBase* Coverage,
+int CFX_CTTGSUBTable::GetCoverageIndex(const CoverageFormat& coverage,
uint32_t g) const {
- if (!Coverage)
+ if (absl::holds_alternative<absl::monostate>(coverage)) {
return -1;
+ }
- switch (Coverage->CoverageFormat) {
- case 1: {
- int i = 0;
- TCoverageFormat1* c1 = static_cast<TCoverageFormat1*>(Coverage);
- for (const auto& glyph : c1->GlyphArray) {
- if (static_cast<uint32_t>(glyph) == g)
- return i;
- ++i;
+ if (absl::holds_alternative<DataVector<uint16_t>>(coverage)) {
+ int i = 0;
+ const auto& glyph_array = absl::get<DataVector<uint16_t>>(coverage);
+ for (const auto& glyph : glyph_array) {
+ if (static_cast<uint32_t>(glyph) == g) {
+ return i;
}
- return -1;
+ ++i;
}
- case 2: {
- TCoverageFormat2* c2 = static_cast<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;
+ }
+
+ const auto& range_records = absl::get<std::vector<RangeRecord>>(coverage);
+ for (const auto& range_rec : range_records) {
+ uint32_t s = range_rec.start;
+ uint32_t e = range_rec.end;
+ uint32_t si = range_rec.start_coverage_index;
+ if (s <= g && g <= e) {
+ return si + g - s;
}
}
return -1;
}
-uint8_t CFX_CTTGSUBTable::GetUInt8(FT_Bytes& p) const {
+uint8_t CFX_CTTGSUBTable::GetUInt8(const uint8_t*& p) const {
uint8_t ret = p[0];
p += 1;
return ret;
}
-int16_t CFX_CTTGSUBTable::GetInt16(FT_Bytes& p) const {
+int16_t CFX_CTTGSUBTable::GetInt16(const uint8_t*& p) const {
uint16_t ret = FXSYS_UINT16_GET_MSBFIRST(p);
p += 2;
- return *(int16_t*)&ret;
+ return *reinterpret_cast<int16_t*>(&ret);
}
-uint16_t CFX_CTTGSUBTable::GetUInt16(FT_Bytes& p) const {
+uint16_t CFX_CTTGSUBTable::GetUInt16(const uint8_t*& p) const {
uint16_t ret = FXSYS_UINT16_GET_MSBFIRST(p);
p += 2;
return ret;
}
-int32_t CFX_CTTGSUBTable::GetInt32(FT_Bytes& p) const {
+int32_t CFX_CTTGSUBTable::GetInt32(const uint8_t*& p) const {
uint32_t ret = FXSYS_UINT32_GET_MSBFIRST(p);
p += 4;
- return *(int32_t*)&ret;
+ return *reinterpret_cast<int32_t*>(&ret);
}
-uint32_t CFX_CTTGSUBTable::GetUInt32(FT_Bytes& p) const {
+uint32_t CFX_CTTGSUBTable::GetUInt32(const uint8_t*& p) const {
uint32_t ret = FXSYS_UINT32_GET_MSBFIRST(p);
p += 4;
return ret;
}
-bool CFX_CTTGSUBTable::Parse(FT_Bytes scriptlist,
- FT_Bytes featurelist,
- FT_Bytes lookuplist) {
+void CFX_CTTGSUBTable::Parse(pdfium::span<const uint8_t> scriptlist,
+ pdfium::span<const uint8_t> featurelist,
+ pdfium::span<const uint8_t> lookuplist) {
ParseScriptList(scriptlist);
ParseFeatureList(featurelist);
ParseLookupList(lookuplist);
- return true;
}
-void CFX_CTTGSUBTable::ParseScriptList(FT_Bytes raw) {
- FT_Bytes sp = raw;
- ScriptList = std::vector<TScriptRecord>(GetUInt16(sp));
- for (auto& scriptRec : ScriptList) {
- scriptRec.ScriptTag = GetUInt32(sp);
- ParseScript(&raw[GetUInt16(sp)], &scriptRec);
+void CFX_CTTGSUBTable::ParseScriptList(pdfium::span<const uint8_t> raw) {
+ const uint8_t* sp = raw.data();
+ script_list_ = std::vector<ScriptRecord>(GetUInt16(sp));
+ for (auto& script : script_list_) {
+ // Skip over "ScriptTag" field.
+ sp += 4;
+ script = ParseScript(&raw[GetUInt16(sp)]);
}
}
-void CFX_CTTGSUBTable::ParseScript(FT_Bytes raw, TScriptRecord* rec) {
- FT_Bytes sp = raw;
- rec->DefaultLangSys = GetUInt16(sp);
- rec->LangSysRecords = std::vector<TLangSysRecord>(GetUInt16(sp));
- for (auto& sysRecord : rec->LangSysRecords) {
- sysRecord.LangSysTag = GetUInt32(sp);
- ParseLangSys(&raw[GetUInt16(sp)], &sysRecord);
+CFX_CTTGSUBTable::ScriptRecord CFX_CTTGSUBTable::ParseScript(
+ const uint8_t* raw) {
+ // Skip over "DefaultLangSys" field.
+ const uint8_t* sp = raw + 2;
+ ScriptRecord result(GetUInt16(sp));
+ for (auto& record : result) {
+ // Skip over "LangSysTag" field.
+ sp += 4;
+ record = ParseLangSys(&raw[GetUInt16(sp)]);
}
+ return result;
}
-void CFX_CTTGSUBTable::ParseLangSys(FT_Bytes raw, TLangSysRecord* rec) {
- FT_Bytes sp = raw;
- rec->LookupOrder = GetUInt16(sp);
- rec->ReqFeatureIndex = GetUInt16(sp);
- rec->FeatureIndices = DataVector<uint16_t>(GetUInt16(sp));
- for (auto& element : rec->FeatureIndices)
+CFX_CTTGSUBTable::FeatureIndices CFX_CTTGSUBTable::ParseLangSys(
+ const uint8_t* raw) {
+ // Skip over "LookupOrder" and "ReqFeatureIndex" fields.
+ const uint8_t* sp = raw + 4;
+ FeatureIndices result(GetUInt16(sp));
+ for (auto& element : result) {
element = GetUInt16(sp);
+ }
+ return result;
}
-void CFX_CTTGSUBTable::ParseFeatureList(FT_Bytes raw) {
- FT_Bytes sp = raw;
- FeatureList = std::vector<TFeatureRecord>(GetUInt16(sp));
- for (auto& featureRec : FeatureList) {
- featureRec.FeatureTag = GetUInt32(sp);
- ParseFeature(&raw[GetUInt16(sp)], &featureRec);
+void CFX_CTTGSUBTable::ParseFeatureList(pdfium::span<const uint8_t> raw) {
+ const uint8_t* sp = raw.data();
+ feature_list_ = std::vector<FeatureRecord>(GetUInt16(sp));
+ for (auto& record : feature_list_) {
+ record.feature_tag = GetUInt32(sp);
+ record.lookup_list_indices =
+ ParseFeatureLookupListIndices(&raw[GetUInt16(sp)]);
}
}
-void CFX_CTTGSUBTable::ParseFeature(FT_Bytes raw, TFeatureRecord* rec) {
- FT_Bytes sp = raw;
- rec->FeatureParams = GetUInt16(sp);
- rec->LookupListIndices = DataVector<uint16_t>(GetUInt16(sp));
- for (auto& listIndex : rec->LookupListIndices)
- listIndex = GetUInt16(sp);
+DataVector<uint16_t> CFX_CTTGSUBTable::ParseFeatureLookupListIndices(
+ const uint8_t* raw) {
+ // Skip over "FeatureParams" field.
+ const uint8_t* sp = raw + 2;
+ DataVector<uint16_t> result(GetUInt16(sp));
+ for (auto& index : result) {
+ index = GetUInt16(sp);
+ }
+ return result;
}
-void CFX_CTTGSUBTable::ParseLookupList(FT_Bytes raw) {
- FT_Bytes sp = raw;
- LookupList = std::vector<TLookup>(GetUInt16(sp));
- for (auto& lookup : LookupList)
- ParseLookup(&raw[GetUInt16(sp)], &lookup);
+void CFX_CTTGSUBTable::ParseLookupList(pdfium::span<const uint8_t> raw) {
+ const uint8_t* sp = raw.data();
+ lookup_list_ = std::vector<Lookup>(GetUInt16(sp));
+ for (auto& lookup : lookup_list_) {
+ lookup = ParseLookup(&raw[GetUInt16(sp)]);
+ }
}
-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<std::unique_ptr<TSubTableBase>>(GetUInt16(sp));
- if (rec->LookupType != 1)
- return;
+CFX_CTTGSUBTable::Lookup CFX_CTTGSUBTable::ParseLookup(const uint8_t* raw) {
+ const uint8_t* sp = raw;
+ CFX_CTTGSUBTable::Lookup result;
+ result.lookup_type = GetUInt16(sp);
+ // Skip over "LookupFlag" field.
+ sp += 2;
+ result.sub_tables = Lookup::SubTables(GetUInt16(sp));
+ if (result.lookup_type != 1) {
+ return result;
+ }
- for (auto& subTable : rec->SubTables)
- subTable = ParseSingleSubst(&raw[GetUInt16(sp)]);
+ for (auto& sub_table : result.sub_tables) {
+ sub_table = ParseSingleSubst(&raw[GetUInt16(sp)]);
+ }
+ return result;
}
-std::unique_ptr<CFX_CTTGSUBTable::TCoverageFormatBase>
-CFX_CTTGSUBTable::ParseCoverage(FT_Bytes raw) {
- FT_Bytes sp = raw;
+CFX_CTTGSUBTable::CoverageFormat CFX_CTTGSUBTable::ParseCoverage(
+ const uint8_t* raw) {
+ const uint8_t* sp = raw;
uint16_t format = GetUInt16(sp);
- if (format == 1)
- return ParseCoverageFormat1(raw);
- if (format == 2)
- return ParseCoverageFormat2(raw);
- return nullptr;
-}
+ if (format != 1 && format != 2) {
+ return absl::monostate();
+ }
-std::unique_ptr<CFX_CTTGSUBTable::TCoverageFormat1>
-CFX_CTTGSUBTable::ParseCoverageFormat1(FT_Bytes raw) {
- FT_Bytes sp = raw;
- (void)GetUInt16(sp);
- auto rec = std::make_unique<TCoverageFormat1>(GetUInt16(sp));
- for (auto& glyph : rec->GlyphArray)
- glyph = GetUInt16(sp);
- return rec;
-}
+ if (format == 1) {
+ DataVector<uint16_t> glyph_array(GetUInt16(sp));
+ for (auto& glyph : glyph_array) {
+ glyph = GetUInt16(sp);
+ }
+ return glyph_array;
+ }
-std::unique_ptr<CFX_CTTGSUBTable::TCoverageFormat2>
-CFX_CTTGSUBTable::ParseCoverageFormat2(FT_Bytes raw) {
- FT_Bytes sp = raw;
- (void)GetUInt16(sp);
- auto rec = std::make_unique<TCoverageFormat2>(GetUInt16(sp));
- for (auto& rangeRec : rec->RangeRecords) {
- rangeRec.Start = GetUInt16(sp);
- rangeRec.End = GetUInt16(sp);
- rangeRec.StartCoverageIndex = GetUInt16(sp);
+ std::vector<RangeRecord> range_records(GetUInt16(sp));
+ for (auto& range_rec : range_records) {
+ range_rec.start = GetUInt16(sp);
+ range_rec.end = GetUInt16(sp);
+ range_rec.start_coverage_index = GetUInt16(sp);
}
- return rec;
+ return range_records;
}
-std::unique_ptr<CFX_CTTGSUBTable::TSubTableBase>
-CFX_CTTGSUBTable::ParseSingleSubst(FT_Bytes raw) {
- FT_Bytes sp = raw;
+CFX_CTTGSUBTable::SubTable CFX_CTTGSUBTable::ParseSingleSubst(
+ const uint8_t* raw) {
+ const uint8_t* sp = raw;
uint16_t format = GetUInt16(sp);
- if (format == 1)
- return ParseSingleSubstFormat1(raw);
- if (format == 2)
- return ParseSingleSubstFormat2(raw);
- return nullptr;
-}
-
-std::unique_ptr<CFX_CTTGSUBTable::TSubTable1>
-CFX_CTTGSUBTable::ParseSingleSubstFormat1(FT_Bytes raw) {
- FT_Bytes sp = raw;
- GetUInt16(sp);
- uint16_t offset = GetUInt16(sp);
- auto rec = std::make_unique<TSubTable1>();
- rec->Coverage = ParseCoverage(&raw[offset]);
- rec->DeltaGlyphID = GetInt16(sp);
- return rec;
-}
+ SubTable rec;
+ if (format != 1 && format != 2) {
+ return rec;
+ }
-std::unique_ptr<CFX_CTTGSUBTable::TSubTable2>
-CFX_CTTGSUBTable::ParseSingleSubstFormat2(FT_Bytes raw) {
- FT_Bytes sp = raw;
- (void)GetUInt16(sp);
uint16_t offset = GetUInt16(sp);
- auto rec = std::make_unique<TSubTable2>();
- rec->Coverage = ParseCoverage(&raw[offset]);
- rec->Substitutes = DataVector<uint16_t>(GetUInt16(sp));
- for (auto& substitute : rec->Substitutes)
- substitute = GetUInt16(sp);
+ rec.coverage = ParseCoverage(&raw[offset]);
+ if (format == 1) {
+ rec.table_data = GetInt16(sp);
+ } else {
+ DataVector<uint16_t> table_data(GetUInt16(sp));
+ for (auto& substitute : table_data) {
+ substitute = GetUInt16(sp);
+ }
+ rec.table_data = std::move(table_data);
+ }
return rec;
}
-CFX_CTTGSUBTable::TLangSysRecord::TLangSysRecord() = default;
-
-CFX_CTTGSUBTable::TLangSysRecord::~TLangSysRecord() = default;
-
-CFX_CTTGSUBTable::TScriptRecord::TScriptRecord() = default;
-
-CFX_CTTGSUBTable::TScriptRecord::~TScriptRecord() = default;
-
-CFX_CTTGSUBTable::TFeatureRecord::TFeatureRecord() = default;
-
-CFX_CTTGSUBTable::TFeatureRecord::~TFeatureRecord() = default;
-
-CFX_CTTGSUBTable::TRangeRecord::TRangeRecord() = default;
-
-CFX_CTTGSUBTable::TCoverageFormat1::TCoverageFormat1(size_t initial_size)
- : TCoverageFormatBase(1), GlyphArray(initial_size) {}
-
-CFX_CTTGSUBTable::TCoverageFormat1::~TCoverageFormat1() = default;
-
-CFX_CTTGSUBTable::TCoverageFormat2::TCoverageFormat2(size_t initial_size)
- : TCoverageFormatBase(2), RangeRecords(initial_size) {}
+CFX_CTTGSUBTable::FeatureRecord::FeatureRecord() = default;
-CFX_CTTGSUBTable::TCoverageFormat2::~TCoverageFormat2() = default;
+CFX_CTTGSUBTable::FeatureRecord::~FeatureRecord() = default;
-CFX_CTTGSUBTable::TDevice::TDevice() = default;
+CFX_CTTGSUBTable::RangeRecord::RangeRecord() = default;
-CFX_CTTGSUBTable::TSubTableBase::TSubTableBase(uint16_t format)
- : SubstFormat(format) {}
+CFX_CTTGSUBTable::SubTable::SubTable() = default;
-CFX_CTTGSUBTable::TSubTableBase::~TSubTableBase() = default;
+CFX_CTTGSUBTable::SubTable::SubTable(SubTable&& that) noexcept = default;
-CFX_CTTGSUBTable::TSubTable1::TSubTable1() : TSubTableBase(1) {}
+CFX_CTTGSUBTable::SubTable& CFX_CTTGSUBTable::SubTable::operator=(
+ SubTable&& that) noexcept = default;
-CFX_CTTGSUBTable::TSubTable1::~TSubTable1() = default;
+CFX_CTTGSUBTable::SubTable::~SubTable() = default;
-CFX_CTTGSUBTable::TSubTable2::TSubTable2() : TSubTableBase(2) {}
+CFX_CTTGSUBTable::Lookup::Lookup() = default;
-CFX_CTTGSUBTable::TSubTable2::~TSubTable2() = default;
+CFX_CTTGSUBTable::Lookup::Lookup(Lookup&& that) noexcept = default;
-CFX_CTTGSUBTable::TLookup::TLookup() = default;
+CFX_CTTGSUBTable::Lookup& CFX_CTTGSUBTable::Lookup::operator=(
+ Lookup&& that) noexcept = default;
-CFX_CTTGSUBTable::TLookup::~TLookup() = default;
+CFX_CTTGSUBTable::Lookup::~Lookup() = default;
diff --git a/core/fpdfapi/font/cfx_cttgsubtable.h b/core/fpdfapi/font/cfx_cttgsubtable.h
index 055533315..2a93cb91c 100644
--- a/core/fpdfapi/font/cfx_cttgsubtable.h
+++ b/core/fpdfapi/font/cfx_cttgsubtable.h
@@ -9,150 +9,105 @@
#include <stdint.h>
-#include <memory>
#include <set>
#include <vector>
#include "core/fxcrt/data_vector.h"
#include "core/fxge/freetype/fx_freetype.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
+#include "third_party/base/containers/span.h"
class CFX_CTTGSUBTable {
public:
- explicit CFX_CTTGSUBTable(FT_Bytes gsub);
+ explicit CFX_CTTGSUBTable(pdfium::span<const uint8_t> gsub);
~CFX_CTTGSUBTable();
uint32_t GetVerticalGlyph(uint32_t glyphnum) const;
private:
- struct TLangSysRecord {
- TLangSysRecord();
- ~TLangSysRecord();
-
- uint32_t LangSysTag = 0;
- uint16_t LookupOrder = 0;
- uint16_t ReqFeatureIndex = 0;
- DataVector<uint16_t> FeatureIndices;
- };
-
- struct TScriptRecord {
- TScriptRecord();
- ~TScriptRecord();
-
- uint32_t ScriptTag = 0;
- uint16_t DefaultLangSys = 0;
- std::vector<TLangSysRecord> LangSysRecords;
- };
-
- struct TFeatureRecord {
- TFeatureRecord();
- ~TFeatureRecord();
-
- uint32_t FeatureTag = 0;
- uint16_t FeatureParams = 0;
- DataVector<uint16_t> LookupListIndices;
- };
-
- struct TRangeRecord {
- TRangeRecord();
-
- uint16_t Start = 0;
- uint16_t End = 0;
- uint16_t StartCoverageIndex = 0;
- };
-
- struct TCoverageFormatBase {
- explicit TCoverageFormatBase(uint16_t format) : CoverageFormat(format) {}
- virtual ~TCoverageFormatBase() = default;
+ using FeatureIndices = DataVector<uint16_t>;
+ using ScriptRecord = std::vector<FeatureIndices>;
- const uint16_t CoverageFormat;
- };
-
- struct TCoverageFormat1 final : public TCoverageFormatBase {
- explicit TCoverageFormat1(size_t initial_size);
- ~TCoverageFormat1() override;
-
- DataVector<uint16_t> GlyphArray;
- };
-
- struct TCoverageFormat2 final : public TCoverageFormatBase {
- explicit TCoverageFormat2(size_t initial_size);
- ~TCoverageFormat2() override;
+ struct FeatureRecord {
+ FeatureRecord();
+ ~FeatureRecord();
- std::vector<TRangeRecord> RangeRecords;
+ uint32_t feature_tag = 0;
+ DataVector<uint16_t> lookup_list_indices;
};
- struct TDevice {
- TDevice();
+ struct RangeRecord {
+ RangeRecord();
- uint16_t StartSize = 0;
- uint16_t EndSize = 0;
- uint16_t DeltaFormat = 0;
+ uint16_t start = 0;
+ uint16_t end = 0;
+ uint16_t start_coverage_index = 0;
};
- struct TSubTableBase {
- explicit TSubTableBase(uint16_t format);
- virtual ~TSubTableBase();
-
- const uint16_t SubstFormat;
- std::unique_ptr<TCoverageFormatBase> Coverage;
+ // GlyphArray for format 1.
+ // RangeRecords for format 2.
+ using CoverageFormat = absl::
+ variant<absl::monostate, DataVector<uint16_t>, std::vector<RangeRecord>>;
+
+ struct SubTable {
+ SubTable();
+ SubTable(const SubTable& that) = delete;
+ SubTable& operator=(const SubTable& that) = delete;
+ SubTable(SubTable&& that) noexcept;
+ SubTable& operator=(SubTable&& that) noexcept;
+ ~SubTable();
+
+ CoverageFormat coverage;
+ // DeltaGlyphID for format 1.
+ // Substitutes for format 2.
+ absl::variant<absl::monostate, int16_t, DataVector<uint16_t>> table_data;
};
- struct TSubTable1 final : public TSubTableBase {
- TSubTable1();
- ~TSubTable1() override;
-
- int16_t DeltaGlyphID = 0;
- };
-
- struct TSubTable2 final : public TSubTableBase {
- TSubTable2();
- ~TSubTable2() override;
-
- DataVector<uint16_t> Substitutes;
- };
+ struct Lookup {
+ using SubTables = std::vector<SubTable>;
- struct TLookup {
- TLookup();
- ~TLookup();
+ Lookup();
+ Lookup(const Lookup& that) = delete;
+ Lookup& operator=(const Lookup& that) = delete;
+ Lookup(Lookup&& that) noexcept;
+ Lookup& operator=(Lookup&& that) noexcept;
+ ~Lookup();
- uint16_t LookupType = 0;
- uint16_t LookupFlag = 0;
- std::vector<std::unique_ptr<TSubTableBase>> SubTables;
+ uint16_t lookup_type = 0;
+ SubTables sub_tables;
};
- bool LoadGSUBTable(FT_Bytes gsub);
- 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<TCoverageFormatBase> ParseCoverage(FT_Bytes raw);
- std::unique_ptr<TCoverageFormat1> ParseCoverageFormat1(FT_Bytes raw);
- std::unique_ptr<TCoverageFormat2> ParseCoverageFormat2(FT_Bytes raw);
- std::unique_ptr<TSubTableBase> ParseSingleSubst(FT_Bytes raw);
- std::unique_ptr<TSubTable1> ParseSingleSubstFormat1(FT_Bytes raw);
- std::unique_ptr<TSubTable2> ParseSingleSubstFormat2(FT_Bytes raw);
-
- absl::optional<uint32_t> GetVerticalGlyphSub(const TFeatureRecord& feature,
+ bool LoadGSUBTable(pdfium::span<const uint8_t> gsub);
+ void Parse(pdfium::span<const uint8_t> scriptlist,
+ pdfium::span<const uint8_t> featurelist,
+ pdfium::span<const uint8_t> lookuplist);
+ void ParseScriptList(pdfium::span<const uint8_t> raw);
+ ScriptRecord ParseScript(const uint8_t* raw);
+ FeatureIndices ParseLangSys(const uint8_t* raw);
+ void ParseFeatureList(pdfium::span<const uint8_t> raw);
+ DataVector<uint16_t> ParseFeatureLookupListIndices(const uint8_t* raw);
+ void ParseLookupList(pdfium::span<const uint8_t> raw);
+ Lookup ParseLookup(const uint8_t* raw);
+ CoverageFormat ParseCoverage(const uint8_t* raw);
+ SubTable ParseSingleSubst(const uint8_t* raw);
+
+ absl::optional<uint32_t> GetVerticalGlyphSub(const FeatureRecord& feature,
uint32_t glyphnum) const;
- absl::optional<uint32_t> GetVerticalGlyphSub2(const TLookup& lookup,
+ absl::optional<uint32_t> GetVerticalGlyphSub2(const Lookup& lookup,
uint32_t glyphnum) const;
- 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<uint32_t> m_featureSet;
- std::vector<TScriptRecord> ScriptList;
- std::vector<TFeatureRecord> FeatureList;
- std::vector<TLookup> LookupList;
+ int GetCoverageIndex(const CoverageFormat& coverage, uint32_t g) const;
+
+ uint8_t GetUInt8(const uint8_t*& p) const;
+ int16_t GetInt16(const uint8_t*& p) const;
+ uint16_t GetUInt16(const uint8_t*& p) const;
+ int32_t GetInt32(const uint8_t*& p) const;
+ uint32_t GetUInt32(const uint8_t*& p) const;
+
+ std::set<uint32_t> feature_set_;
+ std::vector<ScriptRecord> script_list_;
+ std::vector<FeatureRecord> feature_list_;
+ std::vector<Lookup> lookup_list_;
};
#endif // CORE_FPDFAPI_FONT_CFX_CTTGSUBTABLE_H_
diff --git a/core/fpdfapi/font/cfx_stockfontarray.cpp b/core/fpdfapi/font/cfx_stockfontarray.cpp
index b6793ff3b..314252518 100644
--- a/core/fpdfapi/font/cfx_stockfontarray.cpp
+++ b/core/fpdfapi/font/cfx_stockfontarray.cpp
@@ -11,7 +11,7 @@
#include "core/fpdfapi/font/cpdf_font.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
-#include "third_party/base/notreached.h"
+#include "third_party/base/check_op.h"
CFX_StockFontArray::CFX_StockFontArray() = default;
@@ -29,10 +29,8 @@ CFX_StockFontArray::~CFX_StockFontArray() {
RetainPtr<CPDF_Font> CFX_StockFontArray::GetFont(
CFX_FontMapper::StandardFont index) const {
- if (index < std::size(m_StockFonts))
- return m_StockFonts[index];
- NOTREACHED();
- return nullptr;
+ CHECK_LT(index, std::size(m_StockFonts));
+ return m_StockFonts[index];
}
void CFX_StockFontArray::SetFont(CFX_FontMapper::StandardFont index,
diff --git a/core/fpdfapi/font/cpdf_cid2unicodemap.h b/core/fpdfapi/font/cpdf_cid2unicodemap.h
index 5c184936e..6bc5c12c3 100644
--- a/core/fpdfapi/font/cpdf_cid2unicodemap.h
+++ b/core/fpdfapi/font/cpdf_cid2unicodemap.h
@@ -8,7 +8,7 @@
#define CORE_FPDFAPI_FONT_CPDF_CID2UNICODEMAP_H_
#include "core/fpdfapi/font/cpdf_cidfont.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_CID2UnicodeMap {
public:
diff --git a/core/fpdfapi/font/cpdf_cidfont.cpp b/core/fpdfapi/font/cpdf_cidfont.cpp
index 6e0e66510..7d2d549b8 100644
--- a/core/fpdfapi/font/cpdf_cidfont.cpp
+++ b/core/fpdfapi/font/cpdf_cidfont.cpp
@@ -23,6 +23,7 @@
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fpdfapi/parser/cpdf_stream_acc.h"
+#include "core/fxcrt/fixed_uninit_data_vector.h"
#include "core/fxcrt/fx_codepage.h"
#include "core/fxcrt/fx_memory.h"
#include "core/fxcrt/fx_safe_types.h"
@@ -31,8 +32,7 @@
#include "core/fxge/fx_font.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
-#include "third_party/base/cxx17_backports.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace {
@@ -141,7 +141,7 @@ int FTPosToCBoxInt(FT_Pos pos) {
// Boundary values to avoid integer overflow when multiplied by 1000.
constexpr FT_Pos kMinCBox = -2147483;
constexpr FT_Pos kMaxCBox = 2147483;
- return static_cast<int>(pdfium::clamp(pos, kMinCBox, kMaxCBox));
+ return static_cast<int>(std::clamp(pos, kMinCBox, kMaxCBox));
}
#if !BUILDFLAG(IS_WIN)
@@ -660,18 +660,22 @@ int CPDF_CIDFont::GetGlyphIndex(uint32_t unicode, bool* pVertGlyph) {
static constexpr uint32_t kGsubTag =
CFX_FontMapper::MakeTag('G', 'S', 'U', 'B');
- if (!m_Font.GetSubData()) {
- unsigned long length = 0;
- int error = FT_Load_Sfnt_Table(face, kGsubTag, 0, nullptr, &length);
- if (!error)
- m_Font.AllocSubData(length);
+ unsigned long length = 0;
+ int error = FT_Load_Sfnt_Table(face, kGsubTag, 0, nullptr, &length);
+ if (error || !length) {
+ return index;
}
- int error =
- FT_Load_Sfnt_Table(face, kGsubTag, 0, m_Font.GetSubData(), nullptr);
- if (error || !m_Font.GetSubData())
+
+ FixedUninitDataVector<uint8_t> sub_data(length);
+ error = FT_Load_Sfnt_Table(face, kGsubTag, 0, sub_data.writable_span().data(),
+ nullptr);
+ if (error) {
return index;
+ }
- m_pTTGSUBTable = std::make_unique<CFX_CTTGSUBTable>(m_Font.GetSubData());
+ // CFX_CTTGSUBTable parses the data and stores all the values in its structs.
+ // It does not store pointers into `sub_data`.
+ m_pTTGSUBTable = std::make_unique<CFX_CTTGSUBTable>(sub_data.span());
return GetVerticalGlyph(index, pVertGlyph);
}
@@ -883,10 +887,12 @@ const uint8_t* CPDF_CIDFont::GetCIDTransform(uint16_t cid) const {
if (m_Charset != CIDSET_JAPAN1 || m_pFontFile)
return nullptr;
- const auto* pEnd = kJapan1VerticalCIDs + std::size(kJapan1VerticalCIDs);
+ const auto* pBegin = std::begin(kJapan1VerticalCIDs);
+ const auto* pEnd = std::end(kJapan1VerticalCIDs);
const auto* pTransform = std::lower_bound(
- kJapan1VerticalCIDs, pEnd, cid,
+ pBegin, pEnd, cid,
[](const CIDTransform& entry, uint16_t cid) { return entry.cid < cid; });
+
return (pTransform < pEnd && cid == pTransform->cid) ? &pTransform->a
: nullptr;
}
diff --git a/core/fpdfapi/font/cpdf_cmap.h b/core/fpdfapi/font/cpdf_cmap.h
index cc186e82b..416010a75 100644
--- a/core/fpdfapi/font/cpdf_cmap.h
+++ b/core/fpdfapi/font/cpdf_cmap.h
@@ -15,7 +15,7 @@
#include "core/fxcrt/fixed_zeroed_data_vector.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/unowned_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace fxcmap {
struct CMap;
diff --git a/core/fpdfapi/font/cpdf_font.h b/core/fpdfapi/font/cpdf_font.h
index a74cba9ac..e192a5c89 100644
--- a/core/fpdfapi/font/cpdf_font.h
+++ b/core/fpdfapi/font/cpdf_font.h
@@ -68,8 +68,6 @@ class CPDF_Font : public Retainable, public Observable {
static RetainPtr<CPDF_Font> GetStockFont(CPDF_Document* pDoc,
ByteStringView fontname);
- ~CPDF_Font() override;
-
virtual bool IsType1Font() const;
virtual bool IsTrueTypeFont() const;
virtual bool IsType3Font() const;
@@ -138,6 +136,7 @@ class CPDF_Font : public Retainable, public Observable {
protected:
CPDF_Font(CPDF_Document* pDocument, RetainPtr<CPDF_Dictionary> pFontDict);
+ ~CPDF_Font() override;
static int TT2PDF(FT_Pos m, FXFT_FaceRec* face);
diff --git a/core/fpdfapi/font/cpdf_fontglobals.cpp b/core/fpdfapi/font/cpdf_fontglobals.cpp
index 1aa19d612..aa5386dcd 100644
--- a/core/fpdfapi/font/cpdf_fontglobals.cpp
+++ b/core/fpdfapi/font/cpdf_fontglobals.cpp
@@ -50,10 +50,7 @@ CPDF_FontGlobals* CPDF_FontGlobals::GetInstance() {
return g_FontGlobals;
}
-CPDF_FontGlobals::CPDF_FontGlobals() {
- memset(m_EmbeddedCharsets, 0, sizeof(m_EmbeddedCharsets));
- memset(m_EmbeddedToUnicodes, 0, sizeof(m_EmbeddedToUnicodes));
-}
+CPDF_FontGlobals::CPDF_FontGlobals() = default;
CPDF_FontGlobals::~CPDF_FontGlobals() = default;
diff --git a/core/fpdfapi/font/cpdf_fontglobals.h b/core/fpdfapi/font/cpdf_fontglobals.h
index 6b2e3bc80..f5148a092 100644
--- a/core/fpdfapi/font/cpdf_fontglobals.h
+++ b/core/fpdfapi/font/cpdf_fontglobals.h
@@ -7,6 +7,7 @@
#ifndef CORE_FPDFAPI_FONT_CPDF_FONTGLOBALS_H_
#define CORE_FPDFAPI_FONT_CPDF_FONTGLOBALS_H_
+#include <array>
#include <functional>
#include <map>
#include <memory>
@@ -15,7 +16,7 @@
#include "core/fpdfapi/font/cpdf_cidfont.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxge/cfx_fontmapper.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_StockFontArray;
class CPDF_Font;
@@ -63,9 +64,12 @@ class CPDF_FontGlobals {
void LoadEmbeddedKorea1CMaps();
std::map<ByteString, RetainPtr<const CPDF_CMap>> m_CMaps;
- std::unique_ptr<CPDF_CID2UnicodeMap> m_CID2UnicodeMaps[CIDSET_NUM_SETS];
- pdfium::span<const fxcmap::CMap> m_EmbeddedCharsets[CIDSET_NUM_SETS];
- pdfium::span<const uint16_t> m_EmbeddedToUnicodes[CIDSET_NUM_SETS];
+ std::array<std::unique_ptr<CPDF_CID2UnicodeMap>, CIDSET_NUM_SETS>
+ m_CID2UnicodeMaps;
+ std::array<pdfium::span<const fxcmap::CMap>, CIDSET_NUM_SETS>
+ m_EmbeddedCharsets;
+ std::array<pdfium::span<const uint16_t>, CIDSET_NUM_SETS>
+ m_EmbeddedToUnicodes;
std::map<UnownedPtr<CPDF_Document>,
std::unique_ptr<CFX_StockFontArray>,
std::less<>>
diff --git a/core/fpdfapi/font/cpdf_tounicodemap.cpp b/core/fpdfapi/font/cpdf_tounicodemap.cpp
index 3c6e73ed3..2e354a213 100644
--- a/core/fpdfapi/font/cpdf_tounicodemap.cpp
+++ b/core/fpdfapi/font/cpdf_tounicodemap.cpp
@@ -13,6 +13,7 @@
#include "core/fpdfapi/font/cpdf_fontglobals.h"
#include "core/fpdfapi/parser/cpdf_simple_parser.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
+#include "core/fpdfapi/parser/fpdf_parser_utility.h"
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/fx_safe_types.h"
#include "third_party/base/containers/contains.h"
@@ -78,7 +79,28 @@ size_t CPDF_ToUnicodeMap::GetUnicodeCountByCharcodeForTesting(
}
// static
-absl::optional<uint32_t> CPDF_ToUnicodeMap::StringToCode(ByteStringView str) {
+absl::optional<uint32_t> CPDF_ToUnicodeMap::StringToCode(ByteStringView input) {
+ // Ignore whitespaces within `input`. See https://crbug.com/pdfium/2065.
+ std::set<char> seen_whitespace_chars;
+ for (char c : input) {
+ if (PDFCharIsWhitespace(c)) {
+ seen_whitespace_chars.insert(c);
+ }
+ }
+ ByteString str_without_whitespace_chars; // Must outlive `str`.
+ ByteStringView str;
+ if (seen_whitespace_chars.empty()) {
+ str = input;
+ } else {
+ str_without_whitespace_chars.Reserve(input.GetLength());
+ for (char c : input) {
+ if (!pdfium::Contains(seen_whitespace_chars, c)) {
+ str_without_whitespace_chars += c;
+ }
+ }
+ str = str_without_whitespace_chars.AsStringView();
+ }
+
size_t len = str.GetLength();
if (len <= 2 || str[0] != '<' || str[len - 1] != '>')
return absl::nullopt;
diff --git a/core/fpdfapi/font/cpdf_tounicodemap.h b/core/fpdfapi/font/cpdf_tounicodemap.h
index a074f4518..7f4ba03c5 100644
--- a/core/fpdfapi/font/cpdf_tounicodemap.h
+++ b/core/fpdfapi/font/cpdf_tounicodemap.h
@@ -34,7 +34,7 @@ class CPDF_ToUnicodeMap {
friend class cpdf_tounicodemap_StringToCode_Test;
friend class cpdf_tounicodemap_StringToWideString_Test;
- static absl::optional<uint32_t> StringToCode(ByteStringView str);
+ static absl::optional<uint32_t> StringToCode(ByteStringView input);
static WideString StringToWideString(ByteStringView str);
void Load(RetainPtr<const CPDF_Stream> pStream);
diff --git a/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp b/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp
index 86ac2b1df..7a3015de3 100644
--- a/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp
+++ b/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp
@@ -8,7 +8,7 @@
#include "core/fxcrt/retain_ptr.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
TEST(cpdf_tounicodemap, StringToCode) {
EXPECT_THAT(CPDF_ToUnicodeMap::StringToCode("<0001>"), testing::Optional(1u));
@@ -19,6 +19,14 @@ TEST(cpdf_tounicodemap, StringToCode) {
EXPECT_THAT(CPDF_ToUnicodeMap::StringToCode("<FFFFFFFF>"),
testing::Optional(4294967295u));
+ // Whitespaces within the string are ignored.
+ EXPECT_THAT(CPDF_ToUnicodeMap::StringToCode("<00\n0\r1>"),
+ testing::Optional(1u));
+ EXPECT_THAT(CPDF_ToUnicodeMap::StringToCode("<c 2>"),
+ testing::Optional(194u));
+ EXPECT_THAT(CPDF_ToUnicodeMap::StringToCode("<A2\r\n>"),
+ testing::Optional(162u));
+
// Integer overflow
EXPECT_FALSE(CPDF_ToUnicodeMap::StringToCode("<100000000>").has_value());
EXPECT_FALSE(CPDF_ToUnicodeMap::StringToCode("<1abcdFFFF>").has_value());
diff --git a/core/fpdfapi/font/cpdf_truetypefont.cpp b/core/fpdfapi/font/cpdf_truetypefont.cpp
index 0a59b54eb..f19ace9d0 100644
--- a/core/fpdfapi/font/cpdf_truetypefont.cpp
+++ b/core/fpdfapi/font/cpdf_truetypefont.cpp
@@ -11,7 +11,6 @@
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fxge/fx_font.h"
-#include "third_party/base/cxx17_backports.h"
namespace {
diff --git a/core/fpdfapi/font/cpdf_type3char.h b/core/fpdfapi/font/cpdf_type3char.h
index afa39ef26..990fb7747 100644
--- a/core/fpdfapi/font/cpdf_type3char.h
+++ b/core/fpdfapi/font/cpdf_type3char.h
@@ -14,7 +14,7 @@
#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/retain_ptr.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_DIBitmap;
diff --git a/core/fpdfapi/page/BUILD.gn b/core/fpdfapi/page/BUILD.gn
index 51b4adf14..f6bbd743b 100644
--- a/core/fpdfapi/page/BUILD.gn
+++ b/core/fpdfapi/page/BUILD.gn
@@ -108,13 +108,15 @@ source_set("page") {
"ipdf_page.h",
]
configs += [ "../../../:pdfium_strict_config" ]
+ public_deps = [
+ "../../fxge",
+ "../parser",
+ ]
deps = [
"../../../constants",
"../../fxcodec",
"../../fxcrt",
- "../../fxge",
"../font",
- "../parser",
]
allow_circular_includes_from = []
if (pdf_use_skia) {
diff --git a/core/fpdfapi/page/DEPS b/core/fpdfapi/page/DEPS
new file mode 100644
index 000000000..3dc6946b7
--- /dev/null
+++ b/core/fpdfapi/page/DEPS
@@ -0,0 +1,5 @@
+specific_include_rules = {
+ 'cpdf_pageimagecache\.cpp': [
+ '+third_party/skia/include',
+ ],
+}
diff --git a/core/fpdfapi/page/cpdf_allstates.cpp b/core/fpdfapi/page/cpdf_allstates.cpp
index a4330db1e..996b3f795 100644
--- a/core/fpdfapi/page/cpdf_allstates.cpp
+++ b/core/fpdfapi/page/cpdf_allstates.cpp
@@ -18,7 +18,6 @@
#include "core/fpdfapi/parser/fpdf_parser_utility.h"
#include "core/fxcrt/bytestring.h"
#include "core/fxge/cfx_graphstatedata.h"
-#include "third_party/base/cxx17_backports.h"
CPDF_AllStates::CPDF_AllStates() = default;
@@ -26,7 +25,7 @@ CPDF_AllStates::~CPDF_AllStates() = default;
void CPDF_AllStates::Copy(const CPDF_AllStates& src) {
CopyStates(src);
- m_GraphicsResourceName = src.m_GraphicsResourceName;
+ m_GraphicsResourceNames = src.m_GraphicsResourceNames;
m_TextMatrix = src.m_TextMatrix;
m_ParentMatrix = src.m_ParentMatrix;
m_CTM = src.m_CTM;
@@ -117,11 +116,11 @@ void CPDF_AllStates::ProcessExtGS(const CPDF_Dictionary* pGS,
}
case FXBSTR_ID('C', 'A', 0, 0):
m_GeneralState.SetStrokeAlpha(
- pdfium::clamp(pObject->GetNumber(), 0.0f, 1.0f));
+ std::clamp(pObject->GetNumber(), 0.0f, 1.0f));
break;
case FXBSTR_ID('c', 'a', 0, 0):
m_GeneralState.SetFillAlpha(
- pdfium::clamp(pObject->GetNumber(), 0.0f, 1.0f));
+ std::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 63eb52722..3d4d9a37c 100644
--- a/core/fpdfapi/page/cpdf_allstates.h
+++ b/core/fpdfapi/page/cpdf_allstates.h
@@ -7,6 +7,8 @@
#ifndef CORE_FPDFAPI_PAGE_CPDF_ALLSTATES_H_
#define CORE_FPDFAPI_PAGE_CPDF_ALLSTATES_H_
+#include <vector>
+
#include "core/fpdfapi/page/cpdf_graphicstates.h"
#include "core/fxcrt/bytestring.h"
#include "core/fxcrt/fx_coordinates.h"
@@ -25,7 +27,7 @@ class CPDF_AllStates final : public CPDF_GraphicStates {
CPDF_StreamContentParser* pParser);
void SetLineDash(const CPDF_Array* pArray, float phase, float scale);
- ByteString m_GraphicsResourceName;
+ std::vector<ByteString> m_GraphicsResourceNames;
CFX_Matrix m_TextMatrix;
CFX_Matrix m_CTM;
CFX_Matrix m_ParentMatrix;
diff --git a/core/fpdfapi/page/cpdf_color.h b/core/fpdfapi/page/cpdf_color.h
index d3e605b82..a2ba7cb53 100644
--- a/core/fpdfapi/page/cpdf_color.h
+++ b/core/fpdfapi/page/cpdf_color.h
@@ -13,7 +13,7 @@
#include <vector>
#include "core/fxcrt/retain_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_ColorSpace;
class CPDF_Pattern;
diff --git a/core/fpdfapi/page/cpdf_colorspace.cpp b/core/fpdfapi/page/cpdf_colorspace.cpp
index 9d94acd63..2a9d2f4be 100644
--- a/core/fpdfapi/page/cpdf_colorspace.cpp
+++ b/core/fpdfapi/page/cpdf_colorspace.cpp
@@ -43,7 +43,6 @@
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
#include "third_party/base/containers/contains.h"
-#include "third_party/base/cxx17_backports.h"
#include "third_party/base/notreached.h"
namespace {
@@ -373,7 +372,7 @@ class Matrix_3by3 {
};
float RGB_Conversion(float colorComponent) {
- colorComponent = pdfium::clamp(colorComponent, 0.0f, 1.0f);
+ colorComponent = std::clamp(colorComponent, 0.0f, 1.0f);
int scale = std::max(static_cast<int>(colorComponent * 1023), 0);
if (scale < 192)
return kSRGBSamples1[scale] / 255.0f;
@@ -794,7 +793,7 @@ void CPDF_LabCS::GetDefaultValue(int iComponent,
if (range_min <= range_max) {
*min = range_min;
*max = range_max;
- *value = pdfium::clamp(0.0f, *min, *max);
+ *value = std::clamp(0.0f, *min, *max);
return;
}
}
diff --git a/core/fpdfapi/page/cpdf_colorspace.h b/core/fpdfapi/page/cpdf_colorspace.h
index 23253c854..39f84ec3e 100644
--- a/core/fpdfapi/page/cpdf_colorspace.h
+++ b/core/fpdfapi/page/cpdf_colorspace.h
@@ -22,7 +22,7 @@
#include "core/fxcrt/observed_ptr.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/unowned_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_Document;
class CPDF_IndexedCS;
diff --git a/core/fpdfapi/page/cpdf_colorstate.h b/core/fpdfapi/page/cpdf_colorstate.h
index ec2de6b48..6ddae8af8 100644
--- a/core/fpdfapi/page/cpdf_colorstate.h
+++ b/core/fpdfapi/page/cpdf_colorstate.h
@@ -13,7 +13,7 @@
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/shared_copy_on_write.h"
#include "core/fxge/dib/fx_dib.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_ColorSpace;
class CPDF_Pattern;
diff --git a/core/fpdfapi/page/cpdf_contentmarkitem.cpp b/core/fpdfapi/page/cpdf_contentmarkitem.cpp
index 6b5cd6242..f68742b56 100644
--- a/core/fpdfapi/page/cpdf_contentmarkitem.cpp
+++ b/core/fpdfapi/page/cpdf_contentmarkitem.cpp
@@ -22,7 +22,6 @@ RetainPtr<const CPDF_Dictionary> CPDF_ContentMarkItem::GetParam() const {
case kDirectDict:
return m_pDirectDict;
case kNone:
- default:
return nullptr;
}
}
diff --git a/core/fpdfapi/page/cpdf_contentmarkitem.h b/core/fpdfapi/page/cpdf_contentmarkitem.h
index f418aab81..e3a041dd0 100644
--- a/core/fpdfapi/page/cpdf_contentmarkitem.h
+++ b/core/fpdfapi/page/cpdf_contentmarkitem.h
@@ -16,8 +16,7 @@ class CPDF_ContentMarkItem final : public Retainable {
public:
enum ParamType { kNone, kPropertiesDict, kDirectDict };
- explicit CPDF_ContentMarkItem(ByteString name);
- ~CPDF_ContentMarkItem() override;
+ CONSTRUCT_VIA_MAKE_RETAIN;
const ByteString& GetName() const { return m_MarkName; }
ParamType GetParamType() const { return m_ParamType; }
@@ -30,6 +29,9 @@ class CPDF_ContentMarkItem final : public Retainable {
const ByteString& property_name);
private:
+ explicit CPDF_ContentMarkItem(ByteString name);
+ ~CPDF_ContentMarkItem() override;
+
ParamType m_ParamType = kNone;
ByteString m_MarkName;
ByteString m_PropertyName;
diff --git a/core/fpdfapi/page/cpdf_contentmarks.h b/core/fpdfapi/page/cpdf_contentmarks.h
index 95eaeea57..ef3ebd6c7 100644
--- a/core/fpdfapi/page/cpdf_contentmarks.h
+++ b/core/fpdfapi/page/cpdf_contentmarks.h
@@ -42,9 +42,7 @@ class CPDF_ContentMarks {
private:
class MarkData final : public Retainable {
public:
- MarkData();
- MarkData(const MarkData& src);
- ~MarkData() override;
+ CONSTRUCT_VIA_MAKE_RETAIN;
size_t CountItems() const;
bool ContainsItem(const CPDF_ContentMarkItem* pItem) const;
@@ -61,6 +59,10 @@ class CPDF_ContentMarks {
bool RemoveMark(CPDF_ContentMarkItem* pMarkItem);
private:
+ MarkData();
+ MarkData(const MarkData& src);
+ ~MarkData() override;
+
std::vector<RetainPtr<CPDF_ContentMarkItem>> m_Marks;
};
diff --git a/core/fpdfapi/page/cpdf_contentparser.cpp b/core/fpdfapi/page/cpdf_contentparser.cpp
index 5ef9d80d1..1fbcb0bf5 100644
--- a/core/fpdfapi/page/cpdf_contentparser.cpp
+++ b/core/fpdfapi/page/cpdf_contentparser.cpp
@@ -56,12 +56,13 @@ CPDF_ContentParser::CPDF_ContentParser(CPDF_Page* pPage)
HandlePageContentFailure();
}
-CPDF_ContentParser::CPDF_ContentParser(RetainPtr<const CPDF_Stream> pStream,
- CPDF_PageObjectHolder* pPageObjectHolder,
- const CPDF_AllStates* pGraphicStates,
- const CFX_Matrix* pParentMatrix,
- CPDF_Type3Char* pType3Char,
- std::set<const uint8_t*>* pParsedSet)
+CPDF_ContentParser::CPDF_ContentParser(
+ RetainPtr<const CPDF_Stream> pStream,
+ CPDF_PageObjectHolder* pPageObjectHolder,
+ const CPDF_AllStates* pGraphicStates,
+ const CFX_Matrix* pParentMatrix,
+ CPDF_Type3Char* pType3Char,
+ CPDF_Form::RecursionState* recursion_state)
: m_CurrentStage(Stage::kParse),
m_pPageObjectHolder(pPageObjectHolder),
m_pType3Char(pType3Char) {
@@ -95,7 +96,7 @@ CPDF_ContentParser::CPDF_ContentParser(RetainPtr<const CPDF_Stream> pStream,
m_pPageObjectHolder->GetMutablePageResources(),
m_pPageObjectHolder->GetMutableResources(), pParentMatrix,
m_pPageObjectHolder, std::move(pResources), form_bbox, pGraphicStates,
- pParsedSet);
+ recursion_state);
m_pParser->GetCurStates()->m_CTM = form_matrix;
m_pParser->GetCurStates()->m_ParentMatrix = form_matrix;
if (ClipPath.HasRef()) {
@@ -197,12 +198,13 @@ CPDF_ContentParser::Stage CPDF_ContentParser::PrepareContent() {
CPDF_ContentParser::Stage CPDF_ContentParser::Parse() {
if (!m_pParser) {
- m_ParsedSet.clear();
+ m_RecursionState.parsed_set.clear();
+ m_RecursionState.form_count = 0;
m_pParser = std::make_unique<CPDF_StreamContentParser>(
m_pPageObjectHolder->GetDocument(),
m_pPageObjectHolder->GetMutablePageResources(), nullptr, nullptr,
m_pPageObjectHolder, m_pPageObjectHolder->GetMutableResources(),
- m_pPageObjectHolder->GetBBox(), nullptr, &m_ParsedSet);
+ m_pPageObjectHolder->GetBBox(), nullptr, &m_RecursionState);
m_pParser->GetCurStates()->m_ColorState.SetDefault();
}
if (m_CurrentOffset >= GetData().size())
diff --git a/core/fpdfapi/page/cpdf_contentparser.h b/core/fpdfapi/page/cpdf_contentparser.h
index 090c6240a..e2660e22f 100644
--- a/core/fpdfapi/page/cpdf_contentparser.h
+++ b/core/fpdfapi/page/cpdf_contentparser.h
@@ -10,9 +10,9 @@
#include <stdint.h>
#include <memory>
-#include <set>
#include <vector>
+#include "core/fpdfapi/page/cpdf_form.h"
#include "core/fpdfapi/page/cpdf_streamcontentparser.h"
#include "core/fxcrt/fixed_try_alloc_zeroed_data_vector.h"
#include "core/fxcrt/retain_ptr.h"
@@ -36,7 +36,7 @@ class CPDF_ContentParser {
const CPDF_AllStates* pGraphicStates,
const CFX_Matrix* pParentMatrix,
CPDF_Type3Char* pType3Char,
- std::set<const uint8_t*>* pParsedSet);
+ CPDF_Form::RecursionState* recursion_state);
~CPDF_ContentParser();
const CPDF_AllStates* GetCurStates() const {
@@ -80,9 +80,10 @@ class CPDF_ContentParser {
m_Data;
uint32_t m_nStreams = 0;
uint32_t m_CurrentOffset = 0;
- std::set<const uint8_t*> m_ParsedSet; // Only used when parsing pages.
+ // Only used when parsing pages.
+ CPDF_Form::RecursionState m_RecursionState;
- // Must not outlive |m_pParsedSet|.
+ // Must not outlive |m_RecursionState|.
std::unique_ptr<CPDF_StreamContentParser> m_pParser;
};
diff --git a/core/fpdfapi/page/cpdf_devicecs.cpp b/core/fpdfapi/page/cpdf_devicecs.cpp
index 5590c5b17..0faabce89 100644
--- a/core/fpdfapi/page/cpdf_devicecs.cpp
+++ b/core/fpdfapi/page/cpdf_devicecs.cpp
@@ -16,13 +16,12 @@
#include "core/fxcodec/fx_codec.h"
#include "core/fxge/dib/cfx_cmyk_to_srgb.h"
#include "third_party/base/check.h"
-#include "third_party/base/cxx17_backports.h"
#include "third_party/base/notreached.h"
namespace {
float NormalizeChannel(float fVal) {
- return pdfium::clamp(fVal, 0.0f, 1.0f);
+ return std::clamp(fVal, 0.0f, 1.0f);
}
} // namespace
diff --git a/core/fpdfapi/page/cpdf_dib.cpp b/core/fpdfapi/page/cpdf_dib.cpp
index 29db5a4fd..30f1dcf78 100644
--- a/core/fpdfapi/page/cpdf_dib.cpp
+++ b/core/fpdfapi/page/cpdf_dib.cpp
@@ -39,8 +39,6 @@
#include "core/fxge/dib/cfx_dibitmap.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
-#include "third_party/base/cxx17_backports.h"
-#include "third_party/base/notreached.h"
namespace {
@@ -51,7 +49,7 @@ bool IsValidDimension(int value) {
unsigned int GetBits8(const uint8_t* pData, uint64_t bitpos, size_t nbits) {
DCHECK(nbits == 1 || nbits == 2 || nbits == 4 || nbits == 8 || nbits == 16);
- DCHECK_EQ((bitpos & (nbits - 1)), 0);
+ DCHECK_EQ((bitpos & (nbits - 1)), 0u);
unsigned int byte = pData[bitpos / 8];
if (nbits == 8)
return byte;
@@ -180,9 +178,6 @@ JpxDecodeAction GetJpxDecodeActionFromImageColorSpace(
case OPJ_CLRSPC_CMYK:
return JpxDecodeAction::kUseCmyk;
-
- default:
- NOTREACHED_NORETURN();
}
}
@@ -356,7 +351,8 @@ CPDF_DIB::LoadState CPDF_DIB::ContinueLoadDIBBase(PauseIndicatorIface* pPause) {
iDecodeStatus = Jbig2Decoder::StartDecode(
m_pJbig2Context.get(), m_pDocument->GetOrCreateCodecContext(), m_Width,
m_Height, pSrcSpan, nSrcKey, pGlobalSpan, nGlobalKey,
- m_pCachedBitmap->GetBuffer(), m_pCachedBitmap->GetPitch(), pPause);
+ m_pCachedBitmap->GetWritableBuffer(), m_pCachedBitmap->GetPitch(),
+ pPause);
} else {
iDecodeStatus = Jbig2Decoder::ContinueDecode(m_pJbig2Context.get(), pPause);
}
@@ -690,9 +686,9 @@ RetainPtr<CFX_DIBitmap> CPDF_DIB::LoadJpxBitmap(
// If |original_colorspace| exists, then LoadColorInfo() already set
// |m_nComponents|.
if (original_colorspace) {
- DCHECK_NE(0, m_nComponents);
+ DCHECK_NE(0u, m_nComponents);
} else {
- DCHECK_EQ(0, m_nComponents);
+ DCHECK_EQ(0u, m_nComponents);
m_nComponents = GetComponentCountFromOpjColorSpace(image_info.colorspace);
if (m_nComponents == 0) {
return nullptr;
@@ -719,13 +715,13 @@ RetainPtr<CFX_DIBitmap> CPDF_DIB::LoadJpxBitmap(
return nullptr;
result_bitmap->Clear(0xFFFFFFFF);
- if (!decoder->Decode(result_bitmap->GetBuffer(), result_bitmap->GetPitch(),
- swap_rgb, m_nComponents)) {
+ if (!decoder->Decode(result_bitmap->GetWritableBuffer(),
+ result_bitmap->GetPitch(), swap_rgb, m_nComponents)) {
return nullptr;
}
if (convert_argb_to_rgb) {
- DCHECK_EQ(3, m_nComponents);
+ DCHECK_EQ(3u, m_nComponents);
auto rgb_bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
if (!rgb_bitmap->Create(image_info.width, image_info.height,
FXDIB_Format::kRgb)) {
@@ -1061,9 +1057,9 @@ void CPDF_DIB::TranslateScanline24bpp(
} else if (m_Family != CPDF_ColorSpace::Family::kPattern) {
m_pColorSpace->GetRGB(color_values, &R, &G, &B);
}
- R = pdfium::clamp(R, 0.0f, 1.0f);
- G = pdfium::clamp(G, 0.0f, 1.0f);
- B = pdfium::clamp(B, 0.0f, 1.0f);
+ R = std::clamp(R, 0.0f, 1.0f);
+ G = std::clamp(G, 0.0f, 1.0f);
+ B = std::clamp(B, 0.0f, 1.0f);
dest_scan[dest_byte_pos] = static_cast<uint8_t>(B * 255);
dest_scan[dest_byte_pos + 1] = static_cast<uint8_t>(G * 255);
dest_scan[dest_byte_pos + 2] = static_cast<uint8_t>(R * 255);
@@ -1135,9 +1131,9 @@ bool CPDF_DIB::TranslateScanline24bppDefaultDecode(
return true;
}
-pdfium::span<uint8_t> CPDF_DIB::GetBuffer() const {
+pdfium::span<const uint8_t> CPDF_DIB::GetBuffer() const {
return m_pCachedBitmap ? m_pCachedBitmap->GetBuffer()
- : pdfium::span<uint8_t>();
+ : pdfium::span<const uint8_t>();
}
pdfium::span<const uint8_t> CPDF_DIB::GetScanline(int line) const {
diff --git a/core/fpdfapi/page/cpdf_dib.h b/core/fpdfapi/page/cpdf_dib.h
index a24d192f5..5206bf553 100644
--- a/core/fpdfapi/page/cpdf_dib.h
+++ b/core/fpdfapi/page/cpdf_dib.h
@@ -17,7 +17,7 @@
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/unowned_ptr.h"
#include "core/fxge/dib/cfx_dibbase.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_Dictionary;
class CPDF_Document;
@@ -45,7 +45,7 @@ class CPDF_DIB final : public CFX_DIBBase {
CONSTRUCT_VIA_MAKE_RETAIN;
// CFX_DIBBase:
- pdfium::span<uint8_t> GetBuffer() const override;
+ pdfium::span<const uint8_t> GetBuffer() const override;
pdfium::span<const uint8_t> GetScanline(int line) const override;
bool SkipToScanline(int line, PauseIndicatorIface* pPause) const override;
size_t GetEstimatedImageMemoryBurden() const override;
diff --git a/core/fpdfapi/page/cpdf_expintfunc.h b/core/fpdfapi/page/cpdf_expintfunc.h
index 08b12fd7b..22e7f122c 100644
--- a/core/fpdfapi/page/cpdf_expintfunc.h
+++ b/core/fpdfapi/page/cpdf_expintfunc.h
@@ -11,7 +11,7 @@
#include "core/fxcrt/data_vector.h"
#if defined(_SKIA_SUPPORT_)
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#endif
class CPDF_ExpIntFunc final : public CPDF_Function {
diff --git a/core/fpdfapi/page/cpdf_form.cpp b/core/fpdfapi/page/cpdf_form.cpp
index 90a865035..e66ff0b32 100644
--- a/core/fpdfapi/page/cpdf_form.cpp
+++ b/core/fpdfapi/page/cpdf_form.cpp
@@ -18,6 +18,10 @@
#include "core/fxge/dib/cfx_dibitmap.h"
#include "third_party/base/check_op.h"
+CPDF_Form::RecursionState::RecursionState() = default;
+
+CPDF_Form::RecursionState::~RecursionState() = default;
+
// static
CPDF_Dictionary* CPDF_Form::ChooseResourcesDict(
CPDF_Dictionary* pResources,
@@ -61,8 +65,8 @@ void CPDF_Form::ParseContent() {
void CPDF_Form::ParseContent(const CPDF_AllStates* pGraphicStates,
const CFX_Matrix* pParentMatrix,
- std::set<const uint8_t*>* pParsedSet) {
- ParseContentInternal(pGraphicStates, pParentMatrix, nullptr, pParsedSet);
+ RecursionState* recursion_state) {
+ ParseContentInternal(pGraphicStates, pParentMatrix, nullptr, recursion_state);
}
void CPDF_Form::ParseContentForType3Char(CPDF_Type3Char* pType3Char) {
@@ -72,14 +76,14 @@ void CPDF_Form::ParseContentForType3Char(CPDF_Type3Char* pType3Char) {
void CPDF_Form::ParseContentInternal(const CPDF_AllStates* pGraphicStates,
const CFX_Matrix* pParentMatrix,
CPDF_Type3Char* pType3Char,
- std::set<const uint8_t*>* pParsedSet) {
+ RecursionState* recursion_state) {
if (GetParseState() == ParseState::kParsed)
return;
if (GetParseState() == ParseState::kNotParsed) {
StartParse(std::make_unique<CPDF_ContentParser>(
GetStream(), this, pGraphicStates, pParentMatrix, pType3Char,
- pParsedSet ? pParsedSet : &m_ParsedSet));
+ recursion_state ? recursion_state : &m_RecursionState));
}
DCHECK_EQ(GetParseState(), ParseState::kParsing);
ContinueParse(nullptr);
diff --git a/core/fpdfapi/page/cpdf_form.h b/core/fpdfapi/page/cpdf_form.h
index 9052b9d00..ba0fbd43a 100644
--- a/core/fpdfapi/page/cpdf_form.h
+++ b/core/fpdfapi/page/cpdf_form.h
@@ -24,6 +24,14 @@ class CPDF_Type3Char;
class CPDF_Form final : public CPDF_PageObjectHolder,
public CPDF_Font::FormIface {
public:
+ struct RecursionState {
+ RecursionState();
+ ~RecursionState();
+
+ std::set<const uint8_t*> parsed_set;
+ int form_count = 0;
+ };
+
// Helper method to choose the first non-null resources dictionary.
static CPDF_Dictionary* ChooseResourcesDict(CPDF_Dictionary* pResources,
CPDF_Dictionary* pParentResources,
@@ -48,7 +56,7 @@ class CPDF_Form final : public CPDF_PageObjectHolder,
void ParseContent();
void ParseContent(const CPDF_AllStates* pGraphicStates,
const CFX_Matrix* pParentMatrix,
- std::set<const uint8_t*>* pParsedSet);
+ RecursionState* recursion_state);
RetainPtr<const CPDF_Stream> GetStream() const;
@@ -56,9 +64,9 @@ class CPDF_Form final : public CPDF_PageObjectHolder,
void ParseContentInternal(const CPDF_AllStates* pGraphicStates,
const CFX_Matrix* pParentMatrix,
CPDF_Type3Char* pType3Char,
- std::set<const uint8_t*>* pParsedSet);
+ RecursionState* recursion_state);
- std::set<const uint8_t*> m_ParsedSet;
+ RecursionState m_RecursionState;
RetainPtr<CPDF_Stream> const m_pFormStream;
};
diff --git a/core/fpdfapi/page/cpdf_function.cpp b/core/fpdfapi/page/cpdf_function.cpp
index 85b9e4175..5e885e15e 100644
--- a/core/fpdfapi/page/cpdf_function.cpp
+++ b/core/fpdfapi/page/cpdf_function.cpp
@@ -6,6 +6,7 @@
#include "core/fpdfapi/page/cpdf_function.h"
+#include <algorithm>
#include <utility>
#include <vector>
@@ -21,7 +22,6 @@
#include "core/fxcrt/scoped_set_insertion.h"
#include "core/fxcrt/stl_util.h"
#include "third_party/base/containers/contains.h"
-#include "third_party/base/cxx17_backports.h"
namespace {
@@ -141,7 +141,7 @@ absl::optional<uint32_t> CPDF_Function::Call(
if (domain1 > domain2)
return absl::nullopt;
- clamped_inputs[i] = pdfium::clamp(inputs[i], domain1, domain2);
+ clamped_inputs[i] = std::clamp(inputs[i], domain1, domain2);
}
if (!v_Call(clamped_inputs, results))
return absl::nullopt;
@@ -155,7 +155,7 @@ absl::optional<uint32_t> CPDF_Function::Call(
if (range1 > range2)
return absl::nullopt;
- results[i] = pdfium::clamp(results[i], range1, range2);
+ results[i] = std::clamp(results[i], range1, range2);
}
return m_nOutputs;
}
diff --git a/core/fpdfapi/page/cpdf_function.h b/core/fpdfapi/page/cpdf_function.h
index faddb4ec7..d943e6075 100644
--- a/core/fpdfapi/page/cpdf_function.h
+++ b/core/fpdfapi/page/cpdf_function.h
@@ -13,7 +13,7 @@
#include "core/fxcrt/retain_ptr.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_ExpIntFunc;
class CPDF_Object;
diff --git a/core/fpdfapi/page/cpdf_iccprofile.h b/core/fpdfapi/page/cpdf_iccprofile.h
index 0e040aa45..3dd9f149d 100644
--- a/core/fpdfapi/page/cpdf_iccprofile.h
+++ b/core/fpdfapi/page/cpdf_iccprofile.h
@@ -13,7 +13,7 @@
#include "core/fxcrt/observed_ptr.h"
#include "core/fxcrt/retain_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_Stream;
diff --git a/core/fpdfapi/page/cpdf_image.cpp b/core/fpdfapi/page/cpdf_image.cpp
index c9be23106..6b70819fe 100644
--- a/core/fpdfapi/page/cpdf_image.cpp
+++ b/core/fpdfapi/page/cpdf_image.cpp
@@ -66,8 +66,8 @@ CPDF_Image::CPDF_Image(CPDF_Document* pDoc, uint32_t dwStreamObjNum)
CPDF_Image::~CPDF_Image() = default;
void CPDF_Image::FinishInitialization() {
- RetainPtr<CPDF_Dictionary> pStreamDict = m_pStream->GetMutableDict();
- m_pOC = pStreamDict->GetMutableDictFor("OC");
+ RetainPtr<const CPDF_Dictionary> pStreamDict = m_pStream->GetDict();
+ m_pOC = pStreamDict->GetDictFor("OC");
m_bIsMask = !pStreamDict->KeyExist("ColorSpace") ||
pStreamDict->GetBooleanFor("ImageMask", /*bDefault=*/false);
m_bInterpolate = !!pStreamDict->GetIntegerFor("Interpolate");
diff --git a/core/fpdfapi/page/cpdf_image.h b/core/fpdfapi/page/cpdf_image.h
index 04355a9d7..35357fc93 100644
--- a/core/fpdfapi/page/cpdf_image.h
+++ b/core/fpdfapi/page/cpdf_image.h
@@ -12,7 +12,7 @@
#include "core/fpdfapi/page/cpdf_colorspace.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/unowned_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_DIBBase;
class CFX_DIBitmap;
@@ -36,6 +36,8 @@ class CPDF_Image final : public Retainable {
RetainPtr<const CPDF_Dictionary> GetDict() const;
RetainPtr<const CPDF_Stream> GetStream() const;
RetainPtr<const CPDF_Dictionary> GetOC() const;
+
+ // Never returns nullptr.
CPDF_Document* GetDocument() const { return m_pDocument; }
int32_t GetPixelHeight() const { return m_Height; }
diff --git a/core/fpdfapi/page/cpdf_imageobject.cpp b/core/fpdfapi/page/cpdf_imageobject.cpp
index c031502e0..0511a028e 100644
--- a/core/fpdfapi/page/cpdf_imageobject.cpp
+++ b/core/fpdfapi/page/cpdf_imageobject.cpp
@@ -82,10 +82,6 @@ void CPDF_ImageObject::MaybePurgeCache() {
if (!m_pImage)
return;
- auto* pDoc = m_pImage->GetDocument();
- if (!pDoc)
- return;
-
RetainPtr<const CPDF_Stream> pStream = m_pImage->GetStream();
if (!pStream)
return;
@@ -94,6 +90,9 @@ void CPDF_ImageObject::MaybePurgeCache() {
if (!objnum)
return;
+ auto* pDoc = m_pImage->GetDocument();
+ CHECK(pDoc);
+
m_pImage.Reset(); // Clear my reference before asking the cache.
pDoc->MaybePurgeImage(objnum);
}
diff --git a/core/fpdfapi/page/cpdf_indexedcs.cpp b/core/fpdfapi/page/cpdf_indexedcs.cpp
index 85f694fe3..e35352b08 100644
--- a/core/fpdfapi/page/cpdf_indexedcs.cpp
+++ b/core/fpdfapi/page/cpdf_indexedcs.cpp
@@ -20,7 +20,7 @@
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/retain_ptr.h"
#include "third_party/base/check_op.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
CPDF_IndexedCS::CPDF_IndexedCS() : CPDF_BasedCS(Family::kIndexed) {}
diff --git a/core/fpdfapi/page/cpdf_meshstream.cpp b/core/fpdfapi/page/cpdf_meshstream.cpp
index 95f560f59..6a0419ecb 100644
--- a/core/fpdfapi/page/cpdf_meshstream.cpp
+++ b/core/fpdfapi/page/cpdf_meshstream.cpp
@@ -16,7 +16,7 @@
#include "core/fpdfapi/parser/cpdf_stream_acc.h"
#include "core/fxcrt/cfx_bitstream.h"
#include "third_party/base/check.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace {
diff --git a/core/fpdfapi/page/cpdf_pageimagecache.cpp b/core/fpdfapi/page/cpdf_pageimagecache.cpp
index 497cd8be0..cebb8b1fa 100644
--- a/core/fpdfapi/page/cpdf_pageimagecache.cpp
+++ b/core/fpdfapi/page/cpdf_pageimagecache.cpp
@@ -6,6 +6,9 @@
#include "core/fpdfapi/page/cpdf_pageimagecache.h"
+#include <stddef.h>
+#include <stdint.h>
+
#include <algorithm>
#include <utility>
#include <vector>
@@ -16,8 +19,19 @@
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
+#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/stl_util.h"
+#include "core/fxge/dib/cfx_dibbase.h"
#include "core/fxge/dib/cfx_dibitmap.h"
+#include "third_party/base/check.h"
+
+#if defined(_SKIA_SUPPORT_)
+#include "core/fxcrt/data_vector.h"
+#include "core/fxge/cfx_defaultrenderdevice.h"
+#include "third_party/base/notreached.h"
+#include "third_party/skia/include/core/SkImage.h" // nogncheck
+#include "third_party/skia/include/core/SkRefCnt.h" // nogncheck
+#endif
namespace {
@@ -31,6 +45,86 @@ struct CacheInfo {
bool operator<(const CacheInfo& other) const { return time < other.time; }
};
+#if defined(_SKIA_SUPPORT_)
+// Wrapper around a `CFX_DIBBase` that memoizes `RealizeSkImage()`. This is only
+// safe if the underlying `CFX_DIBBase` is not mutable.
+class CachedImage final : public CFX_DIBBase {
+ public:
+ explicit CachedImage(RetainPtr<CFX_DIBBase> image)
+ : image_(std::move(image)) {
+ m_Format = image_->GetFormat();
+ m_Width = image_->GetWidth();
+ m_Height = image_->GetHeight();
+ m_Pitch = image_->GetPitch();
+
+ if (image_->HasPalette()) {
+ pdfium::span<const uint32_t> palette = image_->GetPaletteSpan();
+ m_palette = DataVector<uint32_t>(palette.begin(), palette.end());
+ }
+ }
+
+ pdfium::span<const uint8_t> GetBuffer() const override {
+ // TODO(crbug.com/pdfium/2051): `CachedImage` is only used by Skia, which
+ // should call `RealizeSkImage()` instead. Consider removing this, or at
+ // least making it `NOTREACHED_NORETURN()`.
+ NOTREACHED();
+ return image_->GetBuffer();
+ }
+
+ pdfium::span<const uint8_t> GetScanline(int line) const override {
+ // TODO(crbug.com/pdfium/2050): Still needed for `Realize()` call in
+ // `CPDF_ImageRenderer`.
+ return image_->GetScanline(line);
+ }
+
+ bool SkipToScanline(int line, PauseIndicatorIface* pause) const override {
+ // TODO(crbug.com/pdfium/2051): `CachedImage` is only used by Skia, which
+ // should call `RealizeSkImage()` instead. Consider removing this, or at
+ // least making it `NOTREACHED_NORETURN()`.
+ NOTREACHED();
+ return image_->SkipToScanline(line, pause);
+ }
+
+ size_t GetEstimatedImageMemoryBurden() const override {
+ // A better estimate would account for realizing the `SkImage`.
+ return image_->GetEstimatedImageMemoryBurden();
+ }
+
+ sk_sp<SkImage> RealizeSkImage() const override {
+ if (!cached_skia_image_) {
+ cached_skia_image_ = image_->RealizeSkImage();
+ }
+ return cached_skia_image_;
+ }
+
+ private:
+ RetainPtr<CFX_DIBBase> image_;
+ mutable sk_sp<SkImage> cached_skia_image_;
+};
+#endif // defined(_SKIA_SUPPORT_)
+
+// Makes a `CachedImage` backed by `image` if Skia is the default renderer,
+// otherwise return the image itself. `realize_hint` indicates whether it would
+// be beneficial to realize `image` before caching.
+RetainPtr<CFX_DIBBase> MakeCachedImage(RetainPtr<CFX_DIBBase> image,
+ bool realize_hint) {
+#if defined(_SKIA_SUPPORT_)
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ // TODO(crbug.com/pdfium/2050): Ignore `realize_hint`, as `RealizeSkImage()`
+ // doesn't benefit from it. The current behavior masks a bug in `CPDF_DIB`
+ // in which `GetBuffer()` and `GetScanline()` don't give the same answer.
+ if (realize_hint) {
+ image = image->Realize();
+ if (!image) {
+ return nullptr;
+ }
+ }
+ return pdfium::MakeRetain<CachedImage>(std::move(image));
+ }
+#endif // defined(_SKIA_SUPPORT_)
+ return realize_hint ? image->Realize() : image;
+}
+
} // namespace
CPDF_PageImageCache::CPDF_PageImageCache(CPDF_Page* pPage) : m_pPage(pPage) {}
@@ -226,13 +320,13 @@ void CPDF_PageImageCache::Entry::ContinueGetCachedBitmap(
m_pCurMask = m_pCurBitmap.AsRaw<CPDF_DIB>()->DetachMask();
m_dwTimeCount = pPageImageCache->GetTimeCount();
if (m_pCurBitmap->GetPitch() * m_pCurBitmap->GetHeight() < kHugeImageSize) {
- m_pCachedBitmap = m_pCurBitmap->Realize();
+ m_pCachedBitmap = MakeCachedImage(m_pCurBitmap, /*realize_hint=*/true);
m_pCurBitmap.Reset();
} else {
- m_pCachedBitmap = m_pCurBitmap;
+ m_pCachedBitmap = MakeCachedImage(m_pCurBitmap, /*realize_hint=*/false);
}
if (m_pCurMask) {
- m_pCachedMask = m_pCurMask->Realize();
+ m_pCachedMask = MakeCachedImage(m_pCurMask, /*realize_hint=*/true);
m_pCurMask.Reset();
}
m_pCurBitmap = m_pCachedBitmap;
diff --git a/core/fpdfapi/page/cpdf_pageobject.cpp b/core/fpdfapi/page/cpdf_pageobject.cpp
index 8636af6ce..a7b2156d5 100644
--- a/core/fpdfapi/page/cpdf_pageobject.cpp
+++ b/core/fpdfapi/page/cpdf_pageobject.cpp
@@ -6,6 +6,8 @@
#include "core/fpdfapi/page/cpdf_pageobject.h"
+#include <utility>
+
#include "core/fxcrt/fx_coordinates.h"
CPDF_PageObject::CPDF_PageObject(int32_t content_stream)
@@ -73,6 +75,11 @@ const CPDF_FormObject* CPDF_PageObject::AsForm() const {
return nullptr;
}
+void CPDF_PageObject::SetGraphicsResourceNames(
+ std::vector<ByteString> resource_names) {
+ m_GraphicsResourceNames = std::move(resource_names);
+}
+
void CPDF_PageObject::CopyData(const CPDF_PageObject* pSrc) {
CopyStates(*pSrc);
m_Rect = pSrc->m_Rect;
diff --git a/core/fpdfapi/page/cpdf_pageobject.h b/core/fpdfapi/page/cpdf_pageobject.h
index 7d9d01583..ccdbbaff4 100644
--- a/core/fpdfapi/page/cpdf_pageobject.h
+++ b/core/fpdfapi/page/cpdf_pageobject.h
@@ -9,6 +9,8 @@
#include <stdint.h>
+#include <vector>
+
#include "core/fpdfapi/page/cpdf_contentmarks.h"
#include "core/fpdfapi/page/cpdf_graphicstates.h"
#include "core/fxcrt/bytestring.h"
@@ -94,12 +96,10 @@ class CPDF_PageObject : public CPDF_GraphicStates {
m_ResourceName = resource_name;
}
- const ByteString& GetGraphicsResourceName() const {
- return m_GraphicsResourceName;
- }
- void SetGraphicsResourceName(const ByteString& resource_name) {
- m_GraphicsResourceName = resource_name;
+ const std::vector<ByteString>& GetGraphicsResourceNames() const {
+ return m_GraphicsResourceNames;
}
+ void SetGraphicsResourceNames(std::vector<ByteString> resource_names);
protected:
void CopyData(const CPDF_PageObject* pSrcObject);
@@ -110,8 +110,11 @@ class CPDF_PageObject : public CPDF_GraphicStates {
CPDF_ContentMarks m_ContentMarks;
bool m_bDirty = false;
int32_t m_ContentStream;
- ByteString m_ResourceName; // The resource name for this object.
- ByteString m_GraphicsResourceName; // Like `m_ResourceName` but for graphics.
+ // The resource name for this object.
+ ByteString m_ResourceName;
+ // Like `m_ResourceName` but for graphics. Though unlike the resource name,
+ // multiple graphics states can apply at once.
+ std::vector<ByteString> m_GraphicsResourceNames;
};
#endif // CORE_FPDFAPI_PAGE_CPDF_PAGEOBJECT_H_
diff --git a/core/fpdfapi/page/cpdf_pattern.h b/core/fpdfapi/page/cpdf_pattern.h
index cd535b124..b77381768 100644
--- a/core/fpdfapi/page/cpdf_pattern.h
+++ b/core/fpdfapi/page/cpdf_pattern.h
@@ -22,8 +22,6 @@ class CPDF_Pattern : public Retainable, public Observable {
// Values used in PDFs. Do not change.
enum PatternType { kTiling = 1, kShading = 2 };
- ~CPDF_Pattern() override;
-
virtual CPDF_TilingPattern* AsTilingPattern();
virtual CPDF_ShadingPattern* AsShadingPattern();
@@ -33,6 +31,7 @@ class CPDF_Pattern : public Retainable, public Observable {
CPDF_Pattern(CPDF_Document* pDoc,
RetainPtr<CPDF_Object> pObj,
const CFX_Matrix& parentMatrix);
+ ~CPDF_Pattern() override;
// All the getters that return pointers return non-NULL pointers.
CPDF_Document* document() const { return m_pDocument; }
diff --git a/core/fpdfapi/page/cpdf_psengine.h b/core/fpdfapi/page/cpdf_psengine.h
index d7f6f7e51..0b82bc0e8 100644
--- a/core/fpdfapi/page/cpdf_psengine.h
+++ b/core/fpdfapi/page/cpdf_psengine.h
@@ -14,7 +14,7 @@
#include <vector>
#include "core/fxcrt/bytestring.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_PSEngine;
class CPDF_PSProc;
diff --git a/core/fpdfapi/page/cpdf_sampledfunc.cpp b/core/fpdfapi/page/cpdf_sampledfunc.cpp
index 0aa28f4f0..1dd9a5be4 100644
--- a/core/fpdfapi/page/cpdf_sampledfunc.cpp
+++ b/core/fpdfapi/page/cpdf_sampledfunc.cpp
@@ -6,6 +6,7 @@
#include "core/fpdfapi/page/cpdf_sampledfunc.h"
+#include <algorithm>
#include <utility>
#include "core/fpdfapi/parser/cpdf_array.h"
@@ -15,7 +16,6 @@
#include "core/fxcrt/cfx_bitstream.h"
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/small_buffer.h"
-#include "third_party/base/cxx17_backports.h"
namespace {
@@ -116,8 +116,8 @@ bool CPDF_SampledFunc::v_Call(pdfium::span<const float> inputs,
encoded_input[i] =
Interpolate(inputs[i], m_Domains[i * 2], m_Domains[i * 2 + 1],
m_EncodeInfo[i].encode_min, m_EncodeInfo[i].encode_max);
- index[i] = pdfium::clamp(static_cast<uint32_t>(encoded_input[i]), 0U,
- m_EncodeInfo[i].sizes - 1);
+ index[i] = std::clamp(static_cast<uint32_t>(encoded_input[i]), 0U,
+ m_EncodeInfo[i].sizes - 1);
pos += index[i] * blocksize[i];
}
FX_SAFE_INT32 bits_to_output = m_nOutputs;
diff --git a/core/fpdfapi/page/cpdf_streamcontentparser.cpp b/core/fpdfapi/page/cpdf_streamcontentparser.cpp
index 0522cf1d8..cae9d7201 100644
--- a/core/fpdfapi/page/cpdf_streamcontentparser.cpp
+++ b/core/fpdfapi/page/cpdf_streamcontentparser.cpp
@@ -43,19 +43,22 @@
#include "core/fxge/cfx_graphstatedata.h"
#include "third_party/base/check.h"
#include "third_party/base/containers/contains.h"
+#include "third_party/base/containers/span.h"
#include "third_party/base/no_destructor.h"
#include "third_party/base/notreached.h"
-#include "third_party/base/span.h"
namespace {
-const int kMaxFormLevel = 40;
+constexpr int kMaxFormLevel = 40;
-const int kSingleCoordinatePair = 1;
-const int kTensorCoordinatePairs = 16;
-const int kCoonsCoordinatePairs = 12;
-const int kSingleColorPerPatch = 1;
-const int kQuadColorsPerPatch = 4;
+// Upper limit for the number of form XObjects within a form XObject.
+constexpr int kFormCountLimit = 4096;
+
+constexpr int kSingleCoordinatePair = 1;
+constexpr int kTensorCoordinatePairs = 16;
+constexpr int kCoonsCoordinatePairs = 12;
+constexpr int kSingleColorPerPatch = 1;
+constexpr int kQuadColorsPerPatch = 4;
const char kPathOperatorSubpath = 'm';
const char kPathOperatorLine = 'l';
@@ -250,7 +253,7 @@ CPDF_StreamContentParser::CPDF_StreamContentParser(
RetainPtr<CPDF_Dictionary> pResources,
const CFX_FloatRect& rcBBox,
const CPDF_AllStates* pStates,
- std::set<const uint8_t*>* pParsedSet)
+ CPDF_Form::RecursionState* recursion_state)
: m_pDocument(pDocument),
m_pPageResources(pPageResources),
m_pParentResources(pParentResources),
@@ -258,7 +261,7 @@ CPDF_StreamContentParser::CPDF_StreamContentParser(
pParentResources.Get(),
pPageResources.Get())),
m_pObjectHolder(pObjHolder),
- m_ParsedSet(pParsedSet),
+ m_RecursionState(recursion_state),
m_BBox(rcBBox),
m_pCurStates(std::make_unique<CPDF_AllStates>()) {
if (pmtContentToUser)
@@ -426,7 +429,7 @@ void CPDF_StreamContentParser::SetGraphicStates(CPDF_PageObject* pObj,
if (bText) {
pObj->m_TextState = m_pCurStates->m_TextState;
}
- pObj->SetGraphicsResourceName(m_pCurStates->m_GraphicsResourceName);
+ pObj->SetGraphicsResourceNames(m_pCurStates->m_GraphicsResourceNames);
}
// static
@@ -744,7 +747,16 @@ void CPDF_StreamContentParser::Handle_ExecuteXObject() {
type = pXObject->GetDict()->GetByteStringFor("Subtype");
if (type == "Form") {
+ if (m_RecursionState->form_count > kFormCountLimit) {
+ return;
+ }
+
+ const bool is_first = m_RecursionState->form_count == 0;
+ ++m_RecursionState->form_count;
AddForm(std::move(pXObject), name);
+ if (is_first) {
+ m_RecursionState->form_count = 0;
+ }
return;
}
@@ -772,13 +784,13 @@ void CPDF_StreamContentParser::AddForm(RetainPtr<CPDF_Stream> pStream,
status.m_TextState = m_pCurStates->m_TextState;
auto form = std::make_unique<CPDF_Form>(
m_pDocument, m_pPageResources, std::move(pStream), m_pResources.Get());
- form->ParseContent(&status, nullptr, m_ParsedSet);
+ form->ParseContent(&status, nullptr, m_RecursionState);
CFX_Matrix matrix = m_pCurStates->m_CTM * m_mtContentToUser;
auto pFormObj = std::make_unique<CPDF_FormObject>(GetCurrentStreamIndex(),
std::move(form), matrix);
pFormObj->SetResourceName(name);
- pFormObj->SetGraphicsResourceName(m_pCurStates->m_GraphicsResourceName);
+ pFormObj->SetGraphicsResourceNames(m_pCurStates->m_GraphicsResourceNames);
if (!m_pObjectHolder->BackgroundAlphaNeeded() &&
pFormObj->form()->BackgroundAlphaNeeded()) {
m_pObjectHolder->SetBackgroundAlphaNeeded(true);
@@ -903,7 +915,8 @@ void CPDF_StreamContentParser::Handle_SetExtendGraphState() {
if (!pGS)
return;
- m_pCurStates->m_GraphicsResourceName = name;
+ CHECK(!name.IsEmpty());
+ m_pCurStates->m_GraphicsResourceNames.push_back(std::move(name));
m_pCurStates->ProcessExtGS(pGS.Get(), this);
}
@@ -1535,15 +1548,15 @@ uint32_t CPDF_StreamContentParser::Parse(
// Parsing will be done from within |pDataStart|.
pdfium::span<const uint8_t> pDataStart = pData.subspan(start_offset);
m_StartParseOffset = start_offset;
- if (m_ParsedSet->size() > kMaxFormLevel ||
- pdfium::Contains(*m_ParsedSet, pDataStart.data())) {
+ if (m_RecursionState->parsed_set.size() > kMaxFormLevel ||
+ pdfium::Contains(m_RecursionState->parsed_set, pDataStart.data())) {
return fxcrt::CollectionSize<uint32_t>(pDataStart);
}
m_StreamStartOffsets = stream_start_offsets;
- ScopedSetInsertion<const uint8_t*> scopedInsert(m_ParsedSet,
- pDataStart.data());
+ ScopedSetInsertion<const uint8_t*> scoped_insert(
+ &m_RecursionState->parsed_set, pDataStart.data());
uint32_t init_obj_count = m_pObjectHolder->GetPageObjectCount();
AutoNuller<std::unique_ptr<CPDF_StreamParser>> auto_clearer(&m_pSyntax);
diff --git a/core/fpdfapi/page/cpdf_streamcontentparser.h b/core/fpdfapi/page/cpdf_streamcontentparser.h
index 276dc7292..c31dd157e 100644
--- a/core/fpdfapi/page/cpdf_streamcontentparser.h
+++ b/core/fpdfapi/page/cpdf_streamcontentparser.h
@@ -9,11 +9,11 @@
#include <map>
#include <memory>
-#include <set>
#include <stack>
#include <vector>
#include "core/fpdfapi/page/cpdf_contentmarks.h"
+#include "core/fpdfapi/page/cpdf_form.h"
#include "core/fxcrt/bytestring.h"
#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/fx_number.h"
@@ -21,7 +21,7 @@
#include "core/fxcrt/unowned_ptr.h"
#include "core/fxge/cfx_fillrenderoptions.h"
#include "core/fxge/cfx_path.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_AllStates;
class CPDF_ColorSpace;
@@ -49,7 +49,7 @@ class CPDF_StreamContentParser {
RetainPtr<CPDF_Dictionary> pResources,
const CFX_FloatRect& rcBBox,
const CPDF_AllStates* pStates,
- std::set<const uint8_t*>* pParsedSet);
+ CPDF_Form::RecursionState* parse_state);
~CPDF_StreamContentParser();
uint32_t Parse(pdfium::span<const uint8_t> pData,
@@ -222,7 +222,7 @@ class CPDF_StreamContentParser {
RetainPtr<CPDF_Dictionary> const m_pParentResources;
RetainPtr<CPDF_Dictionary> const m_pResources;
UnownedPtr<CPDF_PageObjectHolder> const m_pObjectHolder;
- UnownedPtr<std::set<const uint8_t*>> const m_ParsedSet;
+ UnownedPtr<CPDF_Form::RecursionState> const m_RecursionState;
CFX_Matrix m_mtContentToUser;
const CFX_FloatRect m_BBox;
uint32_t m_ParamStartPos = 0;
diff --git a/core/fpdfapi/page/cpdf_streamparser.h b/core/fpdfapi/page/cpdf_streamparser.h
index 1a0f1159d..ecefa0295 100644
--- a/core/fpdfapi/page/cpdf_streamparser.h
+++ b/core/fpdfapi/page/cpdf_streamparser.h
@@ -10,7 +10,7 @@
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/string_pool_template.h"
#include "core/fxcrt/weak_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_Dictionary;
class CPDF_Document;
diff --git a/core/fpdfapi/page/cpdf_textobject.cpp b/core/fpdfapi/page/cpdf_textobject.cpp
index a063541c7..087883eaf 100644
--- a/core/fpdfapi/page/cpdf_textobject.cpp
+++ b/core/fpdfapi/page/cpdf_textobject.cpp
@@ -12,7 +12,7 @@
#include "core/fpdfapi/font/cpdf_font.h"
#include "core/fxcrt/fx_coordinates.h"
#include "third_party/base/check.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#define ISLATINWORD(u) (u != 0x20 && u <= 0x28FF)
diff --git a/core/fpdfapi/page/cpdf_textstate.h b/core/fpdfapi/page/cpdf_textstate.h
index 932d5a7a4..b46260611 100644
--- a/core/fpdfapi/page/cpdf_textstate.h
+++ b/core/fpdfapi/page/cpdf_textstate.h
@@ -10,7 +10,7 @@
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/shared_copy_on_write.h"
#include "core/fxcrt/unowned_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_Document;
class CPDF_Font;
diff --git a/core/fpdfapi/page/cpdf_transferfunc.h b/core/fpdfapi/page/cpdf_transferfunc.h
index d16893021..11ea98d53 100644
--- a/core/fpdfapi/page/cpdf_transferfunc.h
+++ b/core/fpdfapi/page/cpdf_transferfunc.h
@@ -13,7 +13,7 @@
#include "core/fxcrt/observed_ptr.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxge/dib/fx_dib.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_DIBBase;
diff --git a/core/fpdfapi/page/cpdf_transferfuncdib.h b/core/fpdfapi/page/cpdf_transferfuncdib.h
index a03411623..81731096f 100644
--- a/core/fpdfapi/page/cpdf_transferfuncdib.h
+++ b/core/fpdfapi/page/cpdf_transferfuncdib.h
@@ -12,7 +12,7 @@
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxge/dib/cfx_dibbase.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_TransferFunc;
diff --git a/core/fpdfapi/parser/cfdf_document.cpp b/core/fpdfapi/parser/cfdf_document.cpp
index 5e9b6d3dd..ea34fbebb 100644
--- a/core/fpdfapi/parser/cfdf_document.cpp
+++ b/core/fpdfapi/parser/cfdf_document.cpp
@@ -15,7 +15,7 @@
#include "core/fpdfapi/parser/fpdf_parser_utility.h"
#include "core/fxcrt/cfx_read_only_span_stream.h"
#include "core/fxcrt/fx_string_wrappers.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
CFDF_Document::CFDF_Document() = default;
diff --git a/core/fpdfapi/parser/cfdf_document.h b/core/fpdfapi/parser/cfdf_document.h
index bd0e72f52..f327ab526 100644
--- a/core/fpdfapi/parser/cfdf_document.h
+++ b/core/fpdfapi/parser/cfdf_document.h
@@ -11,7 +11,7 @@
#include "core/fpdfapi/parser/cpdf_indirect_object_holder.h"
#include "core/fxcrt/retain_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_Dictionary;
class IFX_SeekableReadStream;
diff --git a/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp b/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp
index 7f0b7fed5..8562e642e 100644
--- a/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp
@@ -11,7 +11,6 @@
#include "core/fpdfapi/parser/fpdf_parser_utility.h"
#include "third_party/base/check.h"
#include "third_party/base/containers/contains.h"
-#include "third_party/base/notreached.h"
#include "third_party/base/numerics/safe_conversions.h"
namespace {
@@ -54,11 +53,6 @@ CPDF_DataAvail::DocAvailStatus CPDF_CrossRefAvail::CheckAvail() {
break;
case State::kDone:
break;
- default: {
- status_ = CPDF_DataAvail::kDataError;
- NOTREACHED();
- break;
- }
}
if (!check_result)
break;
diff --git a/core/fpdfapi/parser/cpdf_cross_ref_table.cpp b/core/fpdfapi/parser/cpdf_cross_ref_table.cpp
index 0bb5bb69c..31177a39e 100644
--- a/core/fpdfapi/parser/cpdf_cross_ref_table.cpp
+++ b/core/fpdfapi/parser/cpdf_cross_ref_table.cpp
@@ -110,20 +110,30 @@ void CPDF_CrossRefTable::Update(
UpdateTrailer(std::move(new_cross_ref->trailer_));
}
-void CPDF_CrossRefTable::ShrinkObjectMap(uint32_t objnum) {
- if (objnum == 0) {
+void CPDF_CrossRefTable::SetObjectMapSize(uint32_t size) {
+ if (size == 0) {
objects_info_.clear();
return;
}
- objects_info_.erase(objects_info_.lower_bound(objnum), objects_info_.end());
+ objects_info_.erase(objects_info_.lower_bound(size), objects_info_.end());
- if (!pdfium::Contains(objects_info_, objnum - 1))
- objects_info_[objnum - 1].pos = 0;
+ if (!pdfium::Contains(objects_info_, size - 1)) {
+ objects_info_[size - 1].pos = 0;
+ }
}
void CPDF_CrossRefTable::UpdateInfo(
- std::map<uint32_t, ObjectInfo>&& new_objects_info) {
+ std::map<uint32_t, ObjectInfo> new_objects_info) {
+ if (new_objects_info.empty()) {
+ return;
+ }
+
+ if (objects_info_.empty()) {
+ objects_info_ = std::move(new_objects_info);
+ return;
+ }
+
auto cur_it = objects_info_.begin();
auto new_it = new_objects_info.begin();
while (cur_it != objects_info_.end() && new_it != new_objects_info.end()) {
diff --git a/core/fpdfapi/parser/cpdf_cross_ref_table.h b/core/fpdfapi/parser/cpdf_cross_ref_table.h
index 246e12974..d76e29cda 100644
--- a/core/fpdfapi/parser/cpdf_cross_ref_table.h
+++ b/core/fpdfapi/parser/cpdf_cross_ref_table.h
@@ -73,10 +73,11 @@ class CPDF_CrossRefTable {
void Update(std::unique_ptr<CPDF_CrossRefTable> new_cross_ref);
- void ShrinkObjectMap(uint32_t objnum);
+ // Objects with object number >= `size` will be removed.
+ void SetObjectMapSize(uint32_t size);
private:
- void UpdateInfo(std::map<uint32_t, ObjectInfo>&& new_objects_info);
+ void UpdateInfo(std::map<uint32_t, ObjectInfo> new_objects_info);
void UpdateTrailer(RetainPtr<CPDF_Dictionary> new_trailer);
RetainPtr<CPDF_Dictionary> trailer_;
diff --git a/core/fpdfapi/parser/cpdf_crypto_handler.cpp b/core/fpdfapi/parser/cpdf_crypto_handler.cpp
index 5404207db..43ae781b6 100644
--- a/core/fpdfapi/parser/cpdf_crypto_handler.cpp
+++ b/core/fpdfapi/parser/cpdf_crypto_handler.cpp
@@ -232,7 +232,7 @@ bool CPDF_CryptoHandler::DecryptObjectTree(RetainPtr<CPDF_Object> object) {
return false;
struct MayBeSignature {
- const CPDF_Dictionary* parent;
+ RetainPtr<const CPDF_Dictionary> parent;
RetainPtr<CPDF_Object> contents;
};
@@ -255,7 +255,8 @@ bool CPDF_CryptoHandler::DecryptObjectTree(RetainPtr<CPDF_Object> object) {
// 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({parent_dict.Get(), std::move(child)});
+ may_be_sign_dictionaries.push(
+ {std::move(parent_dict), std::move(child)});
walker.SkipWalkIntoCurrentObject();
continue;
}
diff --git a/core/fpdfapi/parser/cpdf_crypto_handler.h b/core/fpdfapi/parser/cpdf_crypto_handler.h
index b8f938c23..ba934cc3e 100644
--- a/core/fpdfapi/parser/cpdf_crypto_handler.h
+++ b/core/fpdfapi/parser/cpdf_crypto_handler.h
@@ -17,7 +17,7 @@
#include "core/fxcrt/bytestring.h"
#include "core/fxcrt/fx_memory_wrappers.h"
#include "core/fxcrt/retain_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_Dictionary;
class CPDF_Object;
diff --git a/core/fpdfapi/parser/cpdf_data_avail.cpp b/core/fpdfapi/parser/cpdf_data_avail.cpp
index 7db348a8d..bc3ff3377 100644
--- a/core/fpdfapi/parser/cpdf_data_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_data_avail.cpp
@@ -193,9 +193,6 @@ bool CPDF_DataAvail::CheckAndLoadAllXref() {
case kDataError:
m_internalStatus = InternalStatus::kError;
return false;
- default:
- NOTREACHED();
- return false;
}
if (!m_parser.LoadAllCrossRefV4(m_pCrossRefAvail->last_crossref_offset()) &&
@@ -421,9 +418,6 @@ bool CPDF_DataAvail::CheckHeader() {
case kDataError:
m_internalStatus = InternalStatus::kError;
return true;
- default:
- NOTREACHED();
- return false;
}
}
@@ -488,9 +482,6 @@ CPDF_DataAvail::DocLinearizationStatus CPDF_DataAvail::IsLinearizedPDF() {
return kLinearizationUnknown;
case kDataError:
return kNotLinearized;
- default:
- NOTREACHED();
- return kLinearizationUnknown;
}
}
@@ -1002,10 +993,7 @@ CPDF_DataAvail::DocFormStatus CPDF_DataAvail::CheckAcroForm() {
return kFormNotAvailable;
case kDataAvailable:
return kFormAvailable;
- default:
- NOTREACHED();
}
- return kFormError;
}
bool CPDF_DataAvail::ValidatePage(uint32_t dwPage) const {
diff --git a/core/fpdfapi/parser/cpdf_encryptor.h b/core/fpdfapi/parser/cpdf_encryptor.h
index 37f076322..d0aabcc48 100644
--- a/core/fpdfapi/parser/cpdf_encryptor.h
+++ b/core/fpdfapi/parser/cpdf_encryptor.h
@@ -11,7 +11,7 @@
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/unowned_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_CryptoHandler;
diff --git a/core/fpdfapi/parser/cpdf_flateencoder.h b/core/fpdfapi/parser/cpdf_flateencoder.h
index 2d26d9b88..a9b37f702 100644
--- a/core/fpdfapi/parser/cpdf_flateencoder.h
+++ b/core/fpdfapi/parser/cpdf_flateencoder.h
@@ -12,7 +12,7 @@
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/retain_ptr.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_Dictionary;
class CPDF_Encryptor;
diff --git a/core/fpdfapi/parser/cpdf_hint_tables.cpp b/core/fpdfapi/parser/cpdf_hint_tables.cpp
index ba3173d1d..5870d0109 100644
--- a/core/fpdfapi/parser/cpdf_hint_tables.cpp
+++ b/core/fpdfapi/parser/cpdf_hint_tables.cpp
@@ -21,8 +21,8 @@
#include "core/fxcrt/cfx_bitstream.h"
#include "core/fxcrt/fx_safe_types.h"
#include "third_party/base/check.h"
+#include "third_party/base/containers/span.h"
#include "third_party/base/numerics/safe_conversions.h"
-#include "third_party/base/span.h"
namespace {
diff --git a/core/fpdfapi/parser/cpdf_linearized_header.cpp b/core/fpdfapi/parser/cpdf_linearized_header.cpp
index f4de7d7a2..b0935783d 100644
--- a/core/fpdfapi/parser/cpdf_linearized_header.cpp
+++ b/core/fpdfapi/parser/cpdf_linearized_header.cpp
@@ -17,7 +17,7 @@
#include "core/fpdfapi/parser/cpdf_syntax_parser.h"
#include "core/fxcrt/fx_safe_types.h"
#include "third_party/base/check.h"
-#include "third_party/base/ptr_util.h"
+#include "third_party/base/memory/ptr_util.h"
namespace {
diff --git a/core/fpdfapi/parser/cpdf_object_stream.cpp b/core/fpdfapi/parser/cpdf_object_stream.cpp
index 1c5a7b792..19294da7c 100644
--- a/core/fpdfapi/parser/cpdf_object_stream.cpp
+++ b/core/fpdfapi/parser/cpdf_object_stream.cpp
@@ -17,7 +17,7 @@
#include "core/fxcrt/cfx_read_only_span_stream.h"
#include "core/fxcrt/fx_safe_types.h"
#include "third_party/base/check.h"
-#include "third_party/base/ptr_util.h"
+#include "third_party/base/memory/ptr_util.h"
namespace {
diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp
index 302aec1a1..098e67ea9 100644
--- a/core/fpdfapi/parser/cpdf_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -35,14 +35,15 @@
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
#include "third_party/base/containers/contains.h"
+#include "third_party/base/containers/span.h"
#include "third_party/base/notreached.h"
-#include "third_party/base/span.h"
namespace {
// A limit on the size of the xref table. Theoretical limits are higher, but
-// this may be large enough in practice.
-const int32_t kMaxXRefSize = 1048576;
+// this may be large enough in practice. The max size should always be 1 more
+// than the max object number.
+constexpr int32_t kMaxXRefSize = CPDF_Parser::kMaxObjectNumber + 1;
// "%PDF-1.7\n"
constexpr FX_FILESIZE kPDFHeaderSize = 9;
@@ -200,10 +201,6 @@ bool CPDF_Parser::IsObjectFree(uint32_t objnum) const {
return GetObjectType(objnum) == ObjectType::kFree;
}
-void CPDF_Parser::ShrinkObjectMap(uint32_t size) {
- m_CrossRefTable->ShrinkObjectMap(size);
-}
-
bool CPDF_Parser::InitSyntaxParser(RetainPtr<CPDF_ReadValidator> validator) {
const absl::optional<FX_FILESIZE> header_offset = GetHeaderOffset(validator);
if (!header_offset.has_value())
@@ -384,7 +381,7 @@ bool CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xref_offset) {
m_CrossRefTable->SetTrailer(std::move(trailer), kNoV4TrailerObjectNumber);
const int32_t xrefsize = GetTrailer()->GetDirectIntegerFor("Size");
if (xrefsize > 0 && xrefsize <= kMaxXRefSize)
- ShrinkObjectMap(xrefsize);
+ m_CrossRefTable->SetObjectMapSize(xrefsize);
FX_FILESIZE xref_stm = GetTrailer()->GetDirectIntegerFor("XRefStm");
std::vector<FX_FILESIZE> xref_stream_list{xref_stm};
@@ -648,8 +645,6 @@ void CPDF_Parser::MergeCrossRefObjectsData(
m_CrossRefTable->AddCompressed(obj.obj_num, obj.info.archive.obj_num,
obj.info.archive.obj_index);
break;
- default:
- NOTREACHED();
}
}
}
@@ -778,7 +773,7 @@ bool CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef) {
if (bMainXRef) {
m_CrossRefTable = std::make_unique<CPDF_CrossRefTable>(
std::move(pNewTrailer), pStream->GetObjNum());
- m_CrossRefTable->ShrinkObjectMap(size);
+ m_CrossRefTable->SetObjectMapSize(size);
} else {
m_CrossRefTable = CPDF_CrossRefTable::MergeUp(
std::make_unique<CPDF_CrossRefTable>(std::move(pNewTrailer),
@@ -815,17 +810,33 @@ bool CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef) {
pdfium::span<const uint8_t> seg_span = data_span.subspan(
segindex * total_width, index.obj_count * total_width);
- FX_SAFE_UINT32 dwMaxObjNum = index.start_obj_num;
- dwMaxObjNum += index.obj_count;
- uint32_t dwV5Size =
- m_CrossRefTable->objects_info().empty() ? 0 : GetLastObjNum() + 1;
- if (!dwMaxObjNum.IsValid() || dwMaxObjNum.ValueOrDie() > dwV5Size)
+ FX_SAFE_UINT32 safe_new_size = index.start_obj_num;
+ safe_new_size += index.obj_count;
+ if (!safe_new_size.IsValid()) {
continue;
+ }
+
+ // Until SetObjectMapSize() below has been called by a prior loop iteration,
+ // `current_size` is based on the /Size value parsed in LoadCrossRefV5().
+ // PDFs may not always have the correct /Size. In this case, other PDF
+ // implementations ignore the incorrect size, and PDFium also ignores
+ // incorrect size in trailers for V4 xrefs.
+ const uint32_t current_size =
+ m_CrossRefTable->objects_info().empty() ? 0 : GetLastObjNum() + 1;
+ // So allow `new_size` to be greater than `current_size`, but avoid going
+ // over `kMaxXRefSize`. This works just fine because the loop below checks
+ // against `kMaxObjectNumber`, and the two "max" constants are in sync.
+ const uint32_t new_size =
+ std::min<uint32_t>(safe_new_size.ValueOrDie(), kMaxXRefSize);
+ if (new_size > current_size) {
+ m_CrossRefTable->SetObjectMapSize(new_size);
+ }
for (uint32_t i = 0; i < index.obj_count; ++i) {
const uint32_t obj_num = index.start_obj_num + i;
- if (obj_num >= CPDF_Parser::kMaxObjectNumber)
+ if (obj_num >= kMaxObjectNumber) {
break;
+ }
ProcessCrossRefV5Entry(seg_span.subspan(i * total_width, total_width),
field_widths, obj_num);
@@ -841,13 +852,18 @@ void CPDF_Parser::ProcessCrossRefV5Entry(
pdfium::span<const uint32_t> field_widths,
uint32_t obj_num) {
DCHECK_GE(field_widths.size(), kMinFieldCount);
- ObjectType type = ObjectType::kNotCompressed;
+ ObjectType type;
if (field_widths[0]) {
const uint32_t cross_ref_stream_obj_type =
GetFirstXRefStreamEntry(entry_span, field_widths);
type = GetObjectTypeFromCrossRefStreamType(cross_ref_stream_obj_type);
if (type == ObjectType::kNull)
return;
+ } else {
+ // Per ISO 32000-1:2008 table 17, use the default value of 1 for the xref
+ // stream entry when it is not specified. The `type` assignment is the
+ // equivalent to calling GetObjectTypeFromCrossRefStreamType(1).
+ type = ObjectType::kNotCompressed;
}
const ObjectType existing_type = GetObjectType(obj_num);
diff --git a/core/fpdfapi/parser/cpdf_parser.h b/core/fpdfapi/parser/cpdf_parser.h
index 21dd8aaa1..09dc724e2 100644
--- a/core/fpdfapi/parser/cpdf_parser.h
+++ b/core/fpdfapi/parser/cpdf_parser.h
@@ -159,7 +159,6 @@ class CPDF_Parser {
bool LoadLinearizedAllCrossRefV5(FX_FILESIZE main_xref_offset);
Error LoadLinearizedMainXRefTable();
const CPDF_ObjectStream* GetObjectStream(uint32_t object_number);
- void ShrinkObjectMap(uint32_t size);
// A simple check whether the cross reference table matches with
// the objects.
bool VerifyCrossRefV4();
diff --git a/core/fpdfapi/parser/cpdf_parser_unittest.cpp b/core/fpdfapi/parser/cpdf_parser_unittest.cpp
index efde90eb8..075980700 100644
--- a/core/fpdfapi/parser/cpdf_parser_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_parser_unittest.cpp
@@ -6,6 +6,7 @@
#include <limits>
#include <memory>
+#include <ostream>
#include <string>
#include <utility>
#include <vector>
@@ -22,14 +23,16 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/utils/path_service.h"
+using testing::ElementsAre;
+using testing::Pair;
using testing::Return;
namespace {
-CPDF_CrossRefTable::ObjectInfo GetObjInfo(const CPDF_Parser& parser,
- uint32_t obj_num) {
+CPDF_Parser::ObjectInfo GetObjInfo(const CPDF_Parser& parser,
+ uint32_t obj_num) {
const auto* info = parser.GetCrossRefTable()->GetObjectInfo(obj_num);
- return info ? *info : CPDF_CrossRefTable::ObjectInfo();
+ return info ? *info : CPDF_Parser::ObjectInfo();
}
class TestObjectsHolder final : public CPDF_Parser::ParsedObjectsHolder {
@@ -44,6 +47,54 @@ class TestObjectsHolder final : public CPDF_Parser::ParsedObjectsHolder {
} // namespace
+// Test-only helper to support Gmock. Cannot be in an anonymous namespace.
+bool operator==(const CPDF_Parser::ObjectInfo& lhs,
+ const CPDF_Parser::ObjectInfo& rhs) {
+ if (lhs.type != rhs.type) {
+ return false;
+ }
+
+ if (lhs.gennum != rhs.gennum) {
+ return false;
+ }
+
+ switch (lhs.type) {
+ case CPDF_Parser::ObjectType::kFree:
+ return true;
+ case CPDF_Parser::ObjectType::kNormal:
+ return lhs.pos == rhs.pos;
+ case CPDF_Parser::ObjectType::kCompressed:
+ return lhs.archive.obj_num == rhs.archive.obj_num &&
+ lhs.archive.obj_index == rhs.archive.obj_index;
+ case CPDF_Parser::ObjectType::kObjStream:
+ return false;
+ }
+}
+
+// Test-only helper to let Gmock pretty-print `info`. Cannot be in an anonymous
+// namespace.
+std::ostream& operator<<(std::ostream& os,
+ const CPDF_Parser::ObjectInfo& info) {
+ os << "(";
+ switch (info.type) {
+ case CPDF_Parser::ObjectType::kFree:
+ os << "Free object";
+ break;
+ case CPDF_Parser::ObjectType::kNormal:
+ os << "Normal object, pos: " << info.pos;
+ break;
+ case CPDF_Parser::ObjectType::kCompressed:
+ os << "Compressed object, archive obj_num: " << info.archive.obj_num
+ << ", archive obj_index: " << info.archive.obj_index;
+ break;
+ case CPDF_Parser::ObjectType::kObjStream:
+ os << "ObjectStream object";
+ break;
+ }
+ os << ", gennum: " << info.gennum << ")";
+ return os;
+}
+
// A wrapper class to help test member functions of CPDF_Parser.
class CPDF_TestParser final : public CPDF_Parser {
public:
@@ -361,15 +412,28 @@ TEST(ParserTest, BadStartXrefShouldNotBuildCrossRefTable) {
EXPECT_EQ(0u, parser.GetCrossRefTable()->objects_info().size());
}
-TEST(ParserTest, XrefObjectIndicesTooBig) {
- CPDF_TestParser parser;
+class ParserXRefTest : public testing::Test {
+ public:
+ ParserXRefTest() = default;
+ ~ParserXRefTest() override = default;
+
+ // testing::Test:
+ void SetUp() override {
+ // Satisfy CPDF_Parser's checks, so the test data below can concentrate on
+ // the /XRef stream and avoid also providing other valid dictionaries.
+ dummy_root_ = pdfium::MakeRetain<CPDF_Dictionary>();
+ EXPECT_CALL(parser().object_holder(), ParseIndirectObject)
+ .WillRepeatedly(Return(dummy_root_));
+ }
+
+ CPDF_TestParser& parser() { return parser_; }
- // Satisfy CPDF_Parser's checks, so the test data below can concentrate on the
- // /XRef stream and avoid also providing other valid dictionaries.
- auto dummy_root = pdfium::MakeRetain<CPDF_Dictionary>();
- EXPECT_CALL(parser.object_holder(), ParseIndirectObject)
- .WillRepeatedly(Return(dummy_root));
+ private:
+ RetainPtr<CPDF_Dictionary> dummy_root_;
+ CPDF_TestParser parser_;
+};
+TEST_F(ParserXRefTest, XrefObjectIndicesTooBig) {
// Since /Index starts at 4194303, the object number will go past
// `kMaxObjectNumber`.
static_assert(CPDF_Parser::kMaxObjectNumber == 4194304,
@@ -392,36 +456,30 @@ TEST(ParserTest, XrefObjectIndicesTooBig) {
"startxref\n"
"14\n"
"%%EOF\n";
- ASSERT_TRUE(parser.InitTestFromBuffer(kData));
- EXPECT_EQ(CPDF_Parser::SUCCESS, parser.StartParseInternal());
- ASSERT_TRUE(parser.GetCrossRefTable());
- const auto& objects_info = parser.GetCrossRefTable()->objects_info();
- EXPECT_EQ(2u, objects_info.size());
+ ASSERT_TRUE(parser().InitTestFromBuffer(kData));
+ EXPECT_EQ(CPDF_Parser::SUCCESS, parser().StartParseInternal());
+ EXPECT_FALSE(parser().xref_table_rebuilt());
+ ASSERT_TRUE(parser().GetCrossRefTable());
+ const auto& objects_info = parser().GetCrossRefTable()->objects_info();
// This should be the only object from table. Subsequent objects have object
// numbers that are too big.
- auto first_object_it = objects_info.find(4194303);
- ASSERT_NE(first_object_it, objects_info.end());
- EXPECT_EQ(CPDF_Parser::ObjectType::kNormal, first_object_it->second.type);
- EXPECT_EQ(0, first_object_it->second.pos);
+ CPDF_Parser::ObjectInfo only_valid_object;
+ only_valid_object.type = CPDF_Parser::ObjectType::kNormal;
+ only_valid_object.pos = 0;
// TODO(thestig): Should the xref table contain object 4194305?
// Consider reworking CPDF_Parser's object representation to avoid having to
// store this placeholder object.
- auto placeholder_object_it = objects_info.find(4194305);
- ASSERT_NE(placeholder_object_it, objects_info.end());
- EXPECT_EQ(CPDF_Parser::ObjectType::kFree, placeholder_object_it->second.type);
-}
-
-TEST(ParserTest, XrefHasInvalidArchiveObjectNumber) {
- CPDF_TestParser parser;
+ CPDF_Parser::ObjectInfo placeholder_object;
+ placeholder_object.type = CPDF_Parser::ObjectType::kFree;
+ placeholder_object.pos = 0;
- // Satisfy CPDF_Parser's checks, so the test data below can concentrate on the
- // /XRef stream and avoid also providing other valid dictionaries.
- auto dummy_root = pdfium::MakeRetain<CPDF_Dictionary>();
- EXPECT_CALL(parser.object_holder(), ParseIndirectObject)
- .WillRepeatedly(Return(dummy_root));
+ EXPECT_THAT(objects_info, ElementsAre(Pair(4194303, only_valid_object),
+ Pair(4194305, placeholder_object)));
+}
+TEST_F(ParserXRefTest, XrefHasInvalidArchiveObjectNumber) {
// 0xFF in the first object in the xref object stream is invalid.
const unsigned char kData[] =
"%PDF1-7\n%\xa0\xf2\xa4\xf4\n"
@@ -440,23 +498,325 @@ TEST(ParserTest, XrefHasInvalidArchiveObjectNumber) {
"startxref\n"
"14\n"
"%%EOF\n";
- ASSERT_TRUE(parser.InitTestFromBuffer(kData));
- EXPECT_EQ(CPDF_Parser::SUCCESS, parser.StartParseInternal());
+ ASSERT_TRUE(parser().InitTestFromBuffer(kData));
+ EXPECT_EQ(CPDF_Parser::SUCCESS, parser().StartParseInternal());
+ EXPECT_FALSE(parser().xref_table_rebuilt());
- const CPDF_CrossRefTable* cross_ref_table = parser.GetCrossRefTable();
+ const CPDF_CrossRefTable* cross_ref_table = parser().GetCrossRefTable();
ASSERT_TRUE(cross_ref_table);
EXPECT_EQ(7u, cross_ref_table->trailer_object_number());
const auto& objects_info = cross_ref_table->objects_info();
- EXPECT_EQ(2u, objects_info.size());
-
- // Skip over the first object, and continue parsing the remaining objects.
- auto second_object_it = objects_info.find(1);
- ASSERT_NE(second_object_it, objects_info.end());
- EXPECT_EQ(CPDF_Parser::ObjectType::kNormal, second_object_it->second.type);
- EXPECT_EQ(15, second_object_it->second.pos);
-
- auto third_object_it = objects_info.find(2);
- ASSERT_NE(third_object_it, objects_info.end());
- EXPECT_EQ(CPDF_Parser::ObjectType::kNormal, third_object_it->second.type);
- EXPECT_EQ(18, third_object_it->second.pos);
+
+ // The expectation is for the parser to skip over the first object, and
+ // continue parsing the remaining objects. So these are the second and third
+ // objects.
+ CPDF_Parser::ObjectInfo expected_objects[2];
+ expected_objects[0].type = CPDF_Parser::ObjectType::kNormal;
+ expected_objects[0].pos = 15;
+ expected_objects[1].type = CPDF_Parser::ObjectType::kNormal;
+ expected_objects[1].pos = 18;
+
+ EXPECT_THAT(objects_info, ElementsAre(Pair(1, expected_objects[0]),
+ Pair(2, expected_objects[1])));
+}
+
+TEST_F(ParserXRefTest, XrefHasInvalidObjectType) {
+ // The XRef object is a dictionary and not a stream.
+ const unsigned char kData[] =
+ "%PDF1-7\n%\xa0\xf2\xa4\xf4\n"
+ "7 0 obj <<\n"
+ " /Filter /ASCIIHexDecode\n"
+ " /Root 1 0 R\n"
+ " /Size 3\n"
+ " /W [1 1 1]\n"
+ ">>\n"
+ "endobj\n"
+ "startxref\n"
+ "14\n"
+ "%%EOF\n";
+
+ ASSERT_TRUE(parser().InitTestFromBuffer(kData));
+ EXPECT_EQ(CPDF_Parser::FORMAT_ERROR, parser().StartParseInternal());
+}
+
+TEST_F(ParserXRefTest, XrefHasInvalidPrevValue) {
+ // The /Prev value is an absolute offset, so it should never be negative.
+ const unsigned char kData[] =
+ "%PDF1-7\n%\xa0\xf2\xa4\xf4\n"
+ "7 0 obj <<\n"
+ " /Filter /ASCIIHexDecode\n"
+ " /Root 1 0 R\n"
+ " /Size 3\n"
+ " /W [1 1 1]\n"
+ " /Prev -1\n"
+ ">>\n"
+ "stream\n"
+ "02 FF 00\n"
+ "01 0F 00\n"
+ "01 12 00\n"
+ "endstream\n"
+ "endobj\n"
+ "startxref\n"
+ "14\n"
+ "%%EOF\n";
+
+ ASSERT_TRUE(parser().InitTestFromBuffer(kData));
+ EXPECT_EQ(CPDF_Parser::FORMAT_ERROR, parser().StartParseInternal());
+}
+
+TEST_F(ParserXRefTest, XrefHasInvalidSizeValue) {
+ // The /Size value should never be negative.
+ const unsigned char kData[] =
+ "%PDF1-7\n%\xa0\xf2\xa4\xf4\n"
+ "7 0 obj <<\n"
+ " /Filter /ASCIIHexDecode\n"
+ " /Root 1 0 R\n"
+ " /Size 3\n"
+ " /W [1 1 1]\n"
+ " /Size -1\n"
+ ">>\n"
+ "stream\n"
+ "02 FF 00\n"
+ "01 0F 00\n"
+ "01 12 00\n"
+ "endstream\n"
+ "endobj\n"
+ "startxref\n"
+ "14\n"
+ "%%EOF\n";
+
+ ASSERT_TRUE(parser().InitTestFromBuffer(kData));
+ EXPECT_EQ(CPDF_Parser::FORMAT_ERROR, parser().StartParseInternal());
+}
+
+TEST_F(ParserXRefTest, XrefHasInvalidWidth) {
+ // The /W array needs to have at least 3 values.
+ const unsigned char kData[] =
+ "%PDF1-7\n%\xa0\xf2\xa4\xf4\n"
+ "7 0 obj <<\n"
+ " /Filter /ASCIIHexDecode\n"
+ " /Root 1 0 R\n"
+ " /Size 3\n"
+ " /W [1 1]\n"
+ ">>\n"
+ "stream\n"
+ "02 FF 00\n"
+ "01 0F 00\n"
+ "01 12 00\n"
+ "endstream\n"
+ "endobj\n"
+ "startxref\n"
+ "14\n"
+ "%%EOF\n";
+
+ ASSERT_TRUE(parser().InitTestFromBuffer(kData));
+
+ // StartParseInternal() succeeded not because XRef parsing succeeded, but
+ // because RebuildCrossRef() got lucky with the data stream. Therefore, don't
+ // bother checking the garbage output.
+ EXPECT_EQ(CPDF_Parser::SUCCESS, parser().StartParseInternal());
+ EXPECT_TRUE(parser().xref_table_rebuilt());
+}
+
+TEST_F(ParserXRefTest, XrefFirstWidthEntryIsZero) {
+ // When the first /W array entry is 0, it implies the objects are all of the
+ // normal type.
+ const unsigned char kData[] =
+ "%PDF1-7\n%\xa0\xf2\xa4\xf4\n"
+ "7 0 obj <<\n"
+ " /Filter /ASCIIHexDecode\n"
+ " /Root 1 0 R\n"
+ " /Size 2\n"
+ " /W [0 1 1]\n"
+ ">>\n"
+ "stream\n"
+ "0F 00\n"
+ "12 00\n"
+ "endstream\n"
+ "endobj\n"
+ "startxref\n"
+ "14\n"
+ "%%EOF\n";
+
+ ASSERT_TRUE(parser().InitTestFromBuffer(kData));
+ EXPECT_EQ(CPDF_Parser::SUCCESS, parser().StartParseInternal());
+ EXPECT_FALSE(parser().xref_table_rebuilt());
+ ASSERT_TRUE(parser().GetCrossRefTable());
+ const auto& objects_info = parser().GetCrossRefTable()->objects_info();
+
+ CPDF_Parser::ObjectInfo expected_result[2];
+ expected_result[0].type = CPDF_Parser::ObjectType::kNormal;
+ expected_result[0].pos = 15;
+ expected_result[1].type = CPDF_Parser::ObjectType::kNormal;
+ expected_result[1].pos = 18;
+ EXPECT_THAT(objects_info, ElementsAre(Pair(0, expected_result[0]),
+ Pair(1, expected_result[1])));
+}
+
+TEST_F(ParserXRefTest, XrefWithValidIndex) {
+ // The /Index specifies objects (2), (4, 5), (80, 81, 82).
+ const unsigned char kData[] =
+ "%PDF1-7\n%\xa0\xf2\xa4\xf4\n"
+ "7 0 obj <<\n"
+ " /Filter /ASCIIHexDecode\n"
+ " /Root 1 0 R\n"
+ " /Size 83\n"
+ " /Index [2 1 4 2 80 3]\n"
+ " /W [1 1 1]\n"
+ ">>\n"
+ "stream\n"
+ "01 00 00\n"
+ "01 0F 00\n"
+ "01 12 00\n"
+ "01 20 00\n"
+ "01 22 00\n"
+ "01 25 00\n"
+ "endstream\n"
+ "endobj\n"
+ "startxref\n"
+ "14\n"
+ "%%EOF\n";
+
+ ASSERT_TRUE(parser().InitTestFromBuffer(kData));
+ EXPECT_EQ(CPDF_Parser::SUCCESS, parser().StartParseInternal());
+ EXPECT_FALSE(parser().xref_table_rebuilt());
+ ASSERT_TRUE(parser().GetCrossRefTable());
+ const auto& objects_info = parser().GetCrossRefTable()->objects_info();
+
+ CPDF_Parser::ObjectInfo expected_result[6];
+ expected_result[0].type = CPDF_Parser::ObjectType::kNormal;
+ expected_result[0].pos = 0;
+ expected_result[1].type = CPDF_Parser::ObjectType::kNormal;
+ expected_result[1].pos = 15;
+ expected_result[2].type = CPDF_Parser::ObjectType::kNormal;
+ expected_result[2].pos = 18;
+ expected_result[3].type = CPDF_Parser::ObjectType::kNormal;
+ expected_result[3].pos = 32;
+ expected_result[4].type = CPDF_Parser::ObjectType::kNormal;
+ expected_result[4].pos = 34;
+ expected_result[5].type = CPDF_Parser::ObjectType::kNormal;
+ expected_result[5].pos = 37;
+ EXPECT_THAT(
+ objects_info,
+ ElementsAre(Pair(2, expected_result[0]), Pair(4, expected_result[1]),
+ Pair(5, expected_result[2]), Pair(80, expected_result[3]),
+ Pair(81, expected_result[4]), Pair(82, expected_result[5])));
+}
+
+TEST_F(ParserXRefTest, XrefIndexWithRepeatedObject) {
+ // The /Index specifies objects (2, 3), (3). AKA the sub-sections overlap.
+ const unsigned char kData[] =
+ "%PDF1-7\n%\xa0\xf2\xa4\xf4\n"
+ "7 0 obj <<\n"
+ " /Filter /ASCIIHexDecode\n"
+ " /Root 1 0 R\n"
+ " /Size 4\n"
+ " /Index [2 2 3 1]\n"
+ " /W [1 1 1]\n"
+ ">>\n"
+ "stream\n"
+ "01 00 00\n"
+ "01 0F 00\n"
+ "01 12 00\n"
+ "endstream\n"
+ "endobj\n"
+ "startxref\n"
+ "14\n"
+ "%%EOF\n";
+
+ ASSERT_TRUE(parser().InitTestFromBuffer(kData));
+ EXPECT_EQ(CPDF_Parser::SUCCESS, parser().StartParseInternal());
+ EXPECT_FALSE(parser().xref_table_rebuilt());
+ ASSERT_TRUE(parser().GetCrossRefTable());
+ const auto& objects_info = parser().GetCrossRefTable()->objects_info();
+
+ CPDF_Parser::ObjectInfo expected_result[2];
+ expected_result[0].type = CPDF_Parser::ObjectType::kNormal;
+ expected_result[0].pos = 0;
+ expected_result[1].type = CPDF_Parser::ObjectType::kNormal;
+ // Since the /Index does not follow the spec, this is one of the 2 possible
+ // values that a parser can come up with.
+ expected_result[1].pos = 15;
+ EXPECT_THAT(objects_info, ElementsAre(Pair(2, expected_result[0]),
+ Pair(3, expected_result[1])));
+}
+
+TEST_F(ParserXRefTest, XrefIndexWithOutOfOrderObjects) {
+ // The /Index specifies objects (3, 4), (2), which is not in ascending order.
+ const unsigned char kData[] =
+ "%PDF1-7\n%\xa0\xf2\xa4\xf4\n"
+ "7 0 obj <<\n"
+ " /Filter /ASCIIHexDecode\n"
+ " /Root 1 0 R\n"
+ " /Size 5\n"
+ " /Index [3 2 2 1]\n"
+ " /W [1 1 1]\n"
+ ">>\n"
+ "stream\n"
+ "01 00 00\n"
+ "01 0F 00\n"
+ "01 12 00\n"
+ "endstream\n"
+ "endobj\n"
+ "startxref\n"
+ "14\n"
+ "%%EOF\n";
+
+ ASSERT_TRUE(parser().InitTestFromBuffer(kData));
+ EXPECT_EQ(CPDF_Parser::SUCCESS, parser().StartParseInternal());
+ EXPECT_FALSE(parser().xref_table_rebuilt());
+ ASSERT_TRUE(parser().GetCrossRefTable());
+ const auto& objects_info = parser().GetCrossRefTable()->objects_info();
+
+ // Although the /Index does not follow the spec, the parser tolerates it.
+ CPDF_Parser::ObjectInfo expected_result[3];
+ expected_result[0].type = CPDF_Parser::ObjectType::kNormal;
+ expected_result[0].pos = 18;
+ expected_result[1].type = CPDF_Parser::ObjectType::kNormal;
+ expected_result[1].pos = 0;
+ expected_result[2].type = CPDF_Parser::ObjectType::kNormal;
+ expected_result[2].pos = 15;
+ EXPECT_THAT(objects_info, ElementsAre(Pair(2, expected_result[0]),
+ Pair(3, expected_result[1]),
+ Pair(4, expected_result[2])));
+}
+
+TEST_F(ParserXRefTest, XrefWithIndexAndWrongSize) {
+ // The /Index specifies objects (2), (80, 81), so the /Size should be 82,
+ // but is actually 81.
+ const unsigned char kData[] =
+ "%PDF1-7\n%\xa0\xf2\xa4\xf4\n"
+ "7 0 obj <<\n"
+ " /Filter /ASCIIHexDecode\n"
+ " /Root 1 0 R\n"
+ " /Size 81\n"
+ " /Index [2 1 80 2]\n"
+ " /W [1 1 1]\n"
+ ">>\n"
+ "stream\n"
+ "01 00 00\n"
+ "01 0F 00\n"
+ "01 12 00\n"
+ "endstream\n"
+ "endobj\n"
+ "startxref\n"
+ "14\n"
+ "%%EOF\n";
+
+ ASSERT_TRUE(parser().InitTestFromBuffer(kData));
+ EXPECT_EQ(CPDF_Parser::SUCCESS, parser().StartParseInternal());
+ EXPECT_FALSE(parser().xref_table_rebuilt());
+ ASSERT_TRUE(parser().GetCrossRefTable());
+ const auto& objects_info = parser().GetCrossRefTable()->objects_info();
+
+ CPDF_Parser::ObjectInfo expected_result[3];
+ expected_result[0].type = CPDF_Parser::ObjectType::kNormal;
+ expected_result[0].pos = 0;
+ expected_result[1].type = CPDF_Parser::ObjectType::kNormal;
+ expected_result[1].pos = 15;
+ expected_result[2].type = CPDF_Parser::ObjectType::kNormal;
+ expected_result[2].pos = 18;
+ EXPECT_THAT(objects_info, ElementsAre(Pair(2, expected_result[0]),
+ Pair(80, expected_result[1]),
+ Pair(81, expected_result[2])));
}
diff --git a/core/fpdfapi/parser/cpdf_security_handler.cpp b/core/fpdfapi/parser/cpdf_security_handler.cpp
index ff17c59e8..5f2883d16 100644
--- a/core/fpdfapi/parser/cpdf_security_handler.cpp
+++ b/core/fpdfapi/parser/cpdf_security_handler.cpp
@@ -19,6 +19,7 @@
#include "core/fpdfapi/parser/cpdf_object.h"
#include "core/fpdfapi/parser/cpdf_string.h"
#include "core/fxcrt/data_vector.h"
+#include "core/fxcrt/fx_memcpy_wrappers.h"
#include "core/fxcrt/fx_random.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
@@ -35,9 +36,10 @@ void GetPassCode(const ByteString& password, pdfium::span<uint8_t> output) {
DCHECK_EQ(sizeof(kDefaultPasscode), output.size());
size_t len = std::min(password.GetLength(), output.size());
size_t remaining = output.size() - len;
- memcpy(output.data(), password.raw_str(), len);
- if (remaining)
+ FXSYS_memcpy(output.data(), password.raw_str(), len);
+ if (remaining) {
memcpy(&output[len], kDefaultPasscode, remaining);
+ }
}
void CalcEncryptKey(const CPDF_Dictionary* pEncrypt,
diff --git a/core/fpdfapi/parser/cpdf_security_handler_embeddertest.cpp b/core/fpdfapi/parser/cpdf_security_handler_embeddertest.cpp
index f2c5ac1ea..cf1a2b59e 100644
--- a/core/fpdfapi/parser/cpdf_security_handler_embeddertest.cpp
+++ b/core/fpdfapi/parser/cpdf_security_handler_embeddertest.cpp
@@ -136,8 +136,9 @@ TEST_F(CPDFSecurityHandlerEmbedderTest, OwnerPassword) {
TEST_F(CPDFSecurityHandlerEmbedderTest, PasswordAfterGenerateSave) {
const char* checksum = []() {
- if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "df9fe67555b7ceb59c99036e8d2c1c76";
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "ad97491cab71c02f1f4ef5ba0a7b5593";
+ }
#if BUILDFLAG(IS_APPLE)
return "2a308e8cc20a6221112c387d122075a8";
#else
diff --git a/core/fpdfapi/parser/cpdf_simple_parser.h b/core/fpdfapi/parser/cpdf_simple_parser.h
index e4bf0c088..c953be6b2 100644
--- a/core/fpdfapi/parser/cpdf_simple_parser.h
+++ b/core/fpdfapi/parser/cpdf_simple_parser.h
@@ -10,7 +10,7 @@
#include <stdint.h>
#include "core/fxcrt/bytestring.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_SimpleParser {
public:
diff --git a/core/fpdfapi/parser/cpdf_simple_parser_unittest.cpp b/core/fpdfapi/parser/cpdf_simple_parser_unittest.cpp
index 965d5778e..77483b394 100644
--- a/core/fpdfapi/parser/cpdf_simple_parser_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_simple_parser_unittest.cpp
@@ -7,9 +7,10 @@
#include <iterator>
#include "core/fpdfapi/parser/fpdf_parser_utility.h"
+#include "core/fxcrt/fx_memcpy_wrappers.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/test_support.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
TEST(SimpleParserTest, GetWord) {
static const pdfium::StrFuncTestData test_data[] = {
@@ -57,8 +58,8 @@ TEST(SimpleParserTest, 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))
+ EXPECT_EQ(0, FXSYS_memcmp(data.expected, word.unterminated_c_str(),
+ data.expected_size))
<< " for case " << i;
}
}
diff --git a/core/fpdfapi/parser/cpdf_stream_acc.h b/core/fpdfapi/parser/cpdf_stream_acc.h
index 1f0e726d0..74657dd34 100644
--- a/core/fpdfapi/parser/cpdf_stream_acc.h
+++ b/core/fpdfapi/parser/cpdf_stream_acc.h
@@ -15,7 +15,7 @@
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/retain_ptr.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_Dictionary;
class CPDF_Stream;
diff --git a/core/fpdfapi/parser/cpdf_syntax_parser.h b/core/fpdfapi/parser/cpdf_syntax_parser.h
index ed79af2f7..d3f5747ec 100644
--- a/core/fpdfapi/parser/cpdf_syntax_parser.h
+++ b/core/fpdfapi/parser/cpdf_syntax_parser.h
@@ -19,7 +19,7 @@
#include "core/fxcrt/string_pool_template.h"
#include "core/fxcrt/unowned_ptr.h"
#include "core/fxcrt/weak_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_Dictionary;
class CPDF_IndirectObjectHolder;
diff --git a/core/fpdfapi/parser/fpdf_parser_decode.cpp b/core/fpdfapi/parser/fpdf_parser_decode.cpp
index 6f29b7a83..1fbee0346 100644
--- a/core/fpdfapi/parser/fpdf_parser_decode.cpp
+++ b/core/fpdfapi/parser/fpdf_parser_decode.cpp
@@ -8,10 +8,12 @@
#include <ctype.h>
#include <limits.h>
+#include <stddef.h>
#include <algorithm>
#include <utility>
+#include "build/build_config.h"
#include "constants/stream_dict_common.h"
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
@@ -22,6 +24,7 @@
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/span_util.h"
+#include "core/fxcrt/utf16.h"
#include "third_party/base/check.h"
#include "third_party/base/containers/contains.h"
@@ -472,7 +475,7 @@ bool PDF_DataDecode(pdfium::span<const uint8_t> src_span,
}
WideString PDF_DecodeText(pdfium::span<const uint8_t> span) {
- int dest_pos = 0;
+ size_t dest_pos = 0;
WideString result;
if (span.size() >= 2 && ((span[0] == 0xfe && span[1] == 0xff) ||
(span[0] == 0xff && span[1] == 0xfe))) {
@@ -485,6 +488,10 @@ WideString PDF_DecodeText(pdfium::span<const uint8_t> span) {
span[0] == 0xfe ? GetUnicodeFromBigEndianBytes
: GetUnicodeFromLittleEndianBytes;
const uint8_t* unicode_str = &span[2];
+
+#if defined(WCHAR_T_IS_UTF32)
+ char16_t high_surrogate = 0;
+#endif // defined(WCHAR_T_IS_UTF32)
for (size_t i = 0; i < max_chars * 2; i += 2) {
uint16_t unicode = GetUnicodeFromBytes(unicode_str + i);
@@ -505,8 +512,34 @@ WideString PDF_DecodeText(pdfium::span<const uint8_t> span) {
break;
}
+#if defined(WCHAR_T_IS_UTF32)
+ // TODO(crbug.com/pdfium/2031): Always use UTF-16.
+ if (high_surrogate) {
+ char16_t previous_high_surrogate = high_surrogate;
+ high_surrogate = 0;
+
+ if (pdfium::IsLowSurrogate(unicode)) {
+ dest_buf[dest_pos++] =
+ pdfium::SurrogatePair(previous_high_surrogate, unicode)
+ .ToCodePoint();
+ continue;
+ }
+ dest_buf[dest_pos++] = previous_high_surrogate;
+ }
+
+ if (pdfium::IsHighSurrogate(unicode)) {
+ high_surrogate = unicode;
+ continue;
+ }
+#endif // defined(WCHAR_T_IS_UTF32)
dest_buf[dest_pos++] = unicode;
}
+
+#if defined(WCHAR_T_IS_UTF32)
+ if (high_surrogate) {
+ dest_buf[dest_pos++] = high_surrogate;
+ }
+#endif // defined(WCHAR_T_IS_UTF32)
} else {
pdfium::span<wchar_t> dest_buf = result.GetBuffer(span.size());
for (size_t i = 0; i < span.size(); ++i)
@@ -545,18 +578,35 @@ ByteString PDF_EncodeText(WideStringView str) {
}
size_t dest_index = 0;
- size_t encLen = len * 2 + 2;
{
+#if defined(WCHAR_T_IS_UTF32)
+ // 2 or 4 bytes required per UTF-32 code unit.
+ pdfium::span<uint8_t> dest_buf =
+ pdfium::as_writable_bytes(result.GetBuffer(len * 4 + 2));
+#else
+ // 2 bytes required per UTF-16 code unit.
pdfium::span<uint8_t> dest_buf =
- pdfium::as_writable_bytes(result.GetBuffer(encLen));
+ pdfium::as_writable_bytes(result.GetBuffer(len * 2 + 2));
+#endif // defined(WCHAR_T_IS_UTF32)
+
dest_buf[dest_index++] = 0xfe;
dest_buf[dest_index++] = 0xff;
for (size_t j = 0; j < len; ++j) {
+#if defined(WCHAR_T_IS_UTF32)
+ if (pdfium::IsSupplementary(str[j])) {
+ pdfium::SurrogatePair pair(str[j]);
+ dest_buf[dest_index++] = pair.high() >> 8;
+ dest_buf[dest_index++] = static_cast<uint8_t>(pair.high());
+ dest_buf[dest_index++] = pair.low() >> 8;
+ dest_buf[dest_index++] = static_cast<uint8_t>(pair.low());
+ continue;
+ }
+#endif // defined(WCHAR_T_IS_UTF32)
dest_buf[dest_index++] = str[j] >> 8;
dest_buf[dest_index++] = static_cast<uint8_t>(str[j]);
}
}
- result.ReleaseBuffer(encLen);
+ result.ReleaseBuffer(dest_index);
return result;
}
diff --git a/core/fpdfapi/parser/fpdf_parser_decode.h b/core/fpdfapi/parser/fpdf_parser_decode.h
index a437455d1..6e146b552 100644
--- a/core/fpdfapi/parser/fpdf_parser_decode.h
+++ b/core/fpdfapi/parser/fpdf_parser_decode.h
@@ -18,7 +18,7 @@
#include "core/fxcrt/fx_string.h"
#include "core/fxcrt/retain_ptr.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_Array;
class CPDF_Dictionary;
diff --git a/core/fpdfapi/parser/fpdf_parser_decode_unittest.cpp b/core/fpdfapi/parser/fpdf_parser_decode_unittest.cpp
index 2c2074b66..cd3e82a1c 100644
--- a/core/fpdfapi/parser/fpdf_parser_decode_unittest.cpp
+++ b/core/fpdfapi/parser/fpdf_parser_decode_unittest.cpp
@@ -4,6 +4,9 @@
#include "core/fpdfapi/parser/fpdf_parser_decode.h"
+#include <stddef.h>
+#include <stdint.h>
+
#include <iterator>
#include "core/fpdfapi/parser/cpdf_array.h"
@@ -12,9 +15,29 @@
#include "core/fpdfapi/parser/cpdf_name.h"
#include "core/fpdfapi/parser/cpdf_reference.h"
#include "core/fpdfapi/parser/cpdf_string.h"
+#include "core/fxcrt/bytestring.h"
#include "core/fxcrt/fx_memory_wrappers.h"
+#include "core/fxcrt/string_view_template.h"
+#include "core/fxcrt/widestring.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/test_support.h"
+#include "third_party/base/containers/span.h"
+
+namespace {
+
+// Converts a string literal into a `uint8_t` span.
+template <size_t N>
+pdfium::span<const uint8_t> ToSpan(const char (&array)[N]) {
+ return pdfium::span(reinterpret_cast<const uint8_t*>(array), N - 1);
+}
+
+// Converts a string literal into a `ByteString`.
+template <size_t N>
+ByteString ToByteString(const char (&array)[N]) {
+ return ByteString(array, N - 1);
+}
+
+} // namespace
TEST(ParserDecodeTest, ValidateDecoderPipeline) {
{
@@ -379,82 +402,102 @@ TEST(ParserDecodeTest, HexDecode) {
}
TEST(ParserDecodeTest, DecodeText) {
- const struct DecodeTestData {
- const char* input;
- size_t input_length;
- const wchar_t* expected_output;
- size_t expected_length;
- } kTestData[] = {
- // Empty src string.
- {"", 0, L"", 0},
- // ASCII text.
- {"the quick\tfox", 13, L"the quick\tfox", 13},
- // Unicode text.
- {"\xFE\xFF\x03\x30\x03\x31", 6, L"\x0330\x0331", 2},
- // More Unicode text.
- {"\xFE\xFF\x7F\x51\x98\x75\x00\x20\x56\xFE\x72\x47\x00"
- "\x20\x8D\x44\x8B\xAF\x66\xF4\x59\x1A\x00\x20\x00\xBB",
- 26,
- L"\x7F51\x9875\x0020\x56FE\x7247\x0020"
- L"\x8D44\x8BAF\x66F4\x591A\x0020\x00BB",
- 12},
- // Unicode escape sequence. https://crbug.com/pdfium/182
- {"\xFE\xFF\x00\x1B\x6A\x61\x00\x1B\x00\x20\x53\x70\x52\x37", 14,
- L"\x0020\x5370\x5237", 3},
- {"\xFE\xFF\x00\x1B\x6A\x61\x00\x1B\x00\x20\x53\x70\x52\x37\x29", 15,
- L"\x0020\x5370\x5237", 3},
- {"\xFE\xFF\x00\x1B\x6A\x61\x4A\x50\x00\x1B\x00\x20\x53\x70\x52\x37", 16,
- L"\x0020\x5370\x5237", 3},
- {"\xFE\xFF\x00\x20\x00\x1B\x6A\x61\x4A\x50\x00\x1B\x52\x37", 14,
- L"\x0020\x5237", 2},
- // https://crbug.com/1001159
- {"\xFE\xFF\x00\x1B\x00\x1B", 6, L"", 0},
- {"\xFE\xFF\x00\x1B\x00\x1B\x20", 7, L"", 0},
- {"\xFE\xFF\x00\x1B\x00\x1B\x00\x20", 8, L"\x0020", 1},
- };
+ // Empty src string.
+ EXPECT_EQ(L"", PDF_DecodeText(ToSpan("")));
- for (const auto& test_case : kTestData) {
- WideString output = PDF_DecodeText(
- pdfium::make_span(reinterpret_cast<const uint8_t*>(test_case.input),
- test_case.input_length));
- ASSERT_EQ(test_case.expected_length, output.GetLength())
- << "for case " << test_case.input;
- const wchar_t* str_ptr = output.c_str();
- for (size_t i = 0; i < test_case.expected_length; ++i) {
- EXPECT_EQ(test_case.expected_output[i], str_ptr[i])
- << "for case " << test_case.input << " char " << i;
- }
- }
+ // ASCII text.
+ EXPECT_EQ(L"the quick\tfox", PDF_DecodeText(ToSpan("the quick\tfox")));
+
+ // Unicode text.
+ EXPECT_EQ(L"\x0330\x0331",
+ PDF_DecodeText(ToSpan("\xFE\xFF\x03\x30\x03\x31")));
+
+ // More Unicode text.
+ EXPECT_EQ(
+ L"\x7F51\x9875\x0020\x56FE\x7247\x0020"
+ L"\x8D44\x8BAF\x66F4\x591A\x0020\x00BB",
+ PDF_DecodeText(
+ ToSpan("\xFE\xFF\x7F\x51\x98\x75\x00\x20\x56\xFE\x72\x47\x00"
+ "\x20\x8D\x44\x8B\xAF\x66\xF4\x59\x1A\x00\x20\x00\xBB")));
+
+ // Supplementary Unicode text.
+ EXPECT_EQ(L"🎨", PDF_DecodeText(ToSpan("\xFE\xFF\xD8\x3C\xDF\xA8")));
+}
+
+// https://crbug.com/pdfium/182
+TEST(ParserDecodeTest, DecodeTextWithUnicodeEscapes) {
+ EXPECT_EQ(L"\x0020\x5370\x5237",
+ PDF_DecodeText(ToSpan(
+ "\xFE\xFF\x00\x1B\x6A\x61\x00\x1B\x00\x20\x53\x70\x52\x37")));
+ EXPECT_EQ(
+ L"\x0020\x5370\x5237",
+ PDF_DecodeText(ToSpan(
+ "\xFE\xFF\x00\x1B\x6A\x61\x00\x1B\x00\x20\x53\x70\x52\x37\x29")));
+ EXPECT_EQ(
+ L"\x0020\x5370\x5237",
+ PDF_DecodeText(ToSpan(
+ "\xFE\xFF\x00\x1B\x6A\x61\x4A\x50\x00\x1B\x00\x20\x53\x70\x52\x37")));
+ EXPECT_EQ(L"\x0020\x5237",
+ PDF_DecodeText(ToSpan(
+ "\xFE\xFF\x00\x20\x00\x1B\x6A\x61\x4A\x50\x00\x1B\x52\x37")));
+}
+
+// https://crbug.com/1001159
+TEST(ParserDecodeTest, DecodeTextWithInvalidUnicodeEscapes) {
+ EXPECT_EQ(L"", PDF_DecodeText(ToSpan("\xFE\xFF\x00\x1B\x00\x1B")));
+ EXPECT_EQ(L"", PDF_DecodeText(ToSpan("\xFE\xFF\x00\x1B\x00\x1B\x20")));
+ EXPECT_EQ(L"\x0020",
+ PDF_DecodeText(ToSpan("\xFE\xFF\x00\x1B\x00\x1B\x00\x20")));
+}
+
+TEST(ParserDecodeTest, DecodeTextWithUnpairedSurrogates) {
+ EXPECT_EQ(L"\xD800", PDF_DecodeText(ToSpan("\xFE\xFF\xD8\x00"))) << "High";
+ EXPECT_EQ(L"\xDC00", PDF_DecodeText(ToSpan("\xFE\xFF\xDC\x00"))) << "Low";
+ EXPECT_EQ(L"\xD800🎨",
+ PDF_DecodeText(ToSpan("\xFE\xFF\xD8\x00\xD8\x3C\xDF\xA8")))
+ << "High-high";
+ EXPECT_EQ(L"🎨\xDC00",
+ PDF_DecodeText(ToSpan("\xFE\xFF\xD8\x3C\xDF\xA8\xDC\x00")))
+ << "Low-low";
}
TEST(ParserDecodeTest, EncodeText) {
- const struct EncodeTestData {
- const wchar_t* input;
- const char* expected_output;
- size_t expected_length;
- } kTestData[] = {
- // Empty src string.
- {L"", "", 0},
- // ASCII text.
- {L"the quick\tfox", "the quick\tfox", 13},
- // Unicode text.
- {L"\x0330\x0331", "\xFE\xFF\x03\x30\x03\x31", 6},
- // More Unicode text.
- {L"\x7F51\x9875\x0020\x56FE\x7247\x0020"
- L"\x8D44\x8BAF\x66F4\x591A\x0020\x00BB",
- "\xFE\xFF\x7F\x51\x98\x75\x00\x20\x56\xFE\x72\x47\x00"
- "\x20\x8D\x44\x8B\xAF\x66\xF4\x59\x1A\x00\x20\x00\xBB",
- 26},
- };
+ // Empty src string.
+ EXPECT_EQ("", PDF_EncodeText(L""));
- for (const auto& test_case : kTestData) {
- ByteString output = PDF_EncodeText(test_case.input);
- ASSERT_EQ(test_case.expected_length, output.GetLength())
- << "for case " << test_case.input;
- 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 " << test_case.input << " char " << j;
+ // ASCII text.
+ EXPECT_EQ("the quick\tfox", PDF_EncodeText(L"the quick\tfox"));
+
+ // Unicode text.
+ EXPECT_EQ("\xFE\xFF\x03\x30\x03\x31", PDF_EncodeText(L"\x0330\x0331"));
+
+ // More Unicode text.
+ EXPECT_EQ(
+ ToByteString("\xFE\xFF\x7F\x51\x98\x75\x00\x20\x56\xFE\x72\x47\x00"
+ "\x20\x8D\x44\x8B\xAF\x66\xF4\x59\x1A\x00\x20\x00\xBB"),
+ PDF_EncodeText(L"\x7F51\x9875\x0020\x56FE\x7247\x0020"
+ L"\x8D44\x8BAF\x66F4\x591A\x0020\x00BB"));
+
+ // Supplementary Unicode text.
+ EXPECT_EQ("\xFE\xFF\xD8\x3C\xDF\xA8", PDF_EncodeText(L"🎨"));
+}
+
+TEST(ParserDecodeTest, RoundTripText) {
+ for (int pdf_code_point = 0; pdf_code_point < 256; ++pdf_code_point) {
+ ByteString original(static_cast<char>(pdf_code_point));
+ ByteString reencoded =
+ PDF_EncodeText(PDF_DecodeText(original.raw_span()).AsStringView());
+
+ switch (pdf_code_point) {
+ case 0x7F:
+ case 0x9F:
+ case 0xAD:
+ EXPECT_EQ(ByteString('\0'), reencoded) << "PDFDocEncoding undefined";
+ break;
+
+ default:
+ EXPECT_EQ(original, reencoded) << "PDFDocEncoding: " << pdf_code_point;
+ break;
}
}
}
diff --git a/core/fpdfapi/parser/fpdf_parser_utility.cpp b/core/fpdfapi/parser/fpdf_parser_utility.cpp
index 950753e3d..c2f626aaa 100644
--- a/core/fpdfapi/parser/fpdf_parser_utility.cpp
+++ b/core/fpdfapi/parser/fpdf_parser_utility.cpp
@@ -21,14 +21,13 @@
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/fx_stream.h"
#include "third_party/base/check.h"
-#include "third_party/base/notreached.h"
// Indexed by 8-bit character code, contains either:
// 'W' - for whitespace: NUL, TAB, CR, LF, FF, SPACE, 0x80, 0xff
// 'N' - for numeric: 0123456789+-.
// 'D' - for delimiter: %()/<>[]{}
// 'R' - otherwise.
-const char PDF_CharType[256] = {
+const char kPDFCharTypes[256] = {
// NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO
// SI
'W', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'W', 'W', 'R', 'W', 'W', 'R',
@@ -253,9 +252,6 @@ std::ostream& operator<<(std::ostream& buf, const CPDF_Object* pObj) {
buf << "\r\nendstream";
break;
}
- default:
- NOTREACHED();
- break;
}
return buf;
}
diff --git a/core/fpdfapi/parser/fpdf_parser_utility.h b/core/fpdfapi/parser/fpdf_parser_utility.h
index 259495e15..521e20a77 100644
--- a/core/fpdfapi/parser/fpdf_parser_utility.h
+++ b/core/fpdfapi/parser/fpdf_parser_utility.h
@@ -19,20 +19,20 @@ class CPDF_Dictionary;
class CPDF_Object;
class IFX_SeekableReadStream;
-// Use the accessors below instead of directly accessing PDF_CharType.
-extern const char PDF_CharType[256];
+// Use the accessors below instead of directly accessing kPDFCharTypes.
+extern const char kPDFCharTypes[256];
inline bool PDFCharIsWhitespace(uint8_t c) {
- return PDF_CharType[c] == 'W';
+ return kPDFCharTypes[c] == 'W';
}
inline bool PDFCharIsNumeric(uint8_t c) {
- return PDF_CharType[c] == 'N';
+ return kPDFCharTypes[c] == 'N';
}
inline bool PDFCharIsDelimiter(uint8_t c) {
- return PDF_CharType[c] == 'D';
+ return kPDFCharTypes[c] == 'D';
}
inline bool PDFCharIsOther(uint8_t c) {
- return PDF_CharType[c] == 'R';
+ return kPDFCharTypes[c] == 'R';
}
inline bool PDFCharIsLineEnding(uint8_t c) {
diff --git a/core/fpdfapi/parser/object_tree_traversal_util.cpp b/core/fpdfapi/parser/object_tree_traversal_util.cpp
index e1a0d52d0..d3194840b 100644
--- a/core/fpdfapi/parser/object_tree_traversal_util.cpp
+++ b/core/fpdfapi/parser/object_tree_traversal_util.cpp
@@ -17,6 +17,7 @@
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/parser/cpdf_reference.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
+#include "core/fxcrt/unowned_ptr.h"
#include "third_party/base/check.h"
#include "third_party/base/containers/contains.h"
@@ -80,7 +81,6 @@ class ObjectTreeTraverser {
const CPDF_Reference* ref_object = current_object->AsReference();
const uint32_t ref_object_number = GetObjectNumber(ref_object);
const uint32_t referenced_object_number = ref_object->GetRefObjNum();
- CHECK(referenced_object_number);
RetainPtr<const CPDF_Object> referenced_object;
if (ref_object->HasIndirectObjectHolder()) {
@@ -93,6 +93,7 @@ class ObjectTreeTraverser {
}
// Unlike the other object types, CPDF_Reference can point at nullptr.
if (referenced_object) {
+ CHECK(referenced_object_number);
reference_entries.push_back(
{ref_object_number, referenced_object_number});
PushNewObject(ref_object, referenced_object);
@@ -169,7 +170,7 @@ class ObjectTreeTraverser {
return it != object_number_map_.end() ? it->second : 0;
}
- const CPDF_Document* const document_;
+ UnownedPtr<const CPDF_Document> const document_;
// Queue of objects to traverse.
// - Pointers in the queue are non-null.
diff --git a/core/fpdfapi/parser/object_tree_traversal_util_embeddertest.cpp b/core/fpdfapi/parser/object_tree_traversal_util_embeddertest.cpp
index c90c77e41..ed0c8e169 100644
--- a/core/fpdfapi/parser/object_tree_traversal_util_embeddertest.cpp
+++ b/core/fpdfapi/parser/object_tree_traversal_util_embeddertest.cpp
@@ -64,6 +64,14 @@ TEST_F(ObjectTreeTraversalUtilEmbedderTest,
}
TEST_F(ObjectTreeTraversalUtilEmbedderTest,
+ GetObjectsWithReferencesObjectZero) {
+ ASSERT_TRUE(OpenDocument("rectangles_object_zero.pdf"));
+ CPDF_Document* doc = GetCPDFDocument(document());
+ std::set<uint32_t> referenced_objects = GetObjectsWithReferences(doc);
+ EXPECT_THAT(referenced_objects, UnorderedElementsAreArray({1, 2, 3, 4}));
+}
+
+TEST_F(ObjectTreeTraversalUtilEmbedderTest,
GetObjectsWithMultipleReferencesBasic) {
ASSERT_TRUE(OpenDocument("hello_world.pdf"));
CPDF_Document* doc = GetCPDFDocument(document());
@@ -94,3 +102,11 @@ TEST_F(ObjectTreeTraversalUtilEmbedderTest,
std::set<uint32_t> referenced_objects = GetObjectsWithMultipleReferences(doc);
EXPECT_THAT(referenced_objects, UnorderedElementsAreArray({5, 6, 7}));
}
+
+TEST_F(ObjectTreeTraversalUtilEmbedderTest,
+ GetObjectsWithMultipleReferencesObjectZero) {
+ ASSERT_TRUE(OpenDocument("rectangles_object_zero.pdf"));
+ CPDF_Document* doc = GetCPDFDocument(document());
+ std::set<uint32_t> referenced_objects = GetObjectsWithMultipleReferences(doc);
+ EXPECT_TRUE(referenced_objects.empty());
+}
diff --git a/core/fpdfapi/render/charposlist.h b/core/fpdfapi/render/charposlist.h
index af0ea6d4a..47c5d5760 100644
--- a/core/fpdfapi/render/charposlist.h
+++ b/core/fpdfapi/render/charposlist.h
@@ -11,7 +11,7 @@
#include <vector>
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_Font;
class TextCharPos;
diff --git a/core/fpdfapi/render/cpdf_imagerenderer.cpp b/core/fpdfapi/render/cpdf_imagerenderer.cpp
index c5f3f1d46..a773cd281 100644
--- a/core/fpdfapi/render/cpdf_imagerenderer.cpp
+++ b/core/fpdfapi/render/cpdf_imagerenderer.cpp
@@ -40,11 +40,6 @@
#include "core/fxge/dib/cfx_imagestretcher.h"
#include "core/fxge/dib/cfx_imagetransformer.h"
#include "third_party/base/check.h"
-#include "third_party/base/cxx17_backports.h"
-
-#if defined(_SKIA_SUPPORT_)
-#include "core/fxge/skia/fx_skia_device.h"
-#endif
namespace {
@@ -67,19 +62,6 @@ void ClearBitmap(CFX_DefaultRenderDevice& bitmap_device, uint32_t color) {
bitmap_device.GetBitmap()->Clear(color);
}
-RetainPtr<CFX_DIBBase> PreMultiplyBitmapIfAlpha(
- RetainPtr<CFX_DIBBase> base_bitmap) {
-#if defined(_SKIA_SUPPORT_)
- if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
- RetainPtr<CFX_DIBitmap> premultiplied = base_bitmap->Realize();
- if (base_bitmap->IsAlphaFormat())
- premultiplied->PreMultiply();
- return premultiplied;
- }
-#endif // defined(_SKIA_SUPPORT_)
- return base_bitmap;
-}
-
} // namespace
CPDF_ImageRenderer::CPDF_ImageRenderer(CPDF_RenderStatus* pStatus)
@@ -283,11 +265,11 @@ void CPDF_ImageRenderer::CalculateDrawImage(
continue;
}
int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b;
- *dest_scan++ = pdfium::clamp(orig, 0, 255);
+ *dest_scan++ = std::clamp(orig, 0, 255);
orig = (*dest_scan - matte_g) * 255 / alpha + matte_g;
- *dest_scan++ = pdfium::clamp(orig, 0, 255);
+ *dest_scan++ = std::clamp(orig, 0, 255);
orig = (*dest_scan - matte_r) * 255 / alpha + matte_r;
- *dest_scan++ = pdfium::clamp(orig, 0, 255);
+ *dest_scan++ = std::clamp(orig, 0, 255);
dest_scan++;
}
}
@@ -381,6 +363,8 @@ bool CPDF_ImageRenderer::DrawMaskedImage() {
}
CalculateDrawImage(&bitmap_device1, &bitmap_device2, m_pLoader->GetMask(),
new_matrix, rect);
+ DCHECK(!bitmap_device2.GetBitmap()->HasPalette());
+ bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_Format::k8bppMask);
#if defined(_SKIA_SUPPORT_)
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
m_pRenderStatus->GetRenderDevice()->SetBitsWithMask(
@@ -389,7 +373,6 @@ bool CPDF_ImageRenderer::DrawMaskedImage() {
return false;
}
#endif
- bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_Format::k8bppMask);
bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap());
if (m_BitmapAlpha < 255)
bitmap_device1.GetBitmap()->MultiplyAlpha(m_BitmapAlpha);
@@ -412,10 +395,9 @@ bool CPDF_ImageRenderer::StartDIBBase() {
m_ResampleOptions.bInterpolateBilinear = true;
}
}
- RetainPtr<CFX_DIBBase> bitmap = PreMultiplyBitmapIfAlpha(m_pDIBBase);
if (m_pRenderStatus->GetRenderDevice()->StartDIBitsWithBlend(
- bitmap, m_BitmapAlpha, m_FillArgb, m_ImageMatrix, m_ResampleOptions,
- &m_DeviceHandle, m_BlendType)) {
+ m_pDIBBase, m_BitmapAlpha, m_FillArgb, m_ImageMatrix,
+ m_ResampleOptions, &m_DeviceHandle, m_BlendType)) {
if (m_DeviceHandle) {
m_Mode = Mode::kBlend;
return true;
diff --git a/core/fpdfapi/render/cpdf_progressiverenderer.h b/core/fpdfapi/render/cpdf_progressiverenderer.h
index 67170fc80..7af65a0e7 100644
--- a/core/fpdfapi/render/cpdf_progressiverenderer.h
+++ b/core/fpdfapi/render/cpdf_progressiverenderer.h
@@ -53,7 +53,7 @@ class CPDF_ProgressiveRenderer {
std::unique_ptr<CPDF_RenderStatus> m_pRenderStatus;
CFX_FloatRect m_ClipRect;
uint32_t m_LayerIndex = 0;
- CPDF_RenderContext::Layer* m_pCurrentLayer = nullptr;
+ UnownedPtr<CPDF_RenderContext::Layer> m_pCurrentLayer;
CPDF_PageObjectHolder::const_iterator m_LastObjectRendered;
};
diff --git a/core/fpdfapi/render/cpdf_rendershading.cpp b/core/fpdfapi/render/cpdf_rendershading.cpp
index ce7543b6e..bce967f68 100644
--- a/core/fpdfapi/render/cpdf_rendershading.cpp
+++ b/core/fpdfapi/render/cpdf_rendershading.cpp
@@ -27,6 +27,7 @@
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/fx_system.h"
#include "core/fxcrt/span_util.h"
+#include "core/fxcrt/unowned_ptr.h"
#include "core/fxge/cfx_defaultrenderdevice.h"
#include "core/fxge/cfx_fillrenderoptions.h"
#include "core/fxge/cfx_path.h"
@@ -34,8 +35,7 @@
#include "core/fxge/dib/fx_dib.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
-#include "third_party/base/cxx17_backports.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace {
@@ -390,8 +390,8 @@ void DrawGouraud(const RetainPtr<CFX_DIBitmap>& pBitmap,
end_index = 0;
}
- int start_x = pdfium::clamp(min_x, 0, pBitmap->GetWidth());
- int end_x = pdfium::clamp(max_x, 0, pBitmap->GetWidth());
+ int start_x = std::clamp(min_x, 0, pBitmap->GetWidth());
+ int end_x = std::clamp(max_x, 0, pBitmap->GetWidth());
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);
@@ -767,7 +767,7 @@ struct PatchDrawer {
int max_delta;
CFX_Path path;
- CFX_RenderDevice* pDevice;
+ UnownedPtr<CFX_RenderDevice> pDevice;
int bNoPathSmooth;
int alpha;
CoonColor patch_colors[4];
diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp
index fe58de8d1..39101f05a 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.cpp
+++ b/core/fpdfapi/render/cpdf_renderstatus.cpp
@@ -69,12 +69,8 @@
#include "core/fxge/text_glyph_pos.h"
#include "third_party/base/check.h"
#include "third_party/base/containers/contains.h"
+#include "third_party/base/containers/span.h"
#include "third_party/base/notreached.h"
-#include "third_party/base/span.h"
-
-#if defined(_SKIA_SUPPORT_)
-#include "core/fxge/skia/fx_skia_device.h"
-#endif
namespace {
@@ -1213,10 +1209,6 @@ void CPDF_RenderStatus::CompositeDIBitmap(
}
pDIBitmap->MultiplyAlpha(bitmap_alpha);
}
-#if defined(_SKIA_SUPPORT_)
- if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- pDIBitmap->PreMultiply();
-#endif
if (m_pDevice->SetDIBits(pDIBitmap, left, top)) {
return;
}
@@ -1375,7 +1367,7 @@ RetainPtr<CFX_DIBitmap> CPDF_RenderStatus::LoadSMask(
if (!pMask->Create(width, height, FXDIB_Format::k8bppMask))
return nullptr;
- pdfium::span<uint8_t> dest_buf = pMask->GetBuffer();
+ pdfium::span<uint8_t> dest_buf = pMask->GetWritableBuffer();
pdfium::span<const uint8_t> src_buf = bitmap->GetBuffer();
int dest_pitch = pMask->GetPitch();
int src_pitch = bitmap->GetPitch();
diff --git a/core/fpdfapi/render/cpdf_rendertiling.cpp b/core/fpdfapi/render/cpdf_rendertiling.cpp
index fcde2b2ea..5f9dcd770 100644
--- a/core/fpdfapi/render/cpdf_rendertiling.cpp
+++ b/core/fpdfapi/render/cpdf_rendertiling.cpp
@@ -18,6 +18,7 @@
#include "core/fpdfapi/render/cpdf_renderstatus.h"
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxge/cfx_defaultrenderdevice.h"
+#include "core/fxge/dib/cfx_dibitmap.h"
namespace {
diff --git a/core/fpdfapi/render/cpdf_rendertiling.h b/core/fpdfapi/render/cpdf_rendertiling.h
index b687f7490..34fb56bf4 100644
--- a/core/fpdfapi/render/cpdf_rendertiling.h
+++ b/core/fpdfapi/render/cpdf_rendertiling.h
@@ -8,8 +8,8 @@
#define CORE_FPDFAPI_RENDER_CPDF_RENDERTILING_H_
#include "core/fxcrt/retain_ptr.h"
-#include "core/fxge/dib/cfx_dibitmap.h"
+class CFX_DIBitmap;
class CFX_Matrix;
class CPDF_Form;
class CPDF_PageObject;
diff --git a/core/fpdfapi/render/cpdf_textrenderer.h b/core/fpdfapi/render/cpdf_textrenderer.h
index b5529a6ea..857340f7b 100644
--- a/core/fpdfapi/render/cpdf_textrenderer.h
+++ b/core/fpdfapi/render/cpdf_textrenderer.h
@@ -12,7 +12,7 @@
#include "core/fxcrt/bytestring.h"
#include "core/fxcrt/fx_coordinates.h"
#include "core/fxge/dib/fx_dib.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_RenderDevice;
class CFX_GraphStateData;
diff --git a/core/fpdfapi/render/fpdf_progressive_render_embeddertest.cpp b/core/fpdfapi/render/fpdf_progressive_render_embeddertest.cpp
index a51e16e0c..428c56b3d 100644
--- a/core/fpdfapi/render/fpdf_progressive_render_embeddertest.cpp
+++ b/core/fpdfapi/render/fpdf_progressive_render_embeddertest.cpp
@@ -24,11 +24,14 @@ constexpr FX_ARGB kRed = 0xFFFF0000;
constexpr FX_ARGB kWhite = 0xFFFFFFFF;
const char* AnnotationStampWithApBaseContentChecksum() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "4fedc838daa6762cf7eee180986a0f1b";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "243f3d6267d9db09198fed9f8c4957fd";
-#endif
+ return "243f3d6267d9db09198fed9f8c4957fd";
+#else
return "e31414933c9ff3950773981e5bf61678";
+#endif
}
} // namespace
@@ -313,7 +316,7 @@ TEST_F(FPDFProgressiveRenderEmbedderTest, RenderTextWithColorScheme) {
// Test rendering of text with forced color scheme on.
const char* content_with_text_checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "5ece6059efdc2ecb2894fa3cf329dc94";
+ return "edd919ec8b59fab1f16b5f2adb1175f3";
#if BUILDFLAG(IS_APPLE)
return "ee4ec12f54ce8d117a73bd9b85a8954d";
#else
@@ -369,7 +372,7 @@ TEST_F(FPDFProgressiveRenderEmbedderTest, RenderHighlightWithColorScheme) {
// Normal blend mode.
const char* content_with_highlight_fill_checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "9b6273fdbc9db780c49f7540756209f8";
+ return "49dcfcfdc38d200bb3d57a2ca3086034";
#if BUILDFLAG(IS_APPLE)
return "a820afec9b99d3d3f2e9e9382bbad7c1";
#else
@@ -396,7 +399,7 @@ TEST_F(FPDFProgressiveRenderEmbedderTest,
const char* md5_content_with_highlight = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "772246195d18f75d40a22bee913c098f";
+ return "c609e8810fba2f12db8f8a2b043d97bd";
#if BUILDFLAG(IS_APPLE)
return "8837bea0b3520164b1784e513c882a2d";
#else
@@ -415,8 +418,13 @@ TEST_F(FPDFProgressiveRenderEmbedderTest,
TEST_F(FPDFProgressiveRenderEmbedderTest, RenderInkWithColorScheme) {
// Test rendering of multiple ink with forced color scheme on.
const char* content_with_ink_checksum = []() {
- if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "ebc57721e4c8da34156e09b9b2e62fb0";
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+#if BUILDFLAG(IS_APPLE)
+ return "5108aa537b6ecc37b3f0a35b76c1b379";
+#else
+ return "b39d9f68ff71963d82c43eb20caa8f4d";
+#endif
+ }
return "797bce7dc6c50ee86b095405df9fe5aa";
}();
@@ -431,7 +439,7 @@ TEST_F(FPDFProgressiveRenderEmbedderTest, RenderStampWithColorScheme) {
// Test rendering of static annotation with forced color scheme on.
const char* content_with_stamp_checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "a791fdb4f595bb6c4187cc2aeed5e9e8";
+ return "6e028012a4854ebfd9ee92da862bf679";
#if BUILDFLAG(IS_APPLE)
return "8170c539e95f22f14eb8f266a5f1bbed";
#else
diff --git a/core/fpdfdoc/BUILD.gn b/core/fpdfdoc/BUILD.gn
index 2e7a150f6..5e11adb6b 100644
--- a/core/fpdfdoc/BUILD.gn
+++ b/core/fpdfdoc/BUILD.gn
@@ -97,6 +97,7 @@ pdfium_unittest_source_set("unittests") {
sources = [
"cpdf_action_unittest.cpp",
"cpdf_annot_unittest.cpp",
+ "cpdf_annotlist_unittest.cpp",
"cpdf_bafontmap_unittest.cpp",
"cpdf_defaultappearance_unittest.cpp",
"cpdf_dest_unittest.cpp",
diff --git a/core/fpdfdoc/cpdf_annotlist.cpp b/core/fpdfdoc/cpdf_annotlist.cpp
index f565a5a70..ff3ed81be 100644
--- a/core/fpdfdoc/cpdf_annotlist.cpp
+++ b/core/fpdfdoc/cpdf_annotlist.cpp
@@ -23,6 +23,7 @@
#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/fpdfapi/render/cpdf_renderoptions.h"
#include "core/fpdfdoc/cpdf_annot.h"
#include "core/fpdfdoc/cpdf_formfield.h"
@@ -64,7 +65,6 @@ bool PopupAppearsForAnnotType(CPDF_Annot::Subtype subtype) {
case CPDF_Annot::Subtype::THREED:
case CPDF_Annot::Subtype::RICHMEDIA:
case CPDF_Annot::Subtype::XFAWIDGET:
- default:
return false;
}
}
@@ -79,12 +79,13 @@ std::unique_ptr<CPDF_Annot> CreatePopupAnnot(CPDF_Document* pDocument,
if (!pParentDict)
return nullptr;
- // TODO(jaepark): We shouldn't strip BOM for some strings and not for others.
- // See pdfium:593.
- WideString sContents =
- pParentDict->GetUnicodeTextFor(pdfium::annotation::kContents);
- if (sContents.IsEmpty())
+ // TODO(crbug.com/pdfium/1098): Determine if we really need to check if
+ // /Contents is empty or not. If so, optimize decoding for empty check.
+ ByteString contents =
+ pParentDict->GetByteStringFor(pdfium::annotation::kContents);
+ if (PDF_DecodeText(contents.raw_span()).IsEmpty()) {
return nullptr;
+ }
auto pAnnotDict = pDocument->New<CPDF_Dictionary>();
pAnnotDict->SetNewFor<CPDF_Name>(pdfium::annotation::kType, "Annot");
@@ -92,8 +93,8 @@ std::unique_ptr<CPDF_Annot> CreatePopupAnnot(CPDF_Document* pDocument,
pAnnotDict->SetNewFor<CPDF_String>(
pdfium::form_fields::kT,
pParentDict->GetByteStringFor(pdfium::form_fields::kT), false);
- pAnnotDict->SetNewFor<CPDF_String>(pdfium::annotation::kContents,
- sContents.ToUTF8(), false);
+ pAnnotDict->SetNewFor<CPDF_String>(pdfium::annotation::kContents, contents,
+ /*bHex=*/false);
CFX_FloatRect rect = pParentDict->GetRectFor(pdfium::annotation::kRect);
rect.Normalize();
diff --git a/core/fpdfdoc/cpdf_annotlist_unittest.cpp b/core/fpdfdoc/cpdf_annotlist_unittest.cpp
new file mode 100644
index 000000000..653fdfffd
--- /dev/null
+++ b/core/fpdfdoc/cpdf_annotlist_unittest.cpp
@@ -0,0 +1,125 @@
+// Copyright 2023 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/fpdfdoc/cpdf_annotlist.h"
+
+#include <stdint.h>
+
+#include <initializer_list>
+#include <memory>
+
+#include "constants/annotation_common.h"
+#include "core/fpdfapi/page/cpdf_page.h"
+#include "core/fpdfapi/page/test_with_page_module.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_string.h"
+#include "core/fpdfapi/parser/cpdf_test_document.h"
+#include "core/fpdfdoc/cpdf_annot.h"
+#include "core/fxcrt/bytestring.h"
+#include "core/fxcrt/retain_ptr.h"
+#include "core/fxcrt/widestring.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class CPDFAnnotListTest : public TestWithPageModule {
+ public:
+ void SetUp() override {
+ TestWithPageModule::SetUp();
+
+ document_ = std::make_unique<CPDF_TestDocument>();
+ document_->SetRoot(pdfium::MakeRetain<CPDF_Dictionary>());
+ page_ = pdfium::MakeRetain<CPDF_Page>(
+ document_.get(), pdfium::MakeRetain<CPDF_Dictionary>());
+ }
+
+ void TearDown() override {
+ page_.Reset();
+ document_.reset();
+
+ TestWithPageModule::TearDown();
+ }
+
+ protected:
+ void AddTextAnnotation(const ByteString& contents) {
+ RetainPtr<CPDF_Dictionary> annotation =
+ page_->GetOrCreateAnnotsArray()->AppendNew<CPDF_Dictionary>();
+ annotation->SetNewFor<CPDF_Name>(pdfium::annotation::kSubtype, "Text");
+ annotation->SetNewFor<CPDF_String>(pdfium::annotation::kContents, contents,
+ /*bHex=*/false);
+ }
+
+ std::unique_ptr<CPDF_TestDocument> document_;
+ RetainPtr<CPDF_Page> page_;
+};
+
+ByteString MakeByteString(std::initializer_list<uint8_t> bytes) {
+ return ByteString(std::data(bytes), std::size(bytes));
+}
+
+ByteString GetRawContents(const CPDF_Annot* annotation) {
+ return annotation->GetAnnotDict()->GetByteStringFor(
+ pdfium::annotation::kContents);
+}
+
+WideString GetDecodedContents(const CPDF_Annot* annotation) {
+ return annotation->GetAnnotDict()->GetUnicodeTextFor(
+ pdfium::annotation::kContents);
+}
+
+} // namespace
+
+TEST_F(CPDFAnnotListTest, CreatePopupAnnotFromPdfEncoded) {
+ const ByteString kContents = MakeByteString({'A', 'a', 0xE4, 0xA0});
+ AddTextAnnotation(kContents);
+
+ CPDF_AnnotList list(page_);
+
+ ASSERT_EQ(2u, list.Count());
+ EXPECT_EQ(kContents, GetRawContents(list.GetAt(1)));
+ EXPECT_EQ(WideString::FromUTF8("Aaä€"), GetDecodedContents(list.GetAt(1)));
+}
+
+TEST_F(CPDFAnnotListTest, CreatePopupAnnotFromUnicode) {
+ const ByteString kContents =
+ MakeByteString({0xFE, 0xFF, 0x00, 'A', 0x00, 'a', 0x00, 0xE4, 0x20, 0xAC,
+ 0xD8, 0x3C, 0xDF, 0xA8});
+ AddTextAnnotation(kContents);
+
+ CPDF_AnnotList list(page_);
+
+ ASSERT_EQ(2u, list.Count());
+ EXPECT_EQ(kContents, GetRawContents(list.GetAt(1)));
+
+ EXPECT_EQ(WideString::FromUTF8("Aaä€🎨"), GetDecodedContents(list.GetAt(1)));
+}
+
+TEST_F(CPDFAnnotListTest, CreatePopupAnnotFromEmptyPdfEncoded) {
+ AddTextAnnotation("");
+
+ CPDF_AnnotList list(page_);
+
+ EXPECT_EQ(1u, list.Count());
+}
+
+TEST_F(CPDFAnnotListTest, CreatePopupAnnotFromEmptyUnicode) {
+ const ByteString kContents = MakeByteString({0xFE, 0xFF});
+ AddTextAnnotation(kContents);
+
+ CPDF_AnnotList list(page_);
+
+ EXPECT_EQ(1u, list.Count());
+}
+
+TEST_F(CPDFAnnotListTest, CreatePopupAnnotFromEmptyUnicodedWithEscape) {
+ const ByteString kContents =
+ MakeByteString({0xFE, 0xFF, 0x00, 0x1B, 'j', 'a', 0x00, 0x1B});
+ AddTextAnnotation(kContents);
+
+ CPDF_AnnotList list(page_);
+
+ EXPECT_EQ(1u, list.Count());
+}
diff --git a/core/fpdfdoc/cpdf_defaultappearance.cpp b/core/fpdfdoc/cpdf_defaultappearance.cpp
index 1eda1d928..e3b91a908 100644
--- a/core/fpdfdoc/cpdf_defaultappearance.cpp
+++ b/core/fpdfdoc/cpdf_defaultappearance.cpp
@@ -84,24 +84,23 @@ absl::optional<CFX_Color> CPDF_DefaultAppearance::GetColor() const {
if (m_csDA.IsEmpty())
return absl::nullopt;
- float fc[4];
CPDF_SimpleParser syntax(m_csDA.AsStringView().raw_span());
if (FindTagParamFromStart(&syntax, "g", 1)) {
- fc[0] = StringToFloat(syntax.GetWord());
- return CFX_Color(CFX_Color::Type::kGray, fc[0]);
+ float gray = StringToFloat(syntax.GetWord());
+ return CFX_Color(CFX_Color::Type::kGray, gray);
}
if (FindTagParamFromStart(&syntax, "rg", 3)) {
- fc[0] = StringToFloat(syntax.GetWord());
- fc[1] = StringToFloat(syntax.GetWord());
- fc[2] = StringToFloat(syntax.GetWord());
- return CFX_Color(CFX_Color::Type::kRGB, fc[0], fc[1], fc[2]);
+ float r = StringToFloat(syntax.GetWord());
+ float g = StringToFloat(syntax.GetWord());
+ float b = StringToFloat(syntax.GetWord());
+ return CFX_Color(CFX_Color::Type::kRGB, r, g, b);
}
if (FindTagParamFromStart(&syntax, "k", 4)) {
- fc[0] = StringToFloat(syntax.GetWord());
- fc[1] = StringToFloat(syntax.GetWord());
- fc[2] = StringToFloat(syntax.GetWord());
- fc[3] = StringToFloat(syntax.GetWord());
- return CFX_Color(CFX_Color::Type::kCMYK, fc[0], fc[1], fc[2], fc[3]);
+ float c = StringToFloat(syntax.GetWord());
+ float m = StringToFloat(syntax.GetWord());
+ float y = StringToFloat(syntax.GetWord());
+ float k = StringToFloat(syntax.GetWord());
+ return CFX_Color(CFX_Color::Type::kCMYK, c, m, y, k);
}
return absl::nullopt;
}
@@ -135,8 +134,7 @@ absl::optional<CFX_Color::TypeAndARGB> CPDF_DefaultAppearance::GetColorARGB()
static_cast<int>(g * 255 + 0.5f),
static_cast<int>(b * 255 + 0.5f)));
}
- NOTREACHED();
- return absl::nullopt;
+ NOTREACHED_NORETURN();
}
// static
diff --git a/core/fpdfdoc/cpdf_defaultappearance_unittest.cpp b/core/fpdfdoc/cpdf_defaultappearance_unittest.cpp
index 86bac2753..ce08bf30a 100644
--- a/core/fpdfdoc/cpdf_defaultappearance_unittest.cpp
+++ b/core/fpdfdoc/cpdf_defaultappearance_unittest.cpp
@@ -9,7 +9,7 @@
#include "core/fpdfapi/parser/cpdf_simple_parser.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/test_support.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
TEST(CPDFDefaultAppearanceTest, FindTagParamFromStart) {
static const struct FindTagTestStruct {
diff --git a/core/fpdfdoc/cpdf_generateap.cpp b/core/fpdfdoc/cpdf_generateap.cpp
index 8c6f25ec8..234da4c9e 100644
--- a/core/fpdfdoc/cpdf_generateap.cpp
+++ b/core/fpdfdoc/cpdf_generateap.cpp
@@ -218,7 +218,6 @@ ByteString GenerateBorderAP(const CFX_FloatRect& rect,
if (fWidth > 0.0f) {
float fHalfWidth = fWidth / 2.0f;
switch (nStyle) {
- default:
case BorderStyle::kSolid:
sColor = GenerateColorAP(color, PaintOperation::kFill);
if (sColor.GetLength() > 0) {
diff --git a/core/fpdfdoc/cpdf_interactiveform.h b/core/fpdfdoc/cpdf_interactiveform.h
index 3eb3c30e3..3b6e4f1fa 100644
--- a/core/fpdfdoc/cpdf_interactiveform.h
+++ b/core/fpdfdoc/cpdf_interactiveform.h
@@ -23,7 +23,7 @@
#include "core/fxcrt/fx_string.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/unowned_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFieldTree;
class CFDF_Document;
diff --git a/core/fpdfdoc/cpdf_metadata.cpp b/core/fpdfdoc/cpdf_metadata.cpp
index 228a0c137..31564f45f 100644
--- a/core/fpdfdoc/cpdf_metadata.cpp
+++ b/core/fpdfdoc/cpdf_metadata.cpp
@@ -20,8 +20,15 @@
namespace {
-void CheckForSharedFormInternal(CFX_XMLElement* element,
+constexpr int kMaxMetaDataDepth = 128;
+
+bool CheckForSharedFormInternal(int depth,
+ CFX_XMLElement* element,
std::vector<UnsupportedFeature>* unsupported) {
+ if (depth >= kMaxMetaDataDepth) {
+ return false;
+ }
+
WideString attr =
element->GetAttribute(WideString::FromASCII("xmlns:adhocwf"));
if (attr.EqualsASCII("http://ns.adobe.com/AcrobatAdhocWorkflow/1.0/")) {
@@ -54,10 +61,13 @@ void CheckForSharedFormInternal(CFX_XMLElement* element,
for (auto* child = element->GetFirstChild(); child;
child = child->GetNextSibling()) {
- CFX_XMLElement* pElement = ToXMLElement(child);
- if (pElement)
- CheckForSharedFormInternal(pElement, unsupported);
+ CFX_XMLElement* xml_element = ToXMLElement(child);
+ if (xml_element &&
+ !CheckForSharedFormInternal(depth + 1, xml_element, unsupported)) {
+ return false;
+ }
}
+ return true;
}
} // namespace
@@ -80,6 +90,6 @@ std::vector<UnsupportedFeature> CPDF_Metadata::CheckForSharedForm() const {
return {};
std::vector<UnsupportedFeature> unsupported;
- CheckForSharedFormInternal(doc->GetRoot(), &unsupported);
+ CheckForSharedFormInternal(/*depth=*/0, doc->GetRoot(), &unsupported);
return unsupported;
}
diff --git a/core/fpdfdoc/cpdf_metadata_unittest.cpp b/core/fpdfdoc/cpdf_metadata_unittest.cpp
index cfcb8f35b..4bd30edb1 100644
--- a/core/fpdfdoc/cpdf_metadata_unittest.cpp
+++ b/core/fpdfdoc/cpdf_metadata_unittest.cpp
@@ -106,6 +106,39 @@ TEST(CPDF_MetadataTest, CheckSharedFormAsNoAdhoc) {
EXPECT_EQ(0U, results.size());
}
+TEST(CPDF_MetadataTest, CheckSharedFormExceedMaxDepth) {
+ // Node <parent> has the depth of 130, which exceeds the maximum node depth of
+ // `kMaxMetaDataDepth`.
+ static const char kData[] =
+ "<?xml charset=\"utf-8\"?>\n"
+ "<node><node><node><node><node><node><node><node><node><node>\n"
+ "<node><node><node><node><node><node><node><node><node><node>\n"
+ "<node><node><node><node><node><node><node><node><node><node>\n"
+ "<node><node><node><node><node><node><node><node><node><node>\n"
+ "<node><node><node><node><node><node><node><node><node><node>\n"
+ "<node><node><node><node><node><node><node><node><node><node>\n"
+ "<node><node><node><node><node><node><node><node><node><node>\n"
+ "<node><node><node><node><node><node><node><node><node><node>\n"
+ "<node><node><node><node><node><node><node><node><node><node>\n"
+ "<node><node><node><node><node><node><node><node><node><node>\n"
+ "<node><node><node><node><node><node><node><node><node><node>\n"
+ "<node><node><node><node><node><node><node><node><node><node>\n"
+ "<node><node><node><node><node><node><node><node><node><node>\n"
+ "<parent>\n"
+ "<node xmlns:adhocwf=\"http://ns.adobe.com/AcrobatAdhocWorkflow/1.0/\">\n"
+ "<adhocwf:workflowType>0</adhocwf:workflowType>\n"
+ "<adhocwf:version>1.1</adhocwf:version>\n"
+ "</node>"
+ "</parent>";
+
+ auto stream = pdfium::MakeRetain<CPDF_Stream>();
+ stream->SetData(ByteStringView(kData).raw_span());
+ CPDF_Metadata metadata(stream);
+
+ auto results = metadata.CheckForSharedForm();
+ ASSERT_EQ(0U, results.size());
+}
+
TEST(CPDF_MetadataTest, CheckSharedFormWrongNamespace) {
static const char data[] =
"<?xml charset=\"utf-8\"?>\n"
diff --git a/core/fpdfdoc/cpdf_nametree.cpp b/core/fpdfdoc/cpdf_nametree.cpp
index 3b60fab6f..95d540fc8 100644
--- a/core/fpdfdoc/cpdf_nametree.cpp
+++ b/core/fpdfdoc/cpdf_nametree.cpp
@@ -18,7 +18,7 @@
#include "core/fpdfapi/parser/fpdf_parser_decode.h"
#include "core/fxcrt/stl_util.h"
#include "third_party/base/check.h"
-#include "third_party/base/ptr_util.h"
+#include "third_party/base/memory/ptr_util.h"
namespace {
diff --git a/core/fpdfdoc/cpdf_structelement.cpp b/core/fpdfdoc/cpdf_structelement.cpp
index b28774dbd..95e887f09 100644
--- a/core/fpdfdoc/cpdf_structelement.cpp
+++ b/core/fpdfdoc/cpdf_structelement.cpp
@@ -29,7 +29,7 @@ CPDF_StructElement::CPDF_StructElement(const CPDF_StructTree* pTree,
: m_pTree(pTree),
m_pDict(std::move(pDict)),
m_Type(m_pTree->GetRoleMapNameFor(m_pDict->GetNameFor("S"))) {
- LoadKids(m_pDict);
+ LoadKids();
}
CPDF_StructElement::~CPDF_StructElement() {
@@ -99,11 +99,11 @@ bool CPDF_StructElement::UpdateKidIfElement(const CPDF_Dictionary* pDict,
return bSave;
}
-void CPDF_StructElement::LoadKids(RetainPtr<const CPDF_Dictionary> pDict) {
- RetainPtr<const CPDF_Object> pObj = pDict->GetObjectFor("Pg");
+void CPDF_StructElement::LoadKids() {
+ RetainPtr<const CPDF_Object> pObj = m_pDict->GetObjectFor("Pg");
const CPDF_Reference* pRef = ToReference(pObj.Get());
- const uint32_t PageObjNum = pRef ? pRef->GetRefObjNum() : 0;
- RetainPtr<const CPDF_Object> pKids = pDict->GetDirectObjectFor("K");
+ const uint32_t page_obj_num = pRef ? pRef->GetRefObjNum() : 0;
+ RetainPtr<const CPDF_Object> pKids = m_pDict->GetDirectObjectFor("K");
if (!pKids)
return;
@@ -111,28 +111,29 @@ void CPDF_StructElement::LoadKids(RetainPtr<const CPDF_Dictionary> pDict) {
if (const CPDF_Array* pArray = pKids->AsArray()) {
m_Kids.resize(pArray->size());
for (size_t i = 0; i < pArray->size(); ++i) {
- LoadKid(PageObjNum, pArray->GetDirectObjectAt(i), &m_Kids[i]);
+ LoadKid(page_obj_num, pArray->GetDirectObjectAt(i), m_Kids[i]);
}
return;
}
m_Kids.resize(1);
- LoadKid(PageObjNum, std::move(pKids), &m_Kids[0]);
+ LoadKid(page_obj_num, std::move(pKids), m_Kids[0]);
}
-void CPDF_StructElement::LoadKid(uint32_t PageObjNum,
+void CPDF_StructElement::LoadKid(uint32_t page_obj_num,
RetainPtr<const CPDF_Object> pKidObj,
- Kid* pKid) {
+ Kid& kid) {
if (!pKidObj)
return;
if (pKidObj->IsNumber()) {
- if (m_pTree->GetPageObjNum() != PageObjNum)
+ if (m_pTree->GetPageObjNum() != page_obj_num) {
return;
+ }
- pKid->m_Type = Kid::kPageContent;
- pKid->m_ContentId = pKidObj->GetInteger();
- pKid->m_PageObjNum = PageObjNum;
+ kid.m_Type = Kid::kPageContent;
+ kid.m_ContentId = pKidObj->GetInteger();
+ kid.m_PageObjNum = page_obj_num;
return;
}
@@ -142,33 +143,33 @@ void CPDF_StructElement::LoadKid(uint32_t PageObjNum,
if (RetainPtr<const CPDF_Reference> pRef =
ToReference(pKidDict->GetObjectFor("Pg"))) {
- PageObjNum = pRef->GetRefObjNum();
+ page_obj_num = pRef->GetRefObjNum();
}
ByteString type = pKidDict->GetNameFor("Type");
if ((type == "MCR" || type == "OBJR") &&
- m_pTree->GetPageObjNum() != PageObjNum) {
+ m_pTree->GetPageObjNum() != page_obj_num) {
return;
}
if (type == "MCR") {
- pKid->m_Type = Kid::kStreamContent;
+ kid.m_Type = Kid::kStreamContent;
RetainPtr<const CPDF_Reference> pRef =
ToReference(pKidDict->GetObjectFor("Stm"));
- pKid->m_RefObjNum = pRef ? pRef->GetRefObjNum() : 0;
- pKid->m_PageObjNum = PageObjNum;
- pKid->m_ContentId = pKidDict->GetIntegerFor("MCID");
+ kid.m_RefObjNum = pRef ? pRef->GetRefObjNum() : 0;
+ kid.m_PageObjNum = page_obj_num;
+ kid.m_ContentId = pKidDict->GetIntegerFor("MCID");
return;
}
if (type == "OBJR") {
- pKid->m_Type = Kid::kObject;
+ kid.m_Type = Kid::kObject;
RetainPtr<const CPDF_Reference> pObj =
ToReference(pKidDict->GetObjectFor("Obj"));
- pKid->m_RefObjNum = pObj ? pObj->GetRefObjNum() : 0;
- pKid->m_PageObjNum = PageObjNum;
+ kid.m_RefObjNum = pObj ? pObj->GetRefObjNum() : 0;
+ kid.m_PageObjNum = page_obj_num;
return;
}
- pKid->m_Type = Kid::kElement;
- pKid->m_pDict.Reset(pKidDict);
+ kid.m_Type = Kid::kElement;
+ kid.m_pDict.Reset(pKidDict);
}
diff --git a/core/fpdfdoc/cpdf_structelement.h b/core/fpdfdoc/cpdf_structelement.h
index 6dd8f8f00..72a0df357 100644
--- a/core/fpdfdoc/cpdf_structelement.h
+++ b/core/fpdfdoc/cpdf_structelement.h
@@ -62,10 +62,10 @@ class CPDF_StructElement final : public Retainable {
RetainPtr<const CPDF_Dictionary> pDict);
~CPDF_StructElement() override;
- void LoadKids(RetainPtr<const CPDF_Dictionary> pDict);
- void LoadKid(uint32_t PageObjNum,
+ void LoadKids();
+ void LoadKid(uint32_t page_obj_num,
RetainPtr<const CPDF_Object> pKidObj,
- Kid* pKid);
+ Kid& kid);
UnownedPtr<const CPDF_StructTree> const m_pTree;
RetainPtr<const CPDF_Dictionary> const m_pDict;
diff --git a/core/fpdfdoc/cpdf_structtree.cpp b/core/fpdfdoc/cpdf_structtree.cpp
index 67ac9485f..2b00117e0 100644
--- a/core/fpdfdoc/cpdf_structtree.cpp
+++ b/core/fpdfdoc/cpdf_structtree.cpp
@@ -15,7 +15,6 @@
#include "core/fpdfapi/parser/cpdf_reference.h"
#include "core/fpdfdoc/cpdf_numbertree.h"
#include "core/fpdfdoc/cpdf_structelement.h"
-#include "core/fxcrt/stl_util.h"
namespace {
@@ -63,16 +62,16 @@ void CPDF_StructTree::LoadPageTree(RetainPtr<const CPDF_Dictionary> pPageDict) {
if (!pKids)
return;
- uint32_t dwKids = 0;
+ size_t kids_count;
if (pKids->IsDictionary())
- dwKids = 1;
+ kids_count = 1;
else if (const CPDF_Array* pArray = pKids->AsArray())
- dwKids = fxcrt::CollectionSize<uint32_t>(*pArray);
+ kids_count = pArray->size();
else
return;
m_Kids.clear();
- m_Kids.resize(dwKids);
+ m_Kids.resize(kids_count);
RetainPtr<const CPDF_Dictionary> pParentTree =
m_pTreeRoot->GetDictFor("ParentTree");
@@ -124,11 +123,12 @@ RetainPtr<CPDF_StructElement> CPDF_StructTree::AddPageNode(
if (!pParentElement)
return pElement;
- if (!pParentElement->UpdateKidIfElement(pDict, pElement.Get()))
+ if (!pParentElement->UpdateKidIfElement(pDict, pElement.Get())) {
map->erase(key);
+ return pElement;
+ }
pElement->SetParent(pParentElement.Get());
-
return pElement;
}
diff --git a/core/fpdfdoc/cpvt_fontmap.cpp b/core/fpdfdoc/cpvt_fontmap.cpp
index d26655f13..b492b5f4c 100644
--- a/core/fpdfdoc/cpvt_fontmap.cpp
+++ b/core/fpdfdoc/cpvt_fontmap.cpp
@@ -77,17 +77,14 @@ ByteString CPVT_FontMap::GetPDFFontAlias(int32_t nFontIndex) {
int32_t CPVT_FontMap::GetWordFontIndex(uint16_t word,
FX_Charset charset,
int32_t nFontIndex) {
- NOTREACHED();
- return 0;
+ NOTREACHED_NORETURN();
}
int32_t CPVT_FontMap::CharCodeFromUnicode(int32_t nFontIndex, uint16_t word) {
- NOTREACHED();
- return 0;
+ NOTREACHED_NORETURN();
}
FX_Charset CPVT_FontMap::CharSetFromUnicode(uint16_t word,
FX_Charset nOldCharset) {
- NOTREACHED();
- return FX_Charset::kANSI;
+ NOTREACHED_NORETURN();
}
diff --git a/core/fpdfdoc/cpvt_section.cpp b/core/fpdfdoc/cpvt_section.cpp
index 9276d0cae..5c452da37 100644
--- a/core/fpdfdoc/cpvt_section.cpp
+++ b/core/fpdfdoc/cpvt_section.cpp
@@ -12,7 +12,6 @@
#include "core/fpdfdoc/cpvt_wordinfo.h"
#include "core/fxcrt/stl_util.h"
#include "third_party/base/check.h"
-#include "third_party/base/cxx17_backports.h"
namespace {
@@ -223,8 +222,8 @@ void CPVT_Section::ResetLinePlace() {
CPVT_WordPlace CPVT_Section::AddWord(const CPVT_WordPlace& place,
const CPVT_WordInfo& wordinfo) {
- int32_t nWordIndex = pdfium::clamp(
- place.nWordIndex, 0, fxcrt::CollectionSize<int32_t>(m_WordArray));
+ int32_t nWordIndex = std::clamp(place.nWordIndex, 0,
+ fxcrt::CollectionSize<int32_t>(m_WordArray));
m_WordArray.insert(m_WordArray.begin() + nWordIndex,
std::make_unique<CPVT_WordInfo>(wordinfo));
return place;
diff --git a/core/fpdfdoc/cpvt_variabletext.cpp b/core/fpdfdoc/cpvt_variabletext.cpp
index a13af1cfe..f9cab3e65 100644
--- a/core/fpdfdoc/cpvt_variabletext.cpp
+++ b/core/fpdfdoc/cpvt_variabletext.cpp
@@ -18,7 +18,6 @@
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/stl_util.h"
#include "third_party/base/check.h"
-#include "third_party/base/cxx17_backports.h"
namespace {
@@ -528,7 +527,7 @@ CPVT_WordPlace CPVT_VariableText::AddSection(const CPVT_WordPlace& place) {
if (IsValid() && !m_bMultiLine)
return place;
- int32_t nSecIndex = pdfium::clamp(
+ int32_t nSecIndex = std::clamp(
place.nSecIndex, 0, fxcrt::CollectionSize<int32_t>(m_SectionArray));
auto pSection = std::make_unique<CPVT_Section>(this);
@@ -554,8 +553,8 @@ CPVT_WordPlace CPVT_VariableText::AddWord(const CPVT_WordPlace& place,
CPVT_WordPlace newplace = place;
newplace.nSecIndex =
- pdfium::clamp(newplace.nSecIndex, 0,
- fxcrt::CollectionSize<int32_t>(m_SectionArray) - 1);
+ std::clamp(newplace.nSecIndex, 0,
+ fxcrt::CollectionSize<int32_t>(m_SectionArray) - 1);
return m_SectionArray[newplace.nSecIndex]->AddWord(newplace, wordinfo);
}
diff --git a/core/fpdftext/cpdf_textpage.cpp b/core/fpdftext/cpdf_textpage.cpp
index 697e20267..99f336582 100644
--- a/core/fpdftext/cpdf_textpage.cpp
+++ b/core/fpdftext/cpdf_textpage.cpp
@@ -30,7 +30,6 @@
#include "core/fxcrt/stl_util.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
-#include "third_party/base/cxx17_backports.h"
namespace {
@@ -544,7 +543,7 @@ bool CPDF_TextPage::GetRect(int rectIndex, CFX_FloatRect* pRect) const {
CPDF_TextPage::TextOrientation CPDF_TextPage::FindTextlineFlowOrientation()
const {
- DCHECK_NE(m_pPage->GetPageObjectCount(), 0);
+ DCHECK_NE(m_pPage->GetPageObjectCount(), 0u);
const int32_t nPageWidth = static_cast<int32_t>(m_pPage->GetPageWidth());
const int32_t nPageHeight = static_cast<int32_t>(m_pPage->GetPageHeight());
@@ -563,13 +562,13 @@ CPDF_TextPage::TextOrientation CPDF_TextPage::FindTextlineFlowOrientation()
continue;
int32_t minH = static_cast<int32_t>(
- pdfium::clamp<float>(pPageObj->GetRect().left, 0.0f, nPageWidth));
+ std::clamp<float>(pPageObj->GetRect().left, 0.0f, nPageWidth));
int32_t maxH = static_cast<int32_t>(
- pdfium::clamp<float>(pPageObj->GetRect().right, 0.0f, nPageWidth));
+ std::clamp<float>(pPageObj->GetRect().right, 0.0f, nPageWidth));
int32_t minV = static_cast<int32_t>(
- pdfium::clamp<float>(pPageObj->GetRect().bottom, 0.0f, nPageHeight));
+ std::clamp<float>(pPageObj->GetRect().bottom, 0.0f, nPageHeight));
int32_t maxV = static_cast<int32_t>(
- pdfium::clamp<float>(pPageObj->GetRect().top, 0.0f, nPageHeight));
+ std::clamp<float>(pPageObj->GetRect().top, 0.0f, nPageHeight));
if (minH >= maxH || minV >= maxV)
continue;
diff --git a/core/fpdftext/cpdf_textpagefind.cpp b/core/fpdftext/cpdf_textpagefind.cpp
index 3f4ed4aec..419174842 100644
--- a/core/fpdftext/cpdf_textpagefind.cpp
+++ b/core/fpdftext/cpdf_textpagefind.cpp
@@ -17,7 +17,7 @@
#include "core/fxcrt/fx_unicode.h"
#include "core/fxcrt/stl_util.h"
#include "third_party/base/check.h"
-#include "third_party/base/ptr_util.h"
+#include "third_party/base/memory/ptr_util.h"
namespace {
diff --git a/core/fxcodec/basic/basicmodule.h b/core/fxcodec/basic/basicmodule.h
index a2573498e..61e3735fb 100644
--- a/core/fxcodec/basic/basicmodule.h
+++ b/core/fxcodec/basic/basicmodule.h
@@ -12,7 +12,7 @@
#include <memory>
#include "core/fxcrt/data_vector.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace fxcodec {
diff --git a/core/fxcodec/bmp/bmp_decoder.h b/core/fxcodec/bmp/bmp_decoder.h
index 46de34d3d..08a1638ad 100644
--- a/core/fxcodec/bmp/bmp_decoder.h
+++ b/core/fxcodec/bmp/bmp_decoder.h
@@ -13,7 +13,7 @@
#include "core/fxcodec/progressive_decoder_iface.h"
#include "core/fxcrt/fx_system.h"
#include "core/fxcrt/retain_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#ifndef PDF_ENABLE_XFA_BMP
#error "BMP must be enabled"
diff --git a/core/fxcodec/bmp/cfx_bmpdecompressor.h b/core/fxcodec/bmp/cfx_bmpdecompressor.h
index 408e39c69..6432777ec 100644
--- a/core/fxcodec/bmp/cfx_bmpdecompressor.h
+++ b/core/fxcodec/bmp/cfx_bmpdecompressor.h
@@ -16,7 +16,7 @@
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/unowned_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_CodecMemory;
diff --git a/core/fxcodec/cfx_codec_memory.cpp b/core/fxcodec/cfx_codec_memory.cpp
index e3e1ffa9c..8ac15d546 100644
--- a/core/fxcodec/cfx_codec_memory.cpp
+++ b/core/fxcodec/cfx_codec_memory.cpp
@@ -4,10 +4,10 @@
#include "core/fxcodec/cfx_codec_memory.h"
-#include <string.h>
-
#include <algorithm>
+#include "core/fxcrt/span_util.h"
+
CFX_CodecMemory::CFX_CodecMemory(size_t buffer_size)
: buffer_(FX_Alloc(uint8_t, buffer_size)), size_(buffer_size) {}
@@ -26,7 +26,7 @@ size_t CFX_CodecMemory::ReadBlock(pdfium::span<uint8_t> buffer) {
return 0;
size_t bytes_to_read = std::min(buffer.size(), size_ - pos_);
- memcpy(buffer.data(), buffer_.get() + pos_, bytes_to_read);
+ fxcrt::spancpy(buffer, GetBufferSpan().subspan(pos_, bytes_to_read));
pos_ += bytes_to_read;
return bytes_to_read;
}
@@ -44,6 +44,5 @@ bool CFX_CodecMemory::TryResize(size_t new_buffer_size) {
}
void CFX_CodecMemory::Consume(size_t consumed) {
- size_t unconsumed = size_ - consumed;
- memmove(buffer_.get(), buffer_.get() + consumed, unconsumed);
+ fxcrt::spanmove(GetBufferSpan(), GetBufferSpan().subspan(consumed));
}
diff --git a/core/fxcodec/cfx_codec_memory.h b/core/fxcodec/cfx_codec_memory.h
index a3044c3b6..2076311c9 100644
--- a/core/fxcodec/cfx_codec_memory.h
+++ b/core/fxcodec/cfx_codec_memory.h
@@ -9,7 +9,7 @@
#include "core/fxcrt/fx_memory_wrappers.h"
#include "core/fxcrt/retain_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_CodecMemory final : public Retainable {
public:
diff --git a/core/fxcodec/fax/faxmodule.cpp b/core/fxcodec/fax/faxmodule.cpp
index 075c72d08..a904186a8 100644
--- a/core/fxcodec/fax/faxmodule.cpp
+++ b/core/fxcodec/fax/faxmodule.cpp
@@ -22,9 +22,8 @@
#include "core/fxge/calculate_pitch.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
-#include "third_party/base/cxx17_backports.h"
+#include "third_party/base/containers/span.h"
#include "third_party/base/numerics/safe_conversions.h"
-#include "third_party/base/span.h"
#if BUILDFLAG(IS_WIN)
#include "core/fxcrt/span_util.h"
@@ -127,7 +126,7 @@ void FaxG4FindB1B2(pdfium::span<const uint8_t> ref_buf,
void FaxFillBits(uint8_t* dest_buf, int columns, int startpos, int endpos) {
startpos = std::max(startpos, 0);
- endpos = pdfium::clamp(endpos, 0, columns);
+ endpos = std::clamp(endpos, 0, columns);
if (startpos >= endpos)
return;
@@ -586,7 +585,7 @@ uint32_t FaxDecoder::GetSrcOffset() {
void FaxDecoder::InvertBuffer() {
DCHECK_EQ(m_Pitch, m_ScanlineBuf.size());
- DCHECK_EQ(m_Pitch % 4, 0);
+ DCHECK_EQ(m_Pitch % 4, 0u);
uint32_t* data = reinterpret_cast<uint32_t*>(m_ScanlineBuf.data());
for (size_t i = 0; i < m_ScanlineBuf.size() / 4; ++i)
data[i] = ~data[i];
diff --git a/core/fxcodec/fax/faxmodule.h b/core/fxcodec/fax/faxmodule.h
index 5f55cc547..2e7f5be5d 100644
--- a/core/fxcodec/fax/faxmodule.h
+++ b/core/fxcodec/fax/faxmodule.h
@@ -12,7 +12,7 @@
#include <memory>
#include "build/build_config.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#if BUILDFLAG(IS_WIN)
#include "core/fxcrt/data_vector.h"
diff --git a/core/fxcodec/flate/flatemodule.cpp b/core/fxcodec/flate/flatemodule.cpp
index 8c397c5bf..f32955f68 100644
--- a/core/fxcodec/flate/flatemodule.cpp
+++ b/core/fxcodec/flate/flatemodule.cpp
@@ -24,9 +24,9 @@
#include "core/fxcrt/span_util.h"
#include "core/fxge/calculate_pitch.h"
#include "third_party/base/check.h"
+#include "third_party/base/containers/span.h"
#include "third_party/base/notreached.h"
#include "third_party/base/numerics/safe_conversions.h"
-#include "third_party/base/span.h"
#if defined(USE_SYSTEM_ZLIB)
#include <zlib.h>
diff --git a/core/fxcodec/flate/flatemodule.h b/core/fxcodec/flate/flatemodule.h
index f82c54264..f5a950969 100644
--- a/core/fxcodec/flate/flatemodule.h
+++ b/core/fxcodec/flate/flatemodule.h
@@ -13,7 +13,7 @@
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/fx_memory_wrappers.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace fxcodec {
diff --git a/core/fxcodec/gif/cfx_gifcontext.cpp b/core/fxcodec/gif/cfx_gifcontext.cpp
index e7fc432f2..98117590f 100644
--- a/core/fxcodec/gif/cfx_gifcontext.cpp
+++ b/core/fxcodec/gif/cfx_gifcontext.cpp
@@ -7,6 +7,7 @@
#include "core/fxcodec/gif/cfx_gifcontext.h"
#include <stdint.h>
+#include <string.h>
#include <algorithm>
#include <iterator>
diff --git a/core/fxcodec/gif/cfx_gifcontext.h b/core/fxcodec/gif/cfx_gifcontext.h
index 5e651f92c..e4d89c0e1 100644
--- a/core/fxcodec/gif/cfx_gifcontext.h
+++ b/core/fxcodec/gif/cfx_gifcontext.h
@@ -15,7 +15,7 @@
#include "core/fxcodec/gif/lzw_decompressor.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/unowned_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_CodecMemory;
diff --git a/core/fxcodec/gif/gif_decoder.h b/core/fxcodec/gif/gif_decoder.h
index cfcf0e961..1e2d39a6b 100644
--- a/core/fxcodec/gif/gif_decoder.h
+++ b/core/fxcodec/gif/gif_decoder.h
@@ -13,7 +13,7 @@
#include "core/fxcodec/gif/cfx_gif.h"
#include "core/fxcodec/progressive_decoder_iface.h"
#include "core/fxcrt/fx_coordinates.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#ifndef PDF_ENABLE_XFA_GIF
#error "GIF must be enabled"
diff --git a/core/fxcodec/gif/lzw_decompressor.cpp b/core/fxcodec/gif/lzw_decompressor.cpp
index b13932b85..dbfa0b902 100644
--- a/core/fxcodec/gif/lzw_decompressor.cpp
+++ b/core/fxcodec/gif/lzw_decompressor.cpp
@@ -13,8 +13,8 @@
#include <utility>
#include "core/fxcrt/fx_safe_types.h"
+#include "third_party/base/memory/ptr_util.h"
#include "third_party/base/numerics/safe_math.h"
-#include "third_party/base/ptr_util.h"
namespace fxcodec {
diff --git a/core/fxcodec/icc/icc_transform.cpp b/core/fxcodec/icc/icc_transform.cpp
index 18f8a4179..485988d47 100644
--- a/core/fxcodec/icc/icc_transform.cpp
+++ b/core/fxcodec/icc/icc_transform.cpp
@@ -12,10 +12,9 @@
#include <memory>
#include "core/fxcrt/data_vector.h"
-#include "third_party/base/cxx17_backports.h"
+#include "third_party/base/memory/ptr_util.h"
#include "third_party/base/notreached.h"
#include "third_party/base/numerics/safe_conversions.h"
-#include "third_party/base/ptr_util.h"
namespace fxcodec {
@@ -128,8 +127,7 @@ void IccTransform::Translate(pdfium::span<const float> pSrcValues,
} else {
DataVector<uint8_t> inputs(std::max<size_t>(pSrcValues.size(), 16));
for (size_t i = 0; i < pSrcValues.size(); ++i) {
- inputs[i] =
- pdfium::clamp(static_cast<int>(pSrcValues[i] * 255.0f), 0, 255);
+ inputs[i] = std::clamp(static_cast<int>(pSrcValues[i] * 255.0f), 0, 255);
}
cmsDoTransform(m_hTransform, inputs.data(), output, 1);
}
diff --git a/core/fxcodec/icc/icc_transform.h b/core/fxcodec/icc/icc_transform.h
index 78cf82693..47cda0786 100644
--- a/core/fxcodec/icc/icc_transform.h
+++ b/core/fxcodec/icc/icc_transform.h
@@ -12,7 +12,7 @@
#include <memory>
#include "core/fxcodec/fx_codec_def.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#if defined(USE_SYSTEM_LCMS2)
#include <lcms2.h>
diff --git a/core/fxcodec/jbig2/JBig2_ArithDecoder.cpp b/core/fxcodec/jbig2/JBig2_ArithDecoder.cpp
index 2555ee2c4..625ebf2e8 100644
--- a/core/fxcodec/jbig2/JBig2_ArithDecoder.cpp
+++ b/core/fxcodec/jbig2/JBig2_ArithDecoder.cpp
@@ -66,8 +66,7 @@ CJBig2_ArithDecoder::CJBig2_ArithDecoder(CJBig2_BitStream* pStream)
CJBig2_ArithDecoder::~CJBig2_ArithDecoder() = default;
int CJBig2_ArithDecoder::Decode(JBig2ArithCtx* pCX) {
- DCHECK(pCX);
- DCHECK_LT(pCX->I(), std::size(kQeTable));
+ CHECK_LT(pCX->I(), std::size(kQeTable));
const JBig2ArithCtx::JBig2ArithQe& qe = kQeTable[pCX->I()];
m_A -= qe.Qe;
diff --git a/core/fxcodec/jbig2/JBig2_BitStream.cpp b/core/fxcodec/jbig2/JBig2_BitStream.cpp
index 5f89716e3..6802c1bca 100644
--- a/core/fxcodec/jbig2/JBig2_BitStream.cpp
+++ b/core/fxcodec/jbig2/JBig2_BitStream.cpp
@@ -166,7 +166,7 @@ uint32_t CJBig2_BitStream::getLength() const {
}
const uint8_t* CJBig2_BitStream::getPointer() const {
- return getBuf() + m_dwByteIdx;
+ return m_Span.subspan(m_dwByteIdx).data();
}
void CJBig2_BitStream::offset(uint32_t dwOffset) {
diff --git a/core/fxcodec/jbig2/JBig2_BitStream.h b/core/fxcodec/jbig2/JBig2_BitStream.h
index b33f54861..0a3a44d34 100644
--- a/core/fxcodec/jbig2/JBig2_BitStream.h
+++ b/core/fxcodec/jbig2/JBig2_BitStream.h
@@ -8,7 +8,7 @@
#define CORE_FXCODEC_JBIG2_JBIG2_BITSTREAM_H_
#include "core/fxcrt/retain_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CJBig2_BitStream {
public:
diff --git a/core/fxcodec/jbig2/JBig2_Context.cpp b/core/fxcodec/jbig2/JBig2_Context.cpp
index 31b6f7204..0d9028e6c 100644
--- a/core/fxcodec/jbig2/JBig2_Context.cpp
+++ b/core/fxcodec/jbig2/JBig2_Context.cpp
@@ -26,7 +26,7 @@
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/pauseindicator_iface.h"
#include "third_party/base/check.h"
-#include "third_party/base/ptr_util.h"
+#include "third_party/base/memory/ptr_util.h"
namespace {
diff --git a/core/fxcodec/jbig2/JBig2_Context.h b/core/fxcodec/jbig2/JBig2_Context.h
index 279db5bac..5572eb751 100644
--- a/core/fxcodec/jbig2/JBig2_Context.h
+++ b/core/fxcodec/jbig2/JBig2_Context.h
@@ -17,7 +17,7 @@
#include "core/fxcodec/jbig2/JBig2_Page.h"
#include "core/fxcodec/jbig2/JBig2_Segment.h"
#include "core/fxcrt/unowned_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CJBig2_ArithDecoder;
class CJBig2_GRDProc;
diff --git a/core/fxcodec/jbig2/JBig2_GrdProc.h b/core/fxcodec/jbig2/JBig2_GrdProc.h
index 197eb91d9..c543ea11b 100644
--- a/core/fxcodec/jbig2/JBig2_GrdProc.h
+++ b/core/fxcodec/jbig2/JBig2_GrdProc.h
@@ -14,6 +14,7 @@
#include "core/fxcodec/fx_codec_def.h"
#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/unowned_ptr.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
class CJBig2_ArithDecoder;
class CJBig2_BitStream;
@@ -28,7 +29,7 @@ class CJBig2_GRDProc {
ProgressiveArithDecodeState();
~ProgressiveArithDecodeState();
- std::unique_ptr<CJBig2_Image>* pImage;
+ UnownedPtr<std::unique_ptr<CJBig2_Image>> pImage;
UnownedPtr<CJBig2_ArithDecoder> pArithDecoder;
UnownedPtr<JBig2ArithCtx> gbContext;
UnownedPtr<PauseIndicatorIface> pPause;
@@ -94,7 +95,7 @@ class CJBig2_GRDProc {
JBig2ArithCtx* gbContext);
uint32_t m_loopIndex = 0;
- uint8_t* m_pLine = nullptr;
+ UNOWNED_PTR_EXCLUSION uint8_t* m_pLine = nullptr;
FXCODEC_STATUS m_ProgressiveStatus;
uint16_t m_DecodeType = 0;
int m_LTP = 0;
diff --git a/core/fxcodec/jbig2/JBig2_HtrdProc.cpp b/core/fxcodec/jbig2/JBig2_HtrdProc.cpp
index 1c0f88237..16a87cc05 100644
--- a/core/fxcodec/jbig2/JBig2_HtrdProc.cpp
+++ b/core/fxcodec/jbig2/JBig2_HtrdProc.cpp
@@ -13,6 +13,10 @@
#include "core/fxcodec/jbig2/JBig2_GrdProc.h"
#include "core/fxcodec/jbig2/JBig2_Image.h"
+CJBig2_HTRDProc::CJBig2_HTRDProc() = default;
+
+CJBig2_HTRDProc::~CJBig2_HTRDProc() = default;
+
std::unique_ptr<CJBig2_Image> CJBig2_HTRDProc::DecodeArith(
CJBig2_ArithDecoder* pArithDecoder,
JBig2ArithCtx* gbContext,
diff --git a/core/fxcodec/jbig2/JBig2_HtrdProc.h b/core/fxcodec/jbig2/JBig2_HtrdProc.h
index 30e9d9cdd..2073d8b46 100644
--- a/core/fxcodec/jbig2/JBig2_HtrdProc.h
+++ b/core/fxcodec/jbig2/JBig2_HtrdProc.h
@@ -13,6 +13,7 @@
#include <vector>
#include "core/fxcodec/jbig2/JBig2_Image.h"
+#include "core/fxcrt/unowned_ptr.h"
class CJBig2_ArithDecoder;
class CJBig2_BitStream;
@@ -21,6 +22,9 @@ class PauseIndicatorIface;
class CJBig2_HTRDProc {
public:
+ CJBig2_HTRDProc();
+ ~CJBig2_HTRDProc();
+
std::unique_ptr<CJBig2_Image> DecodeArith(CJBig2_ArithDecoder* pArithDecoder,
JBig2ArithCtx* gbContext,
PauseIndicatorIface* pPause);
@@ -33,7 +37,7 @@ class CJBig2_HTRDProc {
bool HMMR;
uint8_t HTEMPLATE;
uint32_t HNUMPATS;
- const std::vector<std::unique_ptr<CJBig2_Image>>* HPATS;
+ UnownedPtr<const std::vector<std::unique_ptr<CJBig2_Image>>> HPATS;
bool HDEFPIXEL;
JBig2ComposeOp HCOMBOP;
bool HENABLESKIP;
diff --git a/core/fxcodec/jbig2/JBig2_HuffmanTable.cpp b/core/fxcodec/jbig2/JBig2_HuffmanTable.cpp
index fcbdb3453..f59ab4d35 100644
--- a/core/fxcodec/jbig2/JBig2_HuffmanTable.cpp
+++ b/core/fxcodec/jbig2/JBig2_HuffmanTable.cpp
@@ -12,6 +12,7 @@
#include "core/fxcodec/jbig2/JBig2_BitStream.h"
#include "core/fxcodec/jbig2/JBig2_Context.h"
#include "core/fxcrt/fx_safe_types.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
#include "third_party/base/check.h"
namespace {
@@ -24,7 +25,7 @@ struct JBig2TableLine {
struct HuffmanTable {
bool HTOOB;
- const JBig2TableLine* lines;
+ UNOWNED_PTR_EXCLUSION const JBig2TableLine* lines;
size_t size;
};
diff --git a/core/fxcodec/jbig2/JBig2_Image.h b/core/fxcodec/jbig2/JBig2_Image.h
index 4f751f4be..1fe8402af 100644
--- a/core/fxcodec/jbig2/JBig2_Image.h
+++ b/core/fxcodec/jbig2/JBig2_Image.h
@@ -12,7 +12,7 @@
#include "core/fxcodec/jbig2/JBig2_Define.h"
#include "core/fxcrt/fx_memory_wrappers.h"
#include "core/fxcrt/maybe_owned.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
struct FX_RECT;
diff --git a/core/fxcodec/jbig2/JBig2_SddProc.h b/core/fxcodec/jbig2/JBig2_SddProc.h
index 09478ebb0..a1e7590ea 100644
--- a/core/fxcodec/jbig2/JBig2_SddProc.h
+++ b/core/fxcodec/jbig2/JBig2_SddProc.h
@@ -14,7 +14,8 @@
#include "core/fxcodec/jbig2/JBig2_ArithDecoder.h"
#include "core/fxcrt/unowned_ptr.h"
-#include "third_party/base/span.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
+#include "third_party/base/containers/span.h"
class CJBig2_BitStream;
class CJBig2_HuffmanTable;
@@ -43,7 +44,7 @@ class CJBig2_SDDProc {
uint32_t SDNUMINSYMS;
uint32_t SDNUMNEWSYMS;
uint32_t SDNUMEXSYMS;
- CJBig2_Image** SDINSYMS;
+ UNOWNED_PTR_EXCLUSION CJBig2_Image** SDINSYMS;
UnownedPtr<const CJBig2_HuffmanTable> SDHUFFDH;
UnownedPtr<const CJBig2_HuffmanTable> SDHUFFDW;
UnownedPtr<const CJBig2_HuffmanTable> SDHUFFBMSIZE;
diff --git a/core/fxcodec/jbig2/JBig2_TrdProc.h b/core/fxcodec/jbig2/JBig2_TrdProc.h
index 7962c7011..bd887d95d 100644
--- a/core/fxcodec/jbig2/JBig2_TrdProc.h
+++ b/core/fxcodec/jbig2/JBig2_TrdProc.h
@@ -14,6 +14,7 @@
#include "core/fxcodec/jbig2/JBig2_Image.h"
#include "core/fxcrt/unowned_ptr.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
class CJBig2_ArithDecoder;
class CJBig2_ArithIaidDecoder;
@@ -71,7 +72,7 @@ class CJBig2_TRDProc {
uint32_t SBSTRIPS;
uint32_t SBNUMSYMS;
std::vector<JBig2HuffmanCode> SBSYMCODES;
- CJBig2_Image** SBSYMS;
+ UNOWNED_PTR_EXCLUSION CJBig2_Image** SBSYMS;
JBig2ComposeOp SBCOMBOP;
JBig2Corner REFCORNER;
UnownedPtr<const CJBig2_HuffmanTable> SBHUFFFS;
diff --git a/core/fxcodec/jbig2/jbig2_decoder.h b/core/fxcodec/jbig2/jbig2_decoder.h
index 0a94f5de8..745fa2ea6 100644
--- a/core/fxcodec/jbig2/jbig2_decoder.h
+++ b/core/fxcodec/jbig2/jbig2_decoder.h
@@ -10,7 +10,8 @@
#include <memory>
#include "core/fxcodec/fx_codec_def.h"
-#include "third_party/base/span.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
+#include "third_party/base/containers/span.h"
class CJBig2_Context;
class JBig2_DocumentContext;
@@ -29,7 +30,7 @@ class Jbig2Context {
uint64_t m_nSrcKey = 0;
pdfium::span<const uint8_t> m_pGlobalSpan;
pdfium::span<const uint8_t> m_pSrcSpan;
- uint8_t* m_dest_buf = nullptr;
+ UNOWNED_PTR_EXCLUSION uint8_t* m_dest_buf = nullptr;
uint32_t m_dest_pitch = 0;
std::unique_ptr<CJBig2_Context> m_pContext;
};
diff --git a/core/fxcodec/jpeg/jpeg_progressive_decoder.cpp b/core/fxcodec/jpeg/jpeg_progressive_decoder.cpp
index c662f144c..1f1a7c375 100644
--- a/core/fxcodec/jpeg/jpeg_progressive_decoder.cpp
+++ b/core/fxcodec/jpeg/jpeg_progressive_decoder.cpp
@@ -17,7 +17,7 @@
#include "core/fxge/dib/fx_dib.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/base/check.h"
-#include "third_party/base/ptr_util.h"
+#include "third_party/base/memory/ptr_util.h"
class CJpegContext final : public ProgressiveDecoderIface::Context {
public:
diff --git a/core/fxcodec/jpeg/jpegmodule.h b/core/fxcodec/jpeg/jpegmodule.h
index a4e20ef91..0f617656b 100644
--- a/core/fxcodec/jpeg/jpegmodule.h
+++ b/core/fxcodec/jpeg/jpegmodule.h
@@ -13,7 +13,7 @@
#include "build/build_config.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#if BUILDFLAG(IS_WIN)
#include "core/fxcrt/retain_ptr.h"
diff --git a/core/fxcodec/jpx/cjpx_decoder.cpp b/core/fxcodec/jpx/cjpx_decoder.cpp
index 9391d61ab..2e7a72aa1 100644
--- a/core/fxcodec/jpx/cjpx_decoder.cpp
+++ b/core/fxcodec/jpx/cjpx_decoder.cpp
@@ -18,8 +18,7 @@
#include "core/fxcrt/span_util.h"
#include "core/fxge/calculate_pitch.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/base/cxx17_backports.h"
-#include "third_party/base/ptr_util.h"
+#include "third_party/base/memory/ptr_util.h"
#if !defined(USE_SYSTEM_LIBOPENJPEG2)
#include "third_party/libopenjpeg/opj_malloc.h"
@@ -88,9 +87,9 @@ void sycc_to_rgb(int offset,
int* out_b) {
cb -= offset;
cr -= offset;
- *out_r = pdfium::clamp(y + static_cast<int>(1.402 * cr), 0, upb);
- *out_g = pdfium::clamp(y - static_cast<int>(0.344 * cb + 0.714 * cr), 0, upb);
- *out_b = pdfium::clamp(y + static_cast<int>(1.772 * cb), 0, upb);
+ *out_r = std::clamp(y + static_cast<int>(1.402 * cr), 0, upb);
+ *out_g = std::clamp(y - static_cast<int>(0.344 * cb + 0.714 * cr), 0, upb);
+ *out_b = std::clamp(y + static_cast<int>(1.772 * cb), 0, upb);
}
void sycc444_to_rgb(opj_image_t* img) {
@@ -594,7 +593,7 @@ bool CJPX_Decoder::Decode(pdfium::span<uint8_t> dest_buf,
uint8_t* pPixel = pScanline + col * channel_count;
int src = comps.data[row * width + col] + src_offset;
int pixel = (src >> adjust) + ((src >> (adjust - 1)) % 2);
- pixel = pdfium::clamp(pixel, 0, 255);
+ pixel = std::clamp(pixel, 0, 255);
*pPixel = static_cast<uint8_t>(pixel);
}
}
diff --git a/core/fxcodec/jpx/cjpx_decoder.h b/core/fxcodec/jpx/cjpx_decoder.h
index 36116b3a9..c6e67c887 100644
--- a/core/fxcodec/jpx/cjpx_decoder.h
+++ b/core/fxcodec/jpx/cjpx_decoder.h
@@ -12,7 +12,7 @@
#include <memory>
#include "core/fxcrt/unowned_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#if defined(USE_SYSTEM_LIBOPENJPEG2)
#include <openjpeg.h>
diff --git a/core/fxcodec/jpx/jpx_unittest.cpp b/core/fxcodec/jpx/jpx_unittest.cpp
index b89a91012..84e6a35d0 100644
--- a/core/fxcodec/jpx/jpx_unittest.cpp
+++ b/core/fxcodec/jpx/jpx_unittest.cpp
@@ -9,6 +9,7 @@
#include "core/fxcodec/jpx/cjpx_decoder.h"
#include "core/fxcodec/jpx/jpx_decode_utils.h"
+#include "core/fxcrt/fx_memcpy_wrappers.h"
#include "core/fxcrt/fx_memory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/libopenjpeg/opj_malloc.h"
@@ -424,9 +425,9 @@ TEST(fxcodec, YUV420ToRGB) {
opj_image_data_alloc(v.w * v.h * sizeof(OPJ_INT32)));
u.data = static_cast<OPJ_INT32*>(
opj_image_data_alloc(u.w * u.h * sizeof(OPJ_INT32)));
- memset(y.data, 1, y.w * y.h * sizeof(OPJ_INT32));
- memset(u.data, 0, u.w * u.h * sizeof(OPJ_INT32));
- memset(v.data, 0, v.w * v.h * sizeof(OPJ_INT32));
+ FXSYS_memset(y.data, 1, y.w * y.h * sizeof(OPJ_INT32));
+ FXSYS_memset(u.data, 0, u.w * u.h * sizeof(OPJ_INT32));
+ FXSYS_memset(v.data, 0, v.w * v.h * sizeof(OPJ_INT32));
img.comps[0] = y;
img.comps[1] = u;
img.comps[2] = v;
diff --git a/core/fxcodec/progressive_decoder.cpp b/core/fxcodec/progressive_decoder.cpp
index a65e2bb75..8e845005c 100644
--- a/core/fxcodec/progressive_decoder.cpp
+++ b/core/fxcodec/progressive_decoder.cpp
@@ -633,8 +633,6 @@ void ProgressiveDecoder::ResampleVertBT(
*scan_des++ = CStretchEngine::PixelFromFixed(dest_a);
}
break;
- default:
- return;
}
}
}
@@ -908,8 +906,6 @@ void ProgressiveDecoder::GifDoubleLineResampleVert(
*scan_des++ = CStretchEngine::PixelFromFixed(dest_a);
}
break;
- default:
- return;
}
}
int dest_bottom = dest_top + m_sizeY - 1;
@@ -1999,8 +1995,6 @@ void ProgressiveDecoder::ResampleVert(
*scan_des++ = CStretchEngine::PixelFromFixed(dest_a);
}
break;
- default:
- return;
}
}
int dest_bottom = dest_top + m_sizeY;
diff --git a/core/fxcodec/progressive_decoder.h b/core/fxcodec/progressive_decoder.h
index 2f8d2ab6b..6325c8877 100644
--- a/core/fxcodec/progressive_decoder.h
+++ b/core/fxcodec/progressive_decoder.h
@@ -18,9 +18,10 @@
#include "core/fxcodec/progressive_decoder_iface.h"
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/retain_ptr.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
#include "core/fxge/dib/cstretchengine.h"
#include "core/fxge/dib/fx_dib.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#ifdef PDF_ENABLE_XFA_BMP
#include "core/fxcodec/bmp/bmp_decoder.h"
@@ -263,7 +264,7 @@ class ProgressiveDecoder final :
size_t m_FrameCur = 0;
#ifdef PDF_ENABLE_XFA_GIF
int m_GifBgIndex = 0;
- CFX_GifPalette* m_pGifPalette = nullptr;
+ UNOWNED_PTR_EXCLUSION CFX_GifPalette* m_pGifPalette = nullptr;
int32_t m_GifPltNumber = 0;
int m_GifTransIndex = -1;
FX_RECT m_GifFrameRect;
diff --git a/core/fxcodec/progressive_decoder_unittest.cpp b/core/fxcodec/progressive_decoder_unittest.cpp
index cdc0ae1c7..ccb0c0385 100644
--- a/core/fxcodec/progressive_decoder_unittest.cpp
+++ b/core/fxcodec/progressive_decoder_unittest.cpp
@@ -22,7 +22,7 @@
#include "core/fxge/dib/fx_dib.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#ifdef PDF_ENABLE_XFA_BMP
#include "core/fxcodec/bmp/bmp_decoder.h"
diff --git a/core/fxcodec/scanlinedecoder.h b/core/fxcodec/scanlinedecoder.h
index 0a1db37f8..f31914735 100644
--- a/core/fxcodec/scanlinedecoder.h
+++ b/core/fxcodec/scanlinedecoder.h
@@ -9,7 +9,7 @@
#include <stdint.h>
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class PauseIndicatorIface;
diff --git a/core/fxcrt/BUILD.gn b/core/fxcrt/BUILD.gn
index 09400e881..c9bdfa01e 100644
--- a/core/fxcrt/BUILD.gn
+++ b/core/fxcrt/BUILD.gn
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build_overrides/build.gni")
import("../../pdfium.gni")
import("../../testing/test.gni")
@@ -9,6 +10,12 @@ source_set("unowned_ptr") {
sources = [ "unowned_ptr.h" ]
deps = [ "../../third_party:pdfium_compiler_specific" ]
configs += [ "../../:pdfium_strict_config" ]
+ if (pdf_use_partition_alloc) {
+ public_deps = [
+ "//base/allocator/partition_allocator:partition_alloc_buildflags",
+ "//base/allocator/partition_allocator:raw_ptr",
+ ]
+ }
}
source_set("fxcrt") {
@@ -34,10 +41,7 @@ source_set("fxcrt") {
"cfx_seekablestreamproxy.h",
"cfx_timer.cpp",
"cfx_timer.h",
- "cfx_utf8decoder.cpp",
- "cfx_utf8decoder.h",
- "cfx_utf8encoder.cpp",
- "cfx_utf8encoder.h",
+ "code_point_view.h",
"data_vector.h",
"fileaccess_iface.h",
"fixed_size_data_vector.h",
@@ -55,6 +59,7 @@ source_set("fxcrt") {
"fx_extension.cpp",
"fx_extension.h",
"fx_folder.h",
+ "fx_memcpy_wrappers.h",
"fx_memory.cpp",
"fx_memory.h",
"fx_memory_wrappers.h",
@@ -89,6 +94,7 @@ source_set("fxcrt") {
"string_pool_template.h",
"string_view_template.h",
"tree_node.h",
+ "utf16.h",
"weak_ptr.h",
"widestring.cpp",
"widestring.h",
@@ -136,7 +142,11 @@ source_set("fxcrt") {
]
if (pdf_use_partition_alloc) {
sources += [ "fx_memory_pa.cpp" ]
- deps += [ "//base/allocator/partition_allocator:partition_alloc" ]
+ deps += [
+ "//base/allocator/partition_allocator:partition_alloc",
+ "//base/allocator/partition_allocator:partition_alloc_buildflags",
+ "//base/allocator/partition_allocator:raw_ptr",
+ ]
} else {
sources += [ "fx_memory_malloc.cpp" ]
}
@@ -162,6 +172,13 @@ source_set("fxcrt") {
}
}
+source_set("test_support") {
+ testonly = true
+ sources = [ "string_test_support.cpp" ]
+ configs += [ "../../:pdfium_strict_config" ]
+ deps = [ ":fxcrt" ]
+}
+
source_set("unit_test_support") {
testonly = true
sources = [
@@ -171,6 +188,7 @@ source_set("unit_test_support") {
configs += [ "../../:pdfium_strict_config" ]
deps = [
":fxcrt",
+ ":test_support",
"//testing/gtest",
]
}
@@ -186,12 +204,14 @@ pdfium_unittest_source_set("unittests") {
"cfx_datetime_unittest.cpp",
"cfx_seekablestreamproxy_unittest.cpp",
"cfx_timer_unittest.cpp",
+ "code_point_view_unittest.cpp",
"fixed_try_alloc_zeroed_data_vector_unittest.cpp",
"fixed_uninit_data_vector_unittest.cpp",
"fixed_zeroed_data_vector_unittest.cpp",
"fx_bidi_unittest.cpp",
"fx_coordinates_unittest.cpp",
"fx_extension_unittest.cpp",
+ "fx_memcpy_wrappers_unittest.cpp",
"fx_memory_unittest.cpp",
"fx_memory_wrappers_unittest.cpp",
"fx_number_unittest.cpp",
@@ -212,6 +232,7 @@ pdfium_unittest_source_set("unittests") {
"string_pool_template_unittest.cpp",
"tree_node_unittest.cpp",
"unowned_ptr_unittest.cpp",
+ "utf16_unittest.cpp",
"weak_ptr_unittest.cpp",
"widestring_unittest.cpp",
"widetext_buffer_unittest.cpp",
@@ -225,7 +246,9 @@ pdfium_unittest_source_set("unittests") {
]
deps = [ ":unit_test_support" ]
pdfium_root_dir = "../../"
-
+ if (pdf_use_partition_alloc) {
+ deps += [ "//base/allocator/partition_allocator:partition_alloc" ]
+ }
if (pdf_enable_xfa) {
sources += [ "cfx_memorystream_unittest.cpp" ]
deps += [ "../fpdfapi/parser" ]
diff --git a/core/fxcrt/autonuller.h b/core/fxcrt/autonuller.h
index 12df63fe7..88ae0cb2f 100644
--- a/core/fxcrt/autonuller.h
+++ b/core/fxcrt/autonuller.h
@@ -6,6 +6,7 @@
#define CORE_FXCRT_AUTONULLER_H_
#include "core/fxcrt/fx_memory.h"
+#include "core/fxcrt/unowned_ptr.h"
namespace fxcrt {
@@ -22,7 +23,7 @@ class AutoNuller {
void AbandonNullification() { m_Location = nullptr; }
private:
- T* m_Location;
+ UnownedPtr<T> m_Location;
};
} // namespace fxcrt
diff --git a/core/fxcrt/autorestorer.h b/core/fxcrt/autorestorer.h
index 02b5f3da0..cecd0cd0e 100644
--- a/core/fxcrt/autorestorer.h
+++ b/core/fxcrt/autorestorer.h
@@ -6,6 +6,7 @@
#define CORE_FXCRT_AUTORESTORER_H_
#include "core/fxcrt/fx_memory.h"
+#include "core/fxcrt/unowned_ptr.h"
namespace fxcrt {
@@ -23,7 +24,7 @@ class AutoRestorer {
void AbandonRestoration() { m_Location = nullptr; }
private:
- T* m_Location;
+ UnownedPtr<T> m_Location;
const T m_OldValue;
};
diff --git a/core/fxcrt/binary_buffer.h b/core/fxcrt/binary_buffer.h
index 9150266ce..26f0cafb8 100644
--- a/core/fxcrt/binary_buffer.h
+++ b/core/fxcrt/binary_buffer.h
@@ -12,7 +12,7 @@
#include "core/fxcrt/bytestring.h"
#include "core/fxcrt/data_vector.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace fxcrt {
diff --git a/core/fxcrt/bytestring.cpp b/core/fxcrt/bytestring.cpp
index d3e1cc043..d2ba60e1c 100644
--- a/core/fxcrt/bytestring.cpp
+++ b/core/fxcrt/bytestring.cpp
@@ -14,17 +14,16 @@
#include <string>
#include <utility>
-#include "core/fxcrt/cfx_utf8decoder.h"
#include "core/fxcrt/fx_codepage.h"
#include "core/fxcrt/fx_extension.h"
+#include "core/fxcrt/fx_memcpy_wrappers.h"
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/fx_system.h"
#include "core/fxcrt/string_pool_template.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
-#include "third_party/base/cxx17_backports.h"
+#include "third_party/base/containers/span.h"
#include "third_party/base/numerics/safe_math.h"
-#include "third_party/base/span.h"
template class fxcrt::StringDataTemplate<char>;
template class fxcrt::StringViewTemplate<char>;
@@ -263,7 +262,7 @@ bool ByteString::operator==(const char* ptr) const {
return m_pData->m_nDataLength == 0;
return strlen(ptr) == m_pData->m_nDataLength &&
- memcmp(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0;
+ FXSYS_memcmp(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0;
}
bool ByteString::operator==(ByteStringView str) const {
@@ -271,8 +270,8 @@ bool ByteString::operator==(ByteStringView str) const {
return str.IsEmpty();
return m_pData->m_nDataLength == str.GetLength() &&
- memcmp(m_pData->m_String, str.unterminated_c_str(), str.GetLength()) ==
- 0;
+ FXSYS_memcmp(m_pData->m_String, str.unterminated_c_str(),
+ str.GetLength()) == 0;
}
bool ByteString::operator==(const ByteString& other) const {
@@ -298,7 +297,7 @@ bool ByteString::operator<(const char* ptr) const {
size_t len = GetLength();
size_t other_len = ptr ? strlen(ptr) : 0;
- int result = memcmp(c_str(), ptr, std::min(len, other_len));
+ int result = FXSYS_memcmp(c_str(), ptr, std::min(len, other_len));
return result < 0 || (result == 0 && len < other_len);
}
@@ -312,7 +311,7 @@ bool ByteString::operator<(const ByteString& other) const {
size_t len = GetLength();
size_t other_len = other.GetLength();
- int result = memcmp(c_str(), other.c_str(), std::min(len, other_len));
+ int result = FXSYS_memcmp(c_str(), other.c_str(), std::min(len, other_len));
return result < 0 || (result == 0 && len < other_len);
}
@@ -433,8 +432,9 @@ size_t ByteString::Delete(size_t index, size_t count) {
return 0;
size_t old_length = m_pData->m_nDataLength;
- if (count == 0 || index != pdfium::clamp<size_t>(index, 0, old_length))
+ if (count == 0 || index != std::clamp<size_t>(index, 0, old_length)) {
return old_length;
+ }
size_t removal_length = index + count;
if (removal_length > old_length)
@@ -442,8 +442,8 @@ size_t ByteString::Delete(size_t index, size_t count) {
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);
+ FXSYS_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;
}
@@ -535,8 +535,8 @@ size_t ByteString::Insert(size_t index, char ch) {
const size_t new_length = cur_length + 1;
ReallocBeforeWrite(new_length);
- memmove(m_pData->m_String + index + 1, m_pData->m_String + index,
- new_length - index);
+ FXSYS_memmove(m_pData->m_String + index + 1, m_pData->m_String + index,
+ new_length - index);
m_pData->m_String[index] = ch;
m_pData->m_nDataLength = new_length;
return new_length;
@@ -549,8 +549,8 @@ absl::optional<size_t> ByteString::Find(char ch, size_t start) const {
if (!IsValidIndex(start))
return absl::nullopt;
- const char* pStr = static_cast<const char*>(
- memchr(m_pData->m_String + start, ch, m_pData->m_nDataLength - start));
+ const char* pStr = static_cast<const char*>(FXSYS_memchr(
+ m_pData->m_String + start, ch, m_pData->m_nDataLength - start));
return pStr ? absl::optional<size_t>(
static_cast<size_t>(pStr - m_pData->m_String))
: absl::nullopt;
@@ -669,13 +669,13 @@ size_t ByteString::Replace(ByteStringView pOld, ByteStringView pNew) {
for (size_t i = 0; i < nCount; i++) {
const char* pTarget = FX_strstr(pStart, static_cast<int>(pEnd - pStart),
pOld.unterminated_c_str(), nSourceLen);
- memcpy(pDest, pStart, pTarget - pStart);
+ FXSYS_memcpy(pDest, pStart, pTarget - pStart);
pDest += pTarget - pStart;
- memcpy(pDest, pNew.unterminated_c_str(), pNew.GetLength());
+ FXSYS_memcpy(pDest, pNew.unterminated_c_str(), pNew.GetLength());
pDest += pNew.GetLength();
pStart = pTarget + nSourceLen;
}
- memcpy(pDest, pStart, pEnd - pStart);
+ FXSYS_memcpy(pDest, pStart, pEnd - pStart);
m_pData.Swap(pNewData);
return nCount;
}
@@ -687,7 +687,8 @@ int ByteString::Compare(ByteStringView str) const {
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);
+ int result =
+ FXSYS_memcmp(m_pData->m_String, str.unterminated_c_str(), min_len);
if (result != 0)
return result;
if (this_len == that_len)
@@ -739,8 +740,8 @@ void ByteString::TrimLeft(ByteStringView targets) {
if (pos) {
ReallocBeforeWrite(len);
size_t nDataLength = len - pos;
- memmove(m_pData->m_String, m_pData->m_String + pos,
- (nDataLength + 1) * sizeof(char));
+ FXSYS_memmove(m_pData->m_String, m_pData->m_String + pos,
+ (nDataLength + 1) * sizeof(char));
m_pData->m_nDataLength = nDataLength;
}
}
diff --git a/core/fxcrt/bytestring.h b/core/fxcrt/bytestring.h
index 5f1ed53e4..3c23d6207 100644
--- a/core/fxcrt/bytestring.h
+++ b/core/fxcrt/bytestring.h
@@ -23,7 +23,7 @@
#include "core/fxcrt/string_view_template.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/base/check.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace fxcrt {
@@ -286,6 +286,13 @@ inline ByteString operator+(ByteStringView str1, const ByteString& str2) {
std::ostream& operator<<(std::ostream& os, const ByteString& str);
std::ostream& operator<<(std::ostream& os, ByteStringView str);
+// This is declared here for use in gtest-based tests but is defined in a test
+// support target. This should not be used in production code. Just use
+// operator<< from above instead.
+// In some cases, gtest will automatically use operator<< as well, but in this
+// case, it needs PrintTo() because ByteString looks like a container to gtest.
+void PrintTo(const ByteString& str, std::ostream* os);
+
} // namespace fxcrt
using ByteString = fxcrt::ByteString;
diff --git a/core/fxcrt/bytestring_unittest.cpp b/core/fxcrt/bytestring_unittest.cpp
index f00bb4631..9d2f132a3 100644
--- a/core/fxcrt/bytestring_unittest.cpp
+++ b/core/fxcrt/bytestring_unittest.cpp
@@ -15,7 +15,7 @@
#include "core/fxcrt/fx_string.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/base/containers/contains.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace fxcrt {
diff --git a/core/fxcrt/cfx_bitstream.h b/core/fxcrt/cfx_bitstream.h
index c60cf0a36..8e168b86c 100644
--- a/core/fxcrt/cfx_bitstream.h
+++ b/core/fxcrt/cfx_bitstream.h
@@ -10,7 +10,7 @@
#include <stddef.h>
#include <stdint.h>
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_BitStream {
public:
diff --git a/core/fxcrt/cfx_datetime.cpp b/core/fxcrt/cfx_datetime.cpp
index 50f1c6a35..526bba458 100644
--- a/core/fxcrt/cfx_datetime.cpp
+++ b/core/fxcrt/cfx_datetime.cpp
@@ -10,7 +10,7 @@
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/fx_system.h"
#include "third_party/base/check.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace {
diff --git a/core/fxcrt/cfx_fileaccess_windows.h b/core/fxcrt/cfx_fileaccess_windows.h
index 2928d1823..89c79e93f 100644
--- a/core/fxcrt/cfx_fileaccess_windows.h
+++ b/core/fxcrt/cfx_fileaccess_windows.h
@@ -13,6 +13,7 @@
#include "build/build_config.h"
#include "core/fxcrt/fileaccess_iface.h"
#include "core/fxcrt/fx_types.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
#if !BUILDFLAG(IS_WIN)
#error "Included on the wrong platform"
@@ -39,7 +40,7 @@ class CFX_FileAccess_Windows final : public FileAccessIface {
bool Truncate(FX_FILESIZE szFile) override;
private:
- void* m_hFile = nullptr;
+ UNOWNED_PTR_EXCLUSION void* m_hFile = nullptr; // void type incompatible.
};
#endif // CORE_FXCRT_CFX_FILEACCESS_WINDOWS_H_
diff --git a/core/fxcrt/cfx_memorystream.h b/core/fxcrt/cfx_memorystream.h
index 5ecf9951b..b2620fccd 100644
--- a/core/fxcrt/cfx_memorystream.h
+++ b/core/fxcrt/cfx_memorystream.h
@@ -10,7 +10,7 @@
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/fx_stream.h"
#include "core/fxcrt/retain_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_MemoryStream final : public IFX_SeekableStream {
public:
diff --git a/core/fxcrt/cfx_read_only_span_stream.h b/core/fxcrt/cfx_read_only_span_stream.h
index b1b30cd6f..d476640e6 100644
--- a/core/fxcrt/cfx_read_only_span_stream.h
+++ b/core/fxcrt/cfx_read_only_span_stream.h
@@ -9,7 +9,7 @@
#include "core/fxcrt/fx_stream.h"
#include "core/fxcrt/retain_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_ReadOnlySpanStream final : public IFX_SeekableReadStream {
public:
diff --git a/core/fxcrt/cfx_read_only_string_stream.cpp b/core/fxcrt/cfx_read_only_string_stream.cpp
index 62d550546..364330b29 100644
--- a/core/fxcrt/cfx_read_only_string_stream.cpp
+++ b/core/fxcrt/cfx_read_only_string_stream.cpp
@@ -7,7 +7,7 @@
#include <utility>
#include "core/fxcrt/cfx_read_only_span_stream.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
CFX_ReadOnlyStringStream::CFX_ReadOnlyStringStream(ByteString data)
: data_(std::move(data)),
diff --git a/core/fxcrt/cfx_read_only_vector_stream.cpp b/core/fxcrt/cfx_read_only_vector_stream.cpp
index d6a5bf00e..97f0dcbcc 100644
--- a/core/fxcrt/cfx_read_only_vector_stream.cpp
+++ b/core/fxcrt/cfx_read_only_vector_stream.cpp
@@ -7,7 +7,7 @@
#include <utility>
#include "core/fxcrt/cfx_read_only_span_stream.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
CFX_ReadOnlyVectorStream::CFX_ReadOnlyVectorStream(DataVector<uint8_t> data)
: data_(std::move(data)),
diff --git a/core/fxcrt/cfx_seekablestreamproxy.cpp b/core/fxcrt/cfx_seekablestreamproxy.cpp
index dc311ae92..6fb7eace4 100644
--- a/core/fxcrt/cfx_seekablestreamproxy.cpp
+++ b/core/fxcrt/cfx_seekablestreamproxy.cpp
@@ -18,7 +18,6 @@
#include "core/fxcrt/fx_safe_types.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
-#include "third_party/base/cxx17_backports.h"
namespace {
@@ -73,7 +72,7 @@ static_assert(sizeof(wchar_t) > 2, "wchar_t is too small");
void UTF16ToWChar(void* pBuffer, size_t iLength) {
DCHECK(pBuffer);
- DCHECK_GT(iLength, 0);
+ DCHECK_GT(iLength, 0u);
uint16_t* pSrc = static_cast<uint16_t*>(pBuffer);
wchar_t* pDst = static_cast<wchar_t*>(pBuffer);
@@ -156,8 +155,7 @@ void CFX_SeekableStreamProxy::Seek(From eSeek, FX_FILESIZE iOffset) {
new_pos.ValueOrDefault(std::numeric_limits<FX_FILESIZE>::max());
} break;
}
- m_iPosition =
- pdfium::clamp(m_iPosition, static_cast<FX_FILESIZE>(0), GetSize());
+ m_iPosition = std::clamp(m_iPosition, static_cast<FX_FILESIZE>(0), GetSize());
}
void CFX_SeekableStreamProxy::SetCodePage(FX_CodePage wCodePage) {
diff --git a/core/fxcrt/cfx_seekablestreamproxy_unittest.cpp b/core/fxcrt/cfx_seekablestreamproxy_unittest.cpp
index 94ebf6629..05cc492de 100644
--- a/core/fxcrt/cfx_seekablestreamproxy_unittest.cpp
+++ b/core/fxcrt/cfx_seekablestreamproxy_unittest.cpp
@@ -9,7 +9,7 @@
#include "core/fxcrt/cfx_read_only_span_stream.h"
#include "core/fxcrt/retain_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
TEST(SeekableStreamProxyTest, NullStream) {
auto proxy_stream = pdfium::MakeRetain<CFX_SeekableStreamProxy>(
diff --git a/core/fxcrt/cfx_utf8decoder.cpp b/core/fxcrt/cfx_utf8decoder.cpp
deleted file mode 100644
index e834815b0..000000000
--- a/core/fxcrt/cfx_utf8decoder.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2017 The PDFium Authors
-// Use of this source code is governed by 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"
-
-#include <utility>
-
-CFX_UTF8Decoder::CFX_UTF8Decoder(ByteStringView input) {
- for (char c : input) {
- ProcessByte(c);
- }
-}
-
-CFX_UTF8Decoder::~CFX_UTF8Decoder() = default;
-
-WideString CFX_UTF8Decoder::TakeResult() {
- return std::move(m_Buffer);
-}
-
-void CFX_UTF8Decoder::AppendCodePoint(uint32_t ch) {
- m_Buffer += static_cast<wchar_t>(ch);
-}
-
-void CFX_UTF8Decoder::ProcessByte(uint8_t byte) {
- if (byte < 0x80) {
- m_PendingBytes = 0;
- AppendCodePoint(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;
- } else {
- m_PendingBytes = 0;
- }
-}
diff --git a/core/fxcrt/cfx_utf8decoder.h b/core/fxcrt/cfx_utf8decoder.h
deleted file mode 100644
index 35b56719b..000000000
--- a/core/fxcrt/cfx_utf8decoder.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2017 The PDFium Authors
-// Use of this source code is governed by 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/string_view_template.h"
-#include "core/fxcrt/widestring.h"
-
-class CFX_UTF8Decoder {
- public:
- explicit CFX_UTF8Decoder(ByteStringView input);
- ~CFX_UTF8Decoder();
-
- WideString TakeResult();
-
- private:
- void ProcessByte(uint8_t byte);
- void AppendCodePoint(uint32_t ch);
-
- int m_PendingBytes = 0;
- uint32_t m_PendingChar = 0;
- WideString m_Buffer;
-};
-
-#endif // CORE_FXCRT_CFX_UTF8DECODER_H_
diff --git a/core/fxcrt/cfx_utf8encoder.cpp b/core/fxcrt/cfx_utf8encoder.cpp
deleted file mode 100644
index 4951126b3..000000000
--- a/core/fxcrt/cfx_utf8encoder.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2018 The PDFium Authors
-// Use of this source code is governed by 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_utf8encoder.h"
-
-CFX_UTF8Encoder::CFX_UTF8Encoder() = default;
-
-CFX_UTF8Encoder::~CFX_UTF8Encoder() = default;
-
-void CFX_UTF8Encoder::Input(wchar_t unicodeAsWchar) {
- uint32_t unicode = static_cast<uint32_t>(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 const 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));
- }
- }
-}
diff --git a/core/fxcrt/cfx_utf8encoder.h b/core/fxcrt/cfx_utf8encoder.h
deleted file mode 100644
index 13815cd12..000000000
--- a/core/fxcrt/cfx_utf8encoder.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2018 The PDFium Authors
-// Use of this source code is governed by 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_UTF8ENCODER_H_
-#define CORE_FXCRT_CFX_UTF8ENCODER_H_
-
-#include <stdint.h>
-
-#include "core/fxcrt/bytestring.h"
-#include "core/fxcrt/data_vector.h"
-
-class CFX_UTF8Encoder {
- public:
- CFX_UTF8Encoder();
- ~CFX_UTF8Encoder();
-
- void Input(wchar_t unicodeAsWchar);
-
- // 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:
- DataVector<uint8_t> m_Buffer;
-};
-
-#endif // CORE_FXCRT_CFX_UTF8ENCODER_H_
diff --git a/core/fxcrt/code_point_view.h b/core/fxcrt/code_point_view.h
new file mode 100644
index 000000000..032d4a163
--- /dev/null
+++ b/core/fxcrt/code_point_view.h
@@ -0,0 +1,91 @@
+// Copyright 2023 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CORE_FXCRT_CODE_POINT_VIEW_H_
+#define CORE_FXCRT_CODE_POINT_VIEW_H_
+
+#include "build/build_config.h"
+#include "core/fxcrt/string_view_template.h"
+#include "core/fxcrt/utf16.h"
+#include "third_party/base/check_op.h"
+
+namespace pdfium {
+
+#if defined(WCHAR_T_IS_UTF16)
+// A view over a UTF-16 `WideStringView` suitable for iterating by code point
+// using a range-based `for` loop.
+class CodePointView final {
+ public:
+ class Iterator {
+ public:
+ bool operator==(const Iterator& other) const {
+ return current_ == other.current_;
+ }
+
+ bool operator!=(const Iterator& other) const {
+ return current_ != other.current_;
+ }
+
+ Iterator& operator++() {
+ DCHECK_LT(current_, end_);
+ current_ += IsSupplementary(code_point_) ? 2 : 1;
+ code_point_ = Decode();
+ return *this;
+ }
+
+ char32_t operator*() const {
+ DCHECK_NE(kSentinel, code_point_);
+ return code_point_;
+ }
+
+ private:
+ friend class CodePointView;
+
+ static constexpr char32_t kSentinel = -1;
+
+ Iterator(const wchar_t* begin, const wchar_t* end)
+ : current_(begin), end_(end), code_point_(Decode()) {}
+
+ char32_t Decode() {
+ if (current_ >= end_) {
+ return kSentinel;
+ }
+
+ char32_t code_point = *current_;
+ if (IsHighSurrogate(code_point)) {
+ const wchar_t* next = current_ + 1;
+ if (next < end_ && IsLowSurrogate(*next)) {
+ code_point = SurrogatePair(code_point, *next).ToCodePoint();
+ }
+ }
+
+ return code_point;
+ }
+
+ const wchar_t* current_;
+ const wchar_t* end_;
+ char32_t code_point_;
+ };
+
+ explicit CodePointView(WideStringView backing)
+ : begin_(backing.begin()), end_(backing.end()) {
+ DCHECK_LE(begin_, end_);
+ }
+
+ Iterator begin() const { return Iterator(begin_, end_); }
+
+ Iterator end() const { return Iterator(end_, end_); }
+
+ private:
+ // Note that a `WideStringView` member would make the constructor too complex.
+ const wchar_t* begin_;
+ const wchar_t* end_;
+};
+#else
+using CodePointView = WideStringView;
+#endif // defined(WCHAR_T_IS_UTF16)
+
+} // namespace pdfium
+
+#endif // CORE_FXCRT_CODE_POINT_VIEW_H_
diff --git a/core/fxcrt/code_point_view_unittest.cpp b/core/fxcrt/code_point_view_unittest.cpp
new file mode 100644
index 000000000..2fb7bd4e7
--- /dev/null
+++ b/core/fxcrt/code_point_view_unittest.cpp
@@ -0,0 +1,55 @@
+// Copyright 2023 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/fxcrt/code_point_view.h"
+
+#include <string>
+
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+using ::pdfium::CodePointView;
+
+std::u32string Materialize(CodePointView view) {
+ std::u32string materialized;
+ for (char32_t code_point : view) {
+ materialized += code_point;
+ }
+ return materialized;
+}
+
+} // namespace
+
+TEST(CodePointViewTest, Empty) {
+ EXPECT_EQ(U"", Materialize(CodePointView(L"")));
+}
+
+TEST(CodePointViewTest, Basic) {
+ EXPECT_EQ(U"(\u0080\uffff)", Materialize(CodePointView(L"(\u0080\uffff)")));
+}
+
+TEST(CodePointViewTest, Supplementary) {
+ EXPECT_EQ(U"(🎨)", Materialize(CodePointView(L"(🎨)")));
+}
+
+TEST(CodePointViewTest, UnpairedHighSurrogate) {
+ EXPECT_EQ(U"\xd800", Materialize(CodePointView(L"\xd800")));
+}
+
+TEST(CodePointViewTest, UnpairedLowSurrogate) {
+ EXPECT_EQ(U"\xdc00", Materialize(CodePointView(L"\xdc00")));
+}
+
+#if defined(WCHAR_T_IS_UTF16)
+TEST(CodePointViewTest, SurrogateErrorRecovery) {
+ EXPECT_EQ(U"(\xd800)", Materialize(CodePointView(L"(\xd800)"))) << "High";
+ EXPECT_EQ(U"(\xdc00)", Materialize(CodePointView(L"(\xdc00)"))) << "Low";
+ EXPECT_EQ(U"(\xd800🎨)", Materialize(CodePointView(L"(\xd800\xd83c\xdfa8)")))
+ << "High-high";
+ EXPECT_EQ(U"(🎨\xdc00)", Materialize(CodePointView(L"(\xd83c\xdfa8\xdc00)")))
+ << "Low-low";
+}
+#endif // defined(WCHAR_T_IS_UTF16)
diff --git a/core/fxcrt/css/cfx_cssdata.cpp b/core/fxcrt/css/cfx_cssdata.cpp
index 15cd8eafb..0659a598f 100644
--- a/core/fxcrt/css/cfx_cssdata.cpp
+++ b/core/fxcrt/css/cfx_cssdata.cpp
@@ -18,19 +18,19 @@ namespace {
#undef CSS_PROP____
#define CSS_PROP____(a, b, c, d) {CFX_CSSProperty::a, c, d},
-const CFX_CSSData::Property propertyTable[] = {
+const CFX_CSSData::Property kPropertyTable[] = {
#include "core/fxcrt/css/properties.inc"
};
#undef CSS_PROP____
#undef CSS_PROP_VALUE____
#define CSS_PROP_VALUE____(a, b, c) {CFX_CSSPropertyValue::a, c},
-const CFX_CSSData::PropertyValue propertyValueTable[] = {
+const CFX_CSSData::PropertyValue kPropertyValueTable[] = {
#include "core/fxcrt/css/property_values.inc"
};
#undef CSS_PROP_VALUE____
-const CFX_CSSData::LengthUnit lengthUnitTable[] = {
+const CFX_CSSData::LengthUnit kLengthUnitTable[] = {
{L"cm", CFX_CSSNumberValue::Unit::kCentiMeters},
{L"em", CFX_CSSNumberValue::Unit::kEMS},
{L"ex", CFX_CSSNumberValue::Unit::kEXS},
@@ -42,7 +42,7 @@ const CFX_CSSData::LengthUnit lengthUnitTable[] = {
};
// 16 colours from CSS 2.0 + alternate spelling of grey/gray.
-const CFX_CSSData::Color colorTable[] = {
+const CFX_CSSData::Color kColorTable[] = {
{L"aqua", 0xff00ffff}, {L"black", 0xff000000}, {L"blue", 0xff0000ff},
{L"fuchsia", 0xffff00ff}, {L"gray", 0xff808080}, {L"green", 0xff008000},
{L"grey", 0xff808080}, {L"lime", 0xff00ff00}, {L"maroon", 0xff800000},
@@ -59,19 +59,21 @@ const CFX_CSSData::Property* CFX_CSSData::GetPropertyByName(
return nullptr;
uint32_t hash = FX_HashCode_GetLoweredW(name);
- auto* result =
- std::lower_bound(std::begin(propertyTable), std::end(propertyTable), hash,
- [](const CFX_CSSData::Property& iter,
- const uint32_t& hash) { return iter.dwHash < hash; });
+ auto* result = std::lower_bound(
+ std::begin(kPropertyTable), std::end(kPropertyTable), hash,
+ [](const CFX_CSSData::Property& iter, const uint32_t& hash) {
+ return iter.dwHash < hash;
+ });
- if (result != std::end(propertyTable) && result->dwHash == hash)
+ if (result != std::end(kPropertyTable) && result->dwHash == hash) {
return result;
+ }
return nullptr;
}
const CFX_CSSData::Property* CFX_CSSData::GetPropertyByEnum(
CFX_CSSProperty property) {
- return &propertyTable[static_cast<uint8_t>(property)];
+ return &kPropertyTable[static_cast<uint8_t>(property)];
}
const CFX_CSSData::PropertyValue* CFX_CSSData::GetPropertyValueByName(
@@ -81,13 +83,14 @@ const CFX_CSSData::PropertyValue* CFX_CSSData::GetPropertyValueByName(
uint32_t hash = FX_HashCode_GetLoweredW(wsName);
auto* result = std::lower_bound(
- std::begin(propertyValueTable), std::end(propertyValueTable), hash,
+ std::begin(kPropertyValueTable), std::end(kPropertyValueTable), hash,
[](const PropertyValue& iter, const uint32_t& hash) {
return iter.dwHash < hash;
});
- if (result != std::end(propertyValueTable) && result->dwHash == hash)
+ if (result != std::end(kPropertyValueTable) && result->dwHash == hash) {
return result;
+ }
return nullptr;
}
@@ -99,8 +102,8 @@ const CFX_CSSData::LengthUnit* CFX_CSSData::GetLengthUnitByName(
WideString lowerName = WideString(wsName);
lowerName.MakeLower();
- for (auto* iter = std::begin(lengthUnitTable);
- iter != std::end(lengthUnitTable); ++iter) {
+ for (auto* iter = std::begin(kLengthUnitTable);
+ iter != std::end(kLengthUnitTable); ++iter) {
if (lowerName == iter->value)
return iter;
}
@@ -115,7 +118,7 @@ const CFX_CSSData::Color* CFX_CSSData::GetColorByName(WideStringView wsName) {
WideString lowerName = WideString(wsName);
lowerName.MakeLower();
- for (auto* iter = std::begin(colorTable); iter != std::end(colorTable);
+ for (auto* iter = std::begin(kColorTable); iter != std::end(kColorTable);
++iter) {
if (lowerName == iter->name)
return iter;
diff --git a/core/fxcrt/css/cfx_cssrulecollection.cpp b/core/fxcrt/css/cfx_cssrulecollection.cpp
index 4abdba4cc..89b6852e1 100644
--- a/core/fxcrt/css/cfx_cssrulecollection.cpp
+++ b/core/fxcrt/css/cfx_cssrulecollection.cpp
@@ -44,3 +44,5 @@ void CFX_CSSRuleCollection::AddRule(CFX_CSSStyleRule* pStyleRule) {
CFX_CSSRuleCollection::Data::Data(CFX_CSSSelector* pSel,
CFX_CSSDeclaration* pDecl)
: pSelector(pSel), pDeclaration(pDecl) {}
+
+CFX_CSSRuleCollection::Data::~Data() = default;
diff --git a/core/fxcrt/css/cfx_cssrulecollection.h b/core/fxcrt/css/cfx_cssrulecollection.h
index b5f09aded..125fdd2cc 100644
--- a/core/fxcrt/css/cfx_cssrulecollection.h
+++ b/core/fxcrt/css/cfx_cssrulecollection.h
@@ -11,6 +11,7 @@
#include <memory>
#include <vector>
+#include "core/fxcrt/unowned_ptr.h"
#include "core/fxcrt/widestring.h"
class CFX_CSSDeclaration;
@@ -23,9 +24,10 @@ class CFX_CSSRuleCollection {
class Data {
public:
Data(CFX_CSSSelector* pSel, CFX_CSSDeclaration* pDecl);
+ ~Data();
- CFX_CSSSelector* const pSelector;
- CFX_CSSDeclaration* const pDeclaration;
+ UnownedPtr<CFX_CSSSelector> const pSelector;
+ UnownedPtr<CFX_CSSDeclaration> const pDeclaration;
};
CFX_CSSRuleCollection();
diff --git a/core/fxcrt/css/cfx_csssyntaxparser.cpp b/core/fxcrt/css/cfx_csssyntaxparser.cpp
index 9341798d8..e5a4d412a 100644
--- a/core/fxcrt/css/cfx_csssyntaxparser.cpp
+++ b/core/fxcrt/css/cfx_csssyntaxparser.cpp
@@ -10,7 +10,6 @@
#include "core/fxcrt/css/cfx_cssdeclaration.h"
#include "core/fxcrt/fx_codepage.h"
#include "core/fxcrt/fx_extension.h"
-#include "third_party/base/notreached.h"
namespace {
@@ -149,9 +148,6 @@ CFX_CSSSyntaxParser::Status CFX_CSSSyntaxParser::DoSyntaxParse() {
}
m_Input.MoveNext();
break;
- default:
- NOTREACHED();
- break;
}
}
if (m_eMode == Mode::kPropertyValue && !m_Output.IsEmpty())
diff --git a/core/fxcrt/fixed_size_data_vector.h b/core/fxcrt/fixed_size_data_vector.h
index c0adc8ce6..bec5e1064 100644
--- a/core/fxcrt/fixed_size_data_vector.h
+++ b/core/fxcrt/fixed_size_data_vector.h
@@ -11,7 +11,7 @@
#include <utility>
#include "core/fxcrt/fx_memory_wrappers.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace fxcrt {
diff --git a/core/fxcrt/fixed_try_alloc_zeroed_data_vector_unittest.cpp b/core/fxcrt/fixed_try_alloc_zeroed_data_vector_unittest.cpp
index e80ba2717..613d838ab 100644
--- a/core/fxcrt/fixed_try_alloc_zeroed_data_vector_unittest.cpp
+++ b/core/fxcrt/fixed_try_alloc_zeroed_data_vector_unittest.cpp
@@ -12,7 +12,7 @@
#include "core/fxcrt/span_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
TEST(FixedTryAllocZeroedDataVector, NoData) {
FixedTryAllocZeroedDataVector<int> vec;
diff --git a/core/fxcrt/fixed_uninit_data_vector_unittest.cpp b/core/fxcrt/fixed_uninit_data_vector_unittest.cpp
index d7a63da68..70eda6aef 100644
--- a/core/fxcrt/fixed_uninit_data_vector_unittest.cpp
+++ b/core/fxcrt/fixed_uninit_data_vector_unittest.cpp
@@ -11,7 +11,7 @@
#include "core/fxcrt/span_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
TEST(FixedUninitDataVector, NoData) {
FixedUninitDataVector<int> vec;
diff --git a/core/fxcrt/fixed_zeroed_data_vector_unittest.cpp b/core/fxcrt/fixed_zeroed_data_vector_unittest.cpp
index ac024bb31..297818f65 100644
--- a/core/fxcrt/fixed_zeroed_data_vector_unittest.cpp
+++ b/core/fxcrt/fixed_zeroed_data_vector_unittest.cpp
@@ -11,7 +11,7 @@
#include "core/fxcrt/span_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
TEST(FixedZeroedDataVector, NoData) {
FixedZeroedDataVector<int> vec;
diff --git a/core/fxcrt/fx_codepage.h b/core/fxcrt/fx_codepage.h
index 94e764eac..2aa77411a 100644
--- a/core/fxcrt/fx_codepage.h
+++ b/core/fxcrt/fx_codepage.h
@@ -12,7 +12,8 @@
// Prove consistency with incomplete forward definitions.
#include "core/fxcrt/fx_codepage_forward.h"
#include "core/fxcrt/fx_string.h"
-#include "third_party/base/span.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
+#include "third_party/base/containers/span.h"
enum class FX_CodePage : uint16_t {
kDefANSI = 0,
@@ -103,7 +104,7 @@ enum class FX_Charset : uint8_t {
// Hi-bytes to unicode codepoint mapping for various code pages.
struct FX_CharsetUnicodes {
FX_Charset m_Charset;
- const uint16_t* m_pUnicodes; // Raw, POD struct.
+ UNOWNED_PTR_EXCLUSION const uint16_t* m_pUnicodes; // POD struct.
};
extern const FX_CharsetUnicodes kFX_CharsetUnicodes[8];
diff --git a/core/fxcrt/fx_coordinates.h b/core/fxcrt/fx_coordinates.h
index abc87ffff..f6b234721 100644
--- a/core/fxcrt/fx_coordinates.h
+++ b/core/fxcrt/fx_coordinates.h
@@ -13,22 +13,17 @@
#include <iosfwd>
#endif
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
template <class BaseType>
class CFX_PTemplate {
public:
- 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) {}
-
- CFX_PTemplate& operator=(const CFX_PTemplate& other) {
- if (this != &other) {
- x = other.x;
- y = other.y;
- }
- return *this;
- }
+ constexpr CFX_PTemplate() = default;
+ constexpr CFX_PTemplate(BaseType new_x, BaseType new_y)
+ : x(new_x), y(new_y) {}
+ CFX_PTemplate(const CFX_PTemplate& other) = default;
+ CFX_PTemplate& operator=(const CFX_PTemplate& other) = default;
+
bool operator==(const CFX_PTemplate& other) const {
return x == other.x && y == other.y;
}
@@ -52,8 +47,8 @@ class CFX_PTemplate {
return CFX_PTemplate(x - other.x, y - other.y);
}
- BaseType x;
- BaseType y;
+ BaseType x = 0;
+ BaseType y = 0;
};
using CFX_Point16 = CFX_PTemplate<int16_t>;
using CFX_Point = CFX_PTemplate<int32_t>;
@@ -62,13 +57,11 @@ using CFX_PointF = CFX_PTemplate<float>;
template <class BaseType>
class CFX_STemplate {
public:
- CFX_STemplate() : width(0), height(0) {}
-
- CFX_STemplate(BaseType new_width, BaseType new_height)
+ constexpr CFX_STemplate() = default;
+ constexpr CFX_STemplate(BaseType new_width, BaseType new_height)
: width(new_width), height(new_height) {}
-
- CFX_STemplate(const CFX_STemplate& other)
- : width(other.width), height(other.height) {}
+ CFX_STemplate(const CFX_STemplate& other) = default;
+ CFX_STemplate& operator=(const CFX_STemplate& other) = default;
template <typename OtherType>
CFX_STemplate<OtherType> As() const {
@@ -80,13 +73,6 @@ class CFX_STemplate {
width = 0;
height = 0;
}
- CFX_STemplate& operator=(const CFX_STemplate& other) {
- if (this != &other) {
- width = other.width;
- height = other.height;
- }
- return *this;
- }
bool operator==(const CFX_STemplate& other) const {
return width == other.width && height == other.height;
}
@@ -126,8 +112,8 @@ class CFX_STemplate {
return CFX_STemplate(width / divisor, height / divisor);
}
- BaseType width;
- BaseType height;
+ BaseType width = 0;
+ BaseType height = 0;
};
using CFX_Size = CFX_STemplate<int32_t>;
using CFX_SizeF = CFX_STemplate<float>;
@@ -160,8 +146,11 @@ using CFX_VectorF = CFX_VTemplate<float>;
// LTRB rectangles (y-axis runs downwards).
// Struct layout is compatible with win32 RECT.
struct FX_RECT {
- FX_RECT() = default;
- FX_RECT(int l, int t, int r, int b) : left(l), top(t), right(r), bottom(b) {}
+ constexpr FX_RECT() = default;
+ constexpr FX_RECT(int l, int t, int r, int b)
+ : left(l), top(t), right(r), bottom(b) {}
+ FX_RECT(const FX_RECT& that) = default;
+ FX_RECT& operator=(const FX_RECT& that) = default;
int Width() const { return right - left; }
int Height() const { return bottom - top; }
@@ -202,6 +191,8 @@ class CFX_FloatRect {
constexpr CFX_FloatRect() = default;
constexpr CFX_FloatRect(float l, float b, float r, float t)
: left(l), bottom(b), right(r), top(t) {}
+ CFX_FloatRect(const CFX_FloatRect& that) = default;
+ CFX_FloatRect& operator=(const CFX_FloatRect& that) = default;
explicit CFX_FloatRect(const FX_RECT& rect);
explicit CFX_FloatRect(const CFX_PointF& point);
@@ -295,9 +286,15 @@ class CFX_RectF {
using PointType = CFX_PointF;
using SizeType = CFX_SizeF;
- CFX_RectF() = default;
- CFX_RectF(float dst_left, float dst_top, float dst_width, float dst_height)
+ constexpr CFX_RectF() = default;
+ constexpr CFX_RectF(float dst_left,
+ float dst_top,
+ float dst_width,
+ float dst_height)
: left(dst_left), top(dst_top), width(dst_width), height(dst_height) {}
+ CFX_RectF(const CFX_RectF& other) = default;
+ CFX_RectF& operator=(const CFX_RectF& other) = default;
+
CFX_RectF(float dst_left, float dst_top, const SizeType& dst_size)
: left(dst_left),
top(dst_top),
@@ -313,11 +310,6 @@ class CFX_RectF {
width(static_cast<float>(that.Width())),
height(static_cast<float>(that.Height())) {}
- // NOLINTNEXTLINE(runtime/explicit)
- CFX_RectF(const CFX_RectF& other) = default;
-
- CFX_RectF& operator=(const CFX_RectF& other) = default;
-
CFX_RectF& operator+=(const PointType& p) {
left += p.x;
top += p.y;
diff --git a/core/fxcrt/fx_extension.cpp b/core/fxcrt/fx_extension.cpp
index c6822594d..dc312f0c0 100644
--- a/core/fxcrt/fx_extension.cpp
+++ b/core/fxcrt/fx_extension.cpp
@@ -10,6 +10,7 @@
#include <limits>
#include "core/fxcrt/fx_system.h"
+#include "core/fxcrt/utf16.h"
#include "third_party/base/check.h"
namespace {
@@ -150,16 +151,17 @@ void FXSYS_IntToFourHexChars(uint16_t n, char* buf) {
}
size_t FXSYS_ToUTF16BE(uint32_t unicode, char* buf) {
- DCHECK(unicode <= 0xD7FF || (unicode > 0xDFFF && unicode <= 0x10FFFF));
+ DCHECK(unicode <= pdfium::kMaximumSupplementaryCodePoint);
+ DCHECK(!pdfium::IsHighSurrogate(unicode));
+ DCHECK(!pdfium::IsLowSurrogate(unicode));
+
if (unicode <= 0xFFFF) {
FXSYS_IntToFourHexChars(unicode, buf);
return 4;
}
- 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);
+ pdfium::SurrogatePair surrogate_pair(unicode);
+ FXSYS_IntToFourHexChars(surrogate_pair.high(), buf);
+ FXSYS_IntToFourHexChars(surrogate_pair.low(), buf + 4);
return 8;
}
diff --git a/core/fxcrt/fx_folder_posix.cpp b/core/fxcrt/fx_folder_posix.cpp
index b4cf9f9ec..fb873be78 100644
--- a/core/fxcrt/fx_folder_posix.cpp
+++ b/core/fxcrt/fx_folder_posix.cpp
@@ -10,7 +10,7 @@
#include "build/build_config.h"
#include "core/fxcrt/unowned_ptr.h"
-#include "third_party/base/ptr_util.h"
+#include "third_party/base/memory/ptr_util.h"
#if BUILDFLAG(IS_WIN)
#error "built on wrong platform"
diff --git a/core/fxcrt/fx_folder_windows.cpp b/core/fxcrt/fx_folder_windows.cpp
index 500c73354..6b19dde83 100644
--- a/core/fxcrt/fx_folder_windows.cpp
+++ b/core/fxcrt/fx_folder_windows.cpp
@@ -9,7 +9,7 @@
#include <memory>
#include "build/build_config.h"
-#include "third_party/base/ptr_util.h"
+#include "third_party/base/memory/ptr_util.h"
#if !BUILDFLAG(IS_WIN)
#error "built on wrong platform"
diff --git a/core/fxcrt/fx_memcpy_wrappers.h b/core/fxcrt/fx_memcpy_wrappers.h
new file mode 100644
index 000000000..2dc8c1c8f
--- /dev/null
+++ b/core/fxcrt/fx_memcpy_wrappers.h
@@ -0,0 +1,86 @@
+// Copyright 2023 The PDFium Authors
+// Use of this source code is governed by 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_MEMCPY_WRAPPERS_H_
+#define CORE_FXCRT_FX_MEMCPY_WRAPPERS_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <wchar.h>
+
+// Wrappers to avoid the zero-length w/NULL arg gotchas in C spec. Use these
+// if there is a possibility of a NULL arg (or a bad arg) that is to be ignored
+// when the length is zero, otherwise just call the C Run Time Library function
+// itself.
+inline int FXSYS_memcmp(const void* ptr1, const void* ptr2, size_t len) {
+ return len ? memcmp(ptr1, ptr2, len) : 0;
+}
+
+inline int FXSYS_wmemcmp(const wchar_t* ptr1, const wchar_t* ptr2, size_t len) {
+ return len ? wmemcmp(ptr1, ptr2, len) : 0;
+}
+
+inline void* FXSYS_memcpy(void* ptr1, const void* ptr2, size_t len) {
+ return len ? memcpy(ptr1, ptr2, len) : ptr1;
+}
+
+inline wchar_t* FXSYS_wmemcpy(wchar_t* ptr1, const wchar_t* ptr2, size_t len) {
+ return len ? wmemcpy(ptr1, ptr2, len) : ptr1;
+}
+
+inline void* FXSYS_memmove(void* ptr1, const void* ptr2, size_t len) {
+ return len ? memmove(ptr1, ptr2, len) : ptr1;
+}
+
+inline wchar_t* FXSYS_wmemmove(wchar_t* ptr1, const wchar_t* ptr2, size_t len) {
+ return len ? wmemmove(ptr1, ptr2, len) : ptr1;
+}
+
+inline void* FXSYS_memset(void* ptr1, int val, size_t len) {
+ return len ? memset(ptr1, val, len) : ptr1;
+}
+
+inline wchar_t* FXSYS_wmemset(wchar_t* ptr1, int val, size_t len) {
+ return len ? wmemset(ptr1, val, len) : ptr1;
+}
+
+inline const void* FXSYS_memchr(const void* ptr1, int val, size_t len) {
+ return len ? memchr(ptr1, val, len) : nullptr;
+}
+
+inline const wchar_t* FXSYS_wmemchr(const wchar_t* ptr1,
+ wchar_t val,
+ size_t len) {
+ return len ? wmemchr(ptr1, val, len) : nullptr;
+}
+
+// Overloaded functions for C++ templates
+inline size_t FXSYS_len(const char* ptr) {
+ return strlen(ptr);
+}
+
+inline size_t FXSYS_len(const wchar_t* ptr) {
+ return wcslen(ptr);
+}
+
+inline int FXSYS_cmp(const char* ptr1, const char* ptr2, size_t len) {
+ return FXSYS_memcmp(ptr1, ptr2, len);
+}
+
+inline int FXSYS_cmp(const wchar_t* ptr1, const wchar_t* ptr2, size_t len) {
+ return FXSYS_wmemcmp(ptr1, ptr2, len);
+}
+
+inline const char* FXSYS_chr(const char* ptr, char ch, size_t len) {
+ return reinterpret_cast<const char*>(FXSYS_memchr(ptr, ch, len));
+}
+
+inline const wchar_t* FXSYS_chr(const wchar_t* ptr, wchar_t ch, size_t len) {
+ return FXSYS_wmemchr(ptr, ch, len);
+}
+
+#endif // CORE_FXCRT_FX_MEMCPY_WRAPPERS_H_
diff --git a/core/fxcrt/fx_memcpy_wrappers_unittest.cpp b/core/fxcrt/fx_memcpy_wrappers_unittest.cpp
new file mode 100644
index 000000000..9d2905028
--- /dev/null
+++ b/core/fxcrt/fx_memcpy_wrappers_unittest.cpp
@@ -0,0 +1,57 @@
+// Copyright 2023 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/fxcrt/fx_memcpy_wrappers.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(fxcrt, FXSYS_memset) {
+ // Test passes if it does not trigger UBSAN warnings.
+ EXPECT_EQ(nullptr, FXSYS_memset(nullptr, 0, 0));
+}
+
+TEST(fxcrt, FXSYS_wmemset) {
+ // Test passes if it does not trigger UBSAN warnings.
+ EXPECT_EQ(nullptr, FXSYS_wmemset(nullptr, 0, 0));
+}
+
+TEST(fxcrt, FXSYS_memcpy) {
+ // Test passes if it does not trigger UBSAN warnings.
+ EXPECT_EQ(nullptr, FXSYS_memcpy(nullptr, nullptr, 0));
+}
+
+TEST(fxcrt, FXSYS_wmemcpy) {
+ // Test passes if it does not trigger UBSAN warnings.
+ EXPECT_EQ(nullptr, FXSYS_wmemcpy(nullptr, nullptr, 0));
+}
+
+TEST(fxcrt, FXSYS_memmove) {
+ // Test passes if it does not trigger UBSAN warnings.
+ EXPECT_EQ(nullptr, FXSYS_memmove(nullptr, nullptr, 0));
+}
+
+TEST(fxcrt, FXSYS_wmemmove) {
+ // Test passes if it does not trigger UBSAN warnings.
+ EXPECT_EQ(nullptr, FXSYS_wmemmove(nullptr, nullptr, 0));
+}
+
+TEST(fxcrt, FXSYS_memcmp) {
+ // Test passes if it does not trigger UBSAN warnings.
+ EXPECT_EQ(0, FXSYS_memcmp(nullptr, nullptr, 0));
+}
+
+TEST(fxcrt, FXSYS_wmemcmp) {
+ // Test passes if it does not trigger UBSAN warnings.
+ EXPECT_EQ(0, FXSYS_wmemcmp(nullptr, nullptr, 0));
+}
+
+TEST(fxcrt, FXSYS_memchr) {
+ // Test passes if it does not trigger UBSAN warnings.
+ EXPECT_EQ(nullptr, FXSYS_memchr(nullptr, 0, 0));
+}
+
+TEST(fxcrt, FXSYS_wmemchr) {
+ // Test passes if it does not trigger UBSAN warnings.
+ EXPECT_EQ(nullptr, FXSYS_wmemchr(nullptr, 0, 0));
+}
diff --git a/core/fxcrt/fx_memory.h b/core/fxcrt/fx_memory.h
index 2ae5003d2..ac61146df 100644
--- a/core/fxcrt/fx_memory.h
+++ b/core/fxcrt/fx_memory.h
@@ -50,14 +50,17 @@ NOINLINE void FX_OutOfMemoryTerminate(size_t size);
#define FX_AllocUninit2D(type, w, h) \
static_cast<type*>(pdfium::internal::AllocOrDie2D(w, h, sizeof(type)))
+// FX_Free frees memory from the above.
+#define FX_Free(ptr) pdfium::internal::Dealloc(ptr)
+
// String Partition Allocators.
// This never returns nullptr, but returns uninitialized memory.
#define FX_StringAlloc(type, size) \
static_cast<type*>(pdfium::internal::StringAllocOrDie(size, sizeof(type)))
-// FX_Free accepts memory from all of the above.
-void FX_Free(void* ptr);
+// FX_StringFree frees memory from FX_StringAlloc.
+#define FX_StringFree(ptr) pdfium::internal::StringDealloc(ptr)
#ifndef V8_ENABLE_SANDBOX
// V8 Array Buffer Partition Allocators.
@@ -84,10 +87,12 @@ void* Realloc(void* ptr, size_t num_members, size_t member_size);
void* CallocOrDie(size_t num_members, size_t member_size);
void* CallocOrDie2D(size_t w, size_t h, size_t member_size);
void* ReallocOrDie(void* ptr, size_t num_members, size_t member_size);
+void Dealloc(void* ptr);
// String partition.
void* StringAlloc(size_t num_members, size_t member_size);
void* StringAllocOrDie(size_t num_members, size_t member_size);
+void StringDealloc(void* ptr);
} // namespace internal
} // namespace pdfium
diff --git a/core/fxcrt/fx_memory_malloc.cpp b/core/fxcrt/fx_memory_malloc.cpp
index 44a05c6d0..e199d4224 100644
--- a/core/fxcrt/fx_memory_malloc.cpp
+++ b/core/fxcrt/fx_memory_malloc.cpp
@@ -47,6 +47,10 @@ void* Realloc(void* ptr, size_t num_members, size_t member_size) {
return realloc(ptr, total.ValueOrDie());
}
+void Dealloc(void* ptr) {
+ free(ptr);
+}
+
void* StringAlloc(size_t num_members, size_t member_size) {
FX_SAFE_SIZE_T total = member_size;
total *= num_members;
@@ -55,6 +59,10 @@ void* StringAlloc(size_t num_members, size_t member_size) {
return malloc(total.ValueOrDie());
}
+void StringDealloc(void* ptr) {
+ free(ptr);
+}
+
} // namespace internal
} // namespace pdfium
@@ -77,7 +85,3 @@ void* FX_ArrayBufferAllocateUninitialized(size_t length) {
void FX_ArrayBufferFree(void* data) {
free(data);
}
-
-void FX_Free(void* ptr) {
- free(ptr);
-}
diff --git a/core/fxcrt/fx_memory_pa.cpp b/core/fxcrt/fx_memory_pa.cpp
index 35c043a02..789f68c9e 100644
--- a/core/fxcrt/fx_memory_pa.cpp
+++ b/core/fxcrt/fx_memory_pa.cpp
@@ -16,33 +16,25 @@
namespace {
-constexpr partition_alloc::PartitionOptions kOptions = {
- partition_alloc::PartitionOptions::AlignedAlloc::kDisallowed,
- partition_alloc::PartitionOptions::ThreadCache::kDisabled,
- partition_alloc::PartitionOptions::Quarantine::kDisallowed,
- partition_alloc::PartitionOptions::Cookie::kAllowed,
- partition_alloc::PartitionOptions::BackupRefPtr::kDisabled,
- partition_alloc::PartitionOptions::BackupRefPtrZapping::kDisabled,
- partition_alloc::PartitionOptions::UseConfigurablePool::kNo,
-};
+constexpr partition_alloc::PartitionOptions kOptions = {};
#ifndef V8_ENABLE_SANDBOX
partition_alloc::PartitionAllocator& GetArrayBufferPartitionAllocator() {
static pdfium::base::NoDestructor<partition_alloc::PartitionAllocator>
- s_array_buffer_allocator;
+ s_array_buffer_allocator(kOptions);
return *s_array_buffer_allocator;
}
#endif // V8_ENABLE_SANDBOX
partition_alloc::PartitionAllocator& GetGeneralPartitionAllocator() {
static pdfium::base::NoDestructor<partition_alloc::PartitionAllocator>
- s_general_allocator;
+ s_general_allocator(kOptions);
return *s_general_allocator;
}
partition_alloc::PartitionAllocator& GetStringPartitionAllocator() {
static pdfium::base::NoDestructor<partition_alloc::PartitionAllocator>
- s_string_allocator;
+ s_string_allocator(kOptions);
return *s_string_allocator;
}
@@ -85,6 +77,20 @@ void* Realloc(void* ptr, size_t num_members, size_t member_size) {
"GeneralPartition");
}
+void Dealloc(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) {
+ GetGeneralPartitionAllocator().root()->Free(ptr);
+ }
+}
+
void* StringAlloc(size_t num_members, size_t member_size) {
FX_SAFE_SIZE_T total = member_size;
total *= num_members;
@@ -96,6 +102,20 @@ void* StringAlloc(size_t num_members, size_t member_size) {
"StringPartition");
}
+void StringDealloc(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) {
+ GetStringPartitionAllocator().root()->Free(ptr);
+ }
+}
+
} // namespace internal
} // namespace pdfium
@@ -103,11 +123,13 @@ void FX_InitializeMemoryAllocators() {
static bool s_partition_allocators_initialized = false;
if (!s_partition_allocators_initialized) {
partition_alloc::PartitionAllocGlobalInit(FX_OutOfMemoryTerminate);
+ // These calls force the allocators to be created and initialized (via magic
+ // of static local variables).
#ifndef V8_ENABLE_SANDBOX
- GetArrayBufferPartitionAllocator().init(kOptions);
+ GetArrayBufferPartitionAllocator();
#endif // V8_ENABLE_SANDBOX
- GetGeneralPartitionAllocator().init(kOptions);
- GetStringPartitionAllocator().init(kOptions);
+ GetGeneralPartitionAllocator();
+ GetStringPartitionAllocator();
s_partition_allocators_initialized = true;
}
}
@@ -127,16 +149,3 @@ void FX_ArrayBufferFree(void* data) {
GetArrayBufferPartitionAllocator().root()->Free(data);
}
#endif // V8_ENABLE_SANDBOX
-
-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)
- partition_alloc::ThreadSafePartitionRoot::Free(ptr);
-}
diff --git a/core/fxcrt/fx_memory_unittest.cpp b/core/fxcrt/fx_memory_unittest.cpp
index e0de4f4af..7d3fe4d35 100644
--- a/core/fxcrt/fx_memory_unittest.cpp
+++ b/core/fxcrt/fx_memory_unittest.cpp
@@ -5,10 +5,15 @@
#include "core/fxcrt/fx_memory.h"
#include <limits>
+#include <memory>
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(PDF_USE_PARTITION_ALLOC)
+#include "base/allocator/partition_allocator/partition_address_space.h"
+#endif
+
namespace {
constexpr size_t kMaxByteAlloc = std::numeric_limits<size_t>::max();
@@ -125,3 +130,39 @@ TEST(fxcrt, FXAlign) {
EXPECT_EQ(512, FxAlignToBoundary<512>(i512));
EXPECT_EQ(-512, FxAlignToBoundary<512>(ineg));
}
+
+#if defined(PDF_USE_PARTITION_ALLOC)
+#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && BUILDFLAG(HAS_64_BIT_POINTERS)
+TEST(FxMemory, NewOperatorResultIsPA) {
+ auto obj = std::make_unique<double>(4.0);
+ EXPECT_TRUE(partition_alloc::IsManagedByPartitionAlloc(
+ reinterpret_cast<uintptr_t>(obj.get())));
+#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+ EXPECT_TRUE(partition_alloc::IsManagedByPartitionAllocBRPPool(
+ reinterpret_cast<uintptr_t>(obj.get())));
+#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+}
+
+TEST(FxMemory, MallocResultIsPA) {
+ void* obj = malloc(16);
+ EXPECT_TRUE(partition_alloc::IsManagedByPartitionAlloc(
+ reinterpret_cast<uintptr_t>(obj)));
+#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+ EXPECT_TRUE(partition_alloc::IsManagedByPartitionAllocBRPPool(
+ reinterpret_cast<uintptr_t>(obj)));
+#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+ free(obj);
+}
+
+TEST(FxMemory, StackObjectIsNotPA) {
+ int x = 3;
+ EXPECT_FALSE(partition_alloc::IsManagedByPartitionAlloc(
+ reinterpret_cast<uintptr_t>(&x)));
+#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+ EXPECT_FALSE(partition_alloc::IsManagedByPartitionAllocBRPPool(
+ reinterpret_cast<uintptr_t>(&x)));
+#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+}
+#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) &&
+ // BUILDFLAG(HAS_64_BIT_POINTERS)
+#endif // defined(PDF_USE_PARTITION_ALLOC)
diff --git a/core/fxcrt/fx_memory_wrappers.h b/core/fxcrt/fx_memory_wrappers.h
index 9e8775411..f4f0b06ff 100644
--- a/core/fxcrt/fx_memory_wrappers.h
+++ b/core/fxcrt/fx_memory_wrappers.h
@@ -30,7 +30,7 @@ struct IsFXDataPartitionException : std::false_type {};
// Allocators for mapping STL containers onto Partition Alloc.
// Otherwise, replacing e.g. the FX_AllocUninit/FX_Free pairs with STL may
// undo some of the nice segregation that we get from PartitionAlloc.
-template <class T, void* F(size_t, size_t)>
+template <class T, void* Alloc(size_t, size_t), void Free(void*)>
struct FxPartitionAllocAllocator {
public:
#if !defined(COMPILER_MSVC) || defined(NDEBUG)
@@ -49,7 +49,7 @@ struct FxPartitionAllocAllocator {
template <class U>
struct rebind {
- using other = FxPartitionAllocAllocator<U, F>;
+ using other = FxPartitionAllocAllocator<U, Alloc, Free>;
};
FxPartitionAllocAllocator() noexcept = default;
@@ -59,14 +59,14 @@ struct FxPartitionAllocAllocator {
template <typename U>
FxPartitionAllocAllocator(
- const FxPartitionAllocAllocator<U, F>& other) noexcept {}
+ const FxPartitionAllocAllocator<U, Alloc, Free>& other) noexcept {}
pointer address(reference x) const noexcept { return &x; }
const_pointer address(const_reference x) const noexcept { return &x; }
pointer allocate(size_type n, const void* hint = 0) {
- return static_cast<pointer>(F(n, sizeof(value_type)));
+ return static_cast<pointer>(Alloc(n, sizeof(value_type)));
}
- void deallocate(pointer p, size_type n) { FX_Free(p); }
+ void deallocate(pointer p, size_type n) { Free(p); }
size_type max_size() const noexcept {
return std::numeric_limits<size_type>::max() / sizeof(value_type);
}
@@ -92,13 +92,16 @@ template <typename T,
typename = std::enable_if_t<std::is_arithmetic<T>::value ||
std::is_enum<T>::value ||
IsFXDataPartitionException<T>::value>>
-using FxAllocAllocator =
- FxPartitionAllocAllocator<T, pdfium::internal::AllocOrDie>;
+using FxAllocAllocator = FxPartitionAllocAllocator<T,
+ pdfium::internal::AllocOrDie,
+ pdfium::internal::Dealloc>;
// Used to put backing store for std::string<> and std::ostringstream<>
// into the string partition.
template <typename T>
using FxStringAllocator =
- FxPartitionAllocAllocator<T, pdfium::internal::StringAllocOrDie>;
+ FxPartitionAllocAllocator<T,
+ pdfium::internal::StringAllocOrDie,
+ pdfium::internal::StringDealloc>;
#endif // CORE_FXCRT_FX_MEMORY_WRAPPERS_H_
diff --git a/core/fxcrt/fx_number.cpp b/core/fxcrt/fx_number.cpp
index a0f38e6be..d577531f9 100644
--- a/core/fxcrt/fx_number.cpp
+++ b/core/fxcrt/fx_number.cpp
@@ -13,6 +13,7 @@
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/fx_string.h"
+#include "third_party/base/numerics/safe_conversions.h"
FX_Number::FX_Number()
: m_bIsInteger(true), m_bIsSigned(false), m_UnsignedValue(0) {}
@@ -88,7 +89,11 @@ FX_Number::FX_Number(ByteStringView strc)
}
int32_t FX_Number::GetSigned() const {
- return m_bIsInteger ? m_SignedValue : static_cast<int32_t>(m_FloatValue);
+ if (m_bIsInteger) {
+ return m_SignedValue;
+ }
+
+ return pdfium::base::saturated_cast<int32_t>(m_FloatValue);
}
float FX_Number::GetFloat() const {
diff --git a/core/fxcrt/fx_number_unittest.cpp b/core/fxcrt/fx_number_unittest.cpp
index deb4cf3c1..9a1d2eb4c 100644
--- a/core/fxcrt/fx_number_unittest.cpp
+++ b/core/fxcrt/fx_number_unittest.cpp
@@ -43,6 +43,18 @@ TEST(fxnumber, FromFloat) {
EXPECT_TRUE(number2.IsSigned());
EXPECT_EQ(-100, number2.GetSigned());
EXPECT_FLOAT_EQ(-100.001f, number2.GetFloat());
+
+ // Show positive saturation.
+ FX_Number number3(1e17f);
+ EXPECT_FALSE(number3.IsInteger());
+ EXPECT_TRUE(number3.IsSigned());
+ EXPECT_EQ(std::numeric_limits<int32_t>::max(), number3.GetSigned());
+
+ // Show negative saturation.
+ FX_Number number4(-1e17f);
+ EXPECT_FALSE(number4.IsInteger());
+ EXPECT_TRUE(number4.IsSigned());
+ EXPECT_EQ(std::numeric_limits<int32_t>::min(), number4.GetSigned());
}
TEST(fxnumber, FromStringUnsigned) {
diff --git a/core/fxcrt/fx_stream.h b/core/fxcrt/fx_stream.h
index e6f1f555f..15e02d5d4 100644
--- a/core/fxcrt/fx_stream.h
+++ b/core/fxcrt/fx_stream.h
@@ -13,7 +13,7 @@
#include "core/fxcrt/bytestring.h"
#include "core/fxcrt/fx_types.h"
#include "core/fxcrt/retain_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class IFX_WriteStream {
public:
diff --git a/core/fxcrt/fx_string.cpp b/core/fxcrt/fx_string.cpp
index 76773a81e..62109cd70 100644
--- a/core/fxcrt/fx_string.cpp
+++ b/core/fxcrt/fx_string.cpp
@@ -6,26 +6,125 @@
#include "core/fxcrt/fx_string.h"
+#include <stdint.h>
+
#include <iterator>
-#include "core/fxcrt/cfx_utf8decoder.h"
-#include "core/fxcrt/cfx_utf8encoder.h"
+#include "build/build_config.h"
+#include "core/fxcrt/bytestring.h"
+#include "core/fxcrt/code_point_view.h"
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/span_util.h"
+#include "core/fxcrt/string_view_template.h"
+#include "core/fxcrt/utf16.h"
+#include "core/fxcrt/widestring.h"
#include "third_party/base/compiler_specific.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
-ByteString FX_UTF8Encode(WideStringView wsStr) {
- CFX_UTF8Encoder encoder;
- for (size_t i = 0; i < wsStr.GetLength(); ++i)
- encoder.Input(wsStr[i]);
+namespace {
+
+// Appends a Unicode code point to a `ByteString` using UTF-8.
+//
+// TODO(crbug.com/pdfium/2041): Migrate to `ByteString`.
+void AppendCodePointToByteString(char32_t code_point, ByteString& buffer) {
+ if (code_point > pdfium::kMaximumSupplementaryCodePoint) {
+ // Invalid code point above U+10FFFF.
+ return;
+ }
+
+ if (code_point < 0x80) {
+ // 7-bit code points are unchanged in UTF-8.
+ buffer += code_point;
+ return;
+ }
- return ByteString(encoder.GetResult());
+ int byte_size;
+ if (code_point < 0x800) {
+ byte_size = 2;
+ } else if (code_point < 0x10000) {
+ byte_size = 3;
+ } else {
+ byte_size = 4;
+ }
+
+ static constexpr uint8_t kPrefix[] = {0xc0, 0xe0, 0xf0};
+ int order = 1 << ((byte_size - 1) * 6);
+ buffer += kPrefix[byte_size - 2] | (code_point / order);
+ for (int i = 0; i < byte_size - 1; i++) {
+ code_point = code_point % order;
+ order >>= 6;
+ buffer += 0x80 | (code_point / order);
+ }
+}
+
+// Appends a Unicode code point to a `WideString` using either UTF-16 or UTF-32,
+// depending on the platform's definition of `wchar_t`.
+//
+// TODO(crbug.com/pdfium/2031): Always use UTF-16.
+// TODO(crbug.com/pdfium/2041): Migrate to `WideString`.
+void AppendCodePointToWideString(char32_t code_point, WideString& buffer) {
+ if (code_point > pdfium::kMaximumSupplementaryCodePoint) {
+ // Invalid code point above U+10FFFF.
+ return;
+ }
+
+#if defined(WCHAR_T_IS_UTF16)
+ if (code_point < pdfium::kMinimumSupplementaryCodePoint) {
+ buffer += static_cast<wchar_t>(code_point);
+ } else {
+ // Encode as UTF-16 surrogate pair.
+ pdfium::SurrogatePair surrogate_pair(code_point);
+ buffer += surrogate_pair.high();
+ buffer += surrogate_pair.low();
+ }
+#else
+ buffer += static_cast<wchar_t>(code_point);
+#endif // defined(WCHAR_T_IS_UTF16)
+}
+
+} // namespace
+
+ByteString FX_UTF8Encode(WideStringView wsStr) {
+ ByteString buffer;
+ for (char32_t code_point : pdfium::CodePointView(wsStr)) {
+ AppendCodePointToByteString(code_point, buffer);
+ }
+ return buffer;
}
WideString FX_UTF8Decode(ByteStringView bsStr) {
- CFX_UTF8Decoder decoder(bsStr);
- return decoder.TakeResult();
+ WideString buffer;
+
+ int remaining = 0;
+ char32_t code_point = 0;
+ for (char byte : bsStr) {
+ uint8_t code_unit = static_cast<uint8_t>(byte);
+ if (code_unit < 0x80) {
+ remaining = 0;
+ AppendCodePointToWideString(code_unit, buffer);
+ } else if (code_unit < 0xc0) {
+ if (remaining > 0) {
+ --remaining;
+ code_point = (code_point << 6) | (code_unit & 0x3f);
+ if (remaining == 0) {
+ AppendCodePointToWideString(code_point, buffer);
+ }
+ }
+ } else if (code_unit < 0xe0) {
+ remaining = 1;
+ code_point = code_unit & 0x1f;
+ } else if (code_unit < 0xf0) {
+ remaining = 2;
+ code_point = code_unit & 0x0f;
+ } else if (code_unit < 0xf8) {
+ remaining = 3;
+ code_point = code_unit & 0x07;
+ } else {
+ remaining = 0;
+ }
+ }
+
+ return buffer;
}
namespace {
diff --git a/core/fxcrt/fx_string.h b/core/fxcrt/fx_string.h
index 41d73e462..49351c10f 100644
--- a/core/fxcrt/fx_string.h
+++ b/core/fxcrt/fx_string.h
@@ -13,7 +13,7 @@
#include "core/fxcrt/bytestring.h"
#include "core/fxcrt/widestring.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
constexpr uint32_t FXBSTR_ID(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4) {
return static_cast<uint32_t>(c1) << 24 | static_cast<uint32_t>(c2) << 16 |
diff --git a/core/fxcrt/fx_string_unittest.cpp b/core/fxcrt/fx_string_unittest.cpp
index 261986471..c671d2291 100644
--- a/core/fxcrt/fx_string_unittest.cpp
+++ b/core/fxcrt/fx_string_unittest.cpp
@@ -4,9 +4,11 @@
#include <limits>
+#include "build/build_config.h"
#include "core/fxcrt/fx_string.h"
+#include "core/fxcrt/utf16.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
char* TerminatedFloatToString(float value, pdfium::span<char> buf) {
size_t buflen = FloatToString(value, buf);
@@ -20,52 +22,135 @@ char* TerminatedDoubleToString(double value, pdfium::span<char> buf) {
return buf.data();
}
-TEST(fxstring, FX_UTF8Encode) {
+TEST(fxstring, FXUTF8Encode) {
EXPECT_EQ("", FX_UTF8Encode(WideStringView()));
EXPECT_EQ(
"x"
- "\xc2\x80"
- "\xc3\xbf"
- "\xef\xbc\xac"
+ "\u0080"
+ "\u00ff"
+ "\ud7ff"
+ "\ue000"
+ "\uff2c"
+ "\uffff"
"y",
FX_UTF8Encode(L"x"
L"\u0080"
L"\u00ff"
+ L"\ud7ff"
+ L"\ue000"
L"\uff2c"
+ L"\uffff"
L"y"));
}
-TEST(fxstring, FX_UTF8Decode) {
+TEST(fxstring, FXUTF8EncodeSupplementary) {
+ EXPECT_EQ(
+ "\U00010000"
+ "🎨"
+ "\U0010ffff",
+ FX_UTF8Encode(L"\U00010000"
+ L"\U0001f3a8"
+ L"\U0010ffff"));
+}
+
+#if defined(WCHAR_T_IS_UTF16)
+TEST(fxstring, FXUTF8EncodeSurrogateErrorRecovery) {
+ EXPECT_EQ("(\xed\xa0\x80)", FX_UTF8Encode(L"(\xd800)")) << "High";
+ EXPECT_EQ("(\xed\xb0\x80)", FX_UTF8Encode(L"(\xdc00)")) << "Low";
+ EXPECT_EQ("(\xed\xa0\x80🎨)", FX_UTF8Encode(L"(\xd800\xd83c\xdfa8)"))
+ << "High-high";
+ EXPECT_EQ("(🎨\xed\xb0\x80)", FX_UTF8Encode(L"(\xd83c\xdfa8\xdc00)"))
+ << "Low-low";
+}
+#endif // defined(WCHAR_T_IS_UTF16)
+
+TEST(fxstring, FXUTF8Decode) {
EXPECT_EQ(L"", FX_UTF8Decode(ByteStringView()));
EXPECT_EQ(
L"x"
L"\u0080"
L"\u00ff"
+ L"\ud7ff"
+ L"\ue000"
L"\uff2c"
+ L"\uffff"
L"y",
FX_UTF8Decode("x"
- "\xc2\x80"
- "\xc3\xbf"
- "\xef\xbc\xac"
+ "\u0080"
+ "\u00ff"
+ "\ud7ff"
+ "\ue000"
+ "\uff2c"
+ "\uffff"
"y"));
- EXPECT_EQ(L"a(A) b() c() d() e().",
- FX_UTF8Decode("a(\xc2\x41) " // Invalid continuation.
- "b(\xc2\xc2) " // Invalid continuation.
- "c(\xc2\xff\x80) " // Invalid continuation.
- "d(\x80\x80) " // Invalid leading.
- "e(\xff\x80\x80)" // Invalid leading.
- "."));
}
-TEST(fxstring, FX_UTF8EncodeDecodeConsistency) {
+TEST(fxstring, FXUTF8DecodeSupplementary) {
+ EXPECT_EQ(
+ L"\U00010000"
+ L"\U0001f3a8"
+ L"\U0010ffff",
+ FX_UTF8Decode("\U00010000"
+ "🎨"
+ "\U0010ffff"));
+}
+
+TEST(fxstring, FXUTF8DecodeErrorRecovery) {
+ EXPECT_EQ(L"(A)", FX_UTF8Decode("(\xc2\x41)")) << "Invalid continuation";
+ EXPECT_EQ(L"()", FX_UTF8Decode("(\xc2\xc2)")) << "Invalid continuation";
+ EXPECT_EQ(L"()", FX_UTF8Decode("(\xc2\xff\x80)")) << "Invalid continuation";
+ EXPECT_EQ(L"()", FX_UTF8Decode("(\x80\x80)")) << "Invalid leading";
+ EXPECT_EQ(L"()", FX_UTF8Decode("(\xff\x80\x80)")) << "Invalid leading";
+ EXPECT_EQ(L"()", FX_UTF8Decode("(\xf8\x80\x80\x80\x80)"))
+ << "Invalid leading";
+ EXPECT_EQ(L"()", FX_UTF8Decode("(\xf8\x88\x80\x80\x80)"))
+ << "Invalid leading";
+ EXPECT_EQ(L"()", FX_UTF8Decode("(\xf4\x90\x80\x80)"))
+ << "Code point greater than U+10FFFF";
+}
+
+TEST(fxstring, FXUTF8EncodeDecodeConsistency) {
WideString wstr;
wstr.Reserve(0x10000);
- for (int w = 0; w < 0x10000; ++w)
+ for (char32_t w = 0; w < pdfium::kMinimumSupplementaryCodePoint; ++w) {
+ if (pdfium::IsHighSurrogate(w) || pdfium::IsLowSurrogate(w)) {
+ // Skip UTF-16 surrogates.
+ continue;
+ }
wstr += static_cast<wchar_t>(w);
+ }
+ ASSERT_EQ(0xf800u, wstr.GetLength());
+
+ ByteString bstr = FX_UTF8Encode(wstr.AsStringView());
+ WideString wstr2 = FX_UTF8Decode(bstr.AsStringView());
+ EXPECT_EQ(wstr, wstr2);
+}
+
+TEST(fxstring, FXUTF8EncodeDecodeConsistencyUnpairedHighSurrogates) {
+ WideString wstr;
+ wstr.Reserve(0x400);
+ for (wchar_t w = pdfium::kMinimumHighSurrogateCodeUnit;
+ w <= pdfium::kMaximumHighSurrogateCodeUnit; ++w) {
+ wstr += w;
+ }
+ ASSERT_EQ(0x400u, wstr.GetLength());
+
+ ByteString bstr = FX_UTF8Encode(wstr.AsStringView());
+ WideString wstr2 = FX_UTF8Decode(bstr.AsStringView());
+ EXPECT_EQ(wstr, wstr2);
+}
+
+TEST(fxstring, FXUTF8EncodeDecodeConsistencyUnpairedLowSurrogates) {
+ WideString wstr;
+ wstr.Reserve(0x400);
+ for (wchar_t w = pdfium::kMinimumLowSurrogateCodeUnit;
+ w <= pdfium::kMaximumLowSurrogateCodeUnit; ++w) {
+ wstr += w;
+ }
+ ASSERT_EQ(0x400u, wstr.GetLength());
ByteString bstr = FX_UTF8Encode(wstr.AsStringView());
WideString wstr2 = FX_UTF8Decode(bstr.AsStringView());
- EXPECT_EQ(0x10000u, wstr2.GetLength());
EXPECT_EQ(wstr, wstr2);
}
diff --git a/core/fxcrt/fx_system.h b/core/fxcrt/fx_system.h
index 52f9ce54d..ca910f8f4 100644
--- a/core/fxcrt/fx_system.h
+++ b/core/fxcrt/fx_system.h
@@ -11,7 +11,6 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <wchar.h>
#include "build/build_config.h"
@@ -92,31 +91,6 @@ float FXSYS_sqrt2(float a, float b);
// C++-only section
-// Overloaded functions for C++ templates
-inline size_t FXSYS_len(const char* ptr) {
- return strlen(ptr);
-}
-
-inline size_t FXSYS_len(const wchar_t* ptr) {
- return wcslen(ptr);
-}
-
-inline int FXSYS_cmp(const char* ptr1, const char* ptr2, size_t len) {
- return memcmp(ptr1, ptr2, len);
-}
-
-inline int FXSYS_cmp(const wchar_t* ptr1, const wchar_t* ptr2, size_t len) {
- return wmemcmp(ptr1, ptr2, len);
-}
-
-inline const char* FXSYS_chr(const char* ptr, char ch, size_t len) {
- return reinterpret_cast<const char*>(memchr(ptr, ch, len));
-}
-
-inline const wchar_t* FXSYS_chr(const wchar_t* ptr, wchar_t ch, size_t len) {
- return wmemchr(ptr, ch, len);
-}
-
// Could be C, but uses C++-style casting.
#define FXSYS_UINT16_GET_LSBFIRST(p) \
(static_cast<uint16_t>( \
diff --git a/core/fxcrt/observed_ptr.h b/core/fxcrt/observed_ptr.h
index 7e55dc6d9..05b03d824 100644
--- a/core/fxcrt/observed_ptr.h
+++ b/core/fxcrt/observed_ptr.h
@@ -9,6 +9,7 @@
#include <set>
+#include "core/fxcrt/unowned_ptr_exclusion.h"
#include "third_party/base/check.h"
namespace fxcrt {
@@ -91,7 +92,7 @@ class ObservedPtr final : public Observable::ObserverIface {
T* operator->() const { return m_pObservable; }
private:
- T* m_pObservable = nullptr;
+ UNOWNED_PTR_EXCLUSION T* m_pObservable = nullptr;
};
template <typename T, typename U>
diff --git a/core/fxcrt/pdfium_span_unittest.cpp b/core/fxcrt/pdfium_span_unittest.cpp
index d0dfee200..e9da064de 100644
--- a/core/fxcrt/pdfium_span_unittest.cpp
+++ b/core/fxcrt/pdfium_span_unittest.cpp
@@ -5,7 +5,7 @@
#include <vector>
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
// Tests PDFium-modifications to base::span. The name of this file is
// chosen to avoid collisions with base's span_unittest.cc
diff --git a/core/fxcrt/scoped_set_insertion.h b/core/fxcrt/scoped_set_insertion.h
index 3a0ff0e6b..d93098221 100644
--- a/core/fxcrt/scoped_set_insertion.h
+++ b/core/fxcrt/scoped_set_insertion.h
@@ -9,6 +9,7 @@
#include <utility>
#include "core/fxcrt/fx_memory.h"
+#include "core/fxcrt/unowned_ptr.h"
#include "third_party/base/check.h"
namespace fxcrt {
@@ -29,7 +30,7 @@ class ScopedSetInsertion {
~ScopedSetInsertion() { set_->erase(insert_results_.first); }
private:
- std::set<T>* const set_;
+ UnownedPtr<std::set<T>> const set_;
const std::pair<typename std::set<T>::iterator, bool> insert_results_;
};
diff --git a/core/fxcrt/shared_copy_on_write_unittest.cpp b/core/fxcrt/shared_copy_on_write_unittest.cpp
index 979058b9e..2e8c9e88f 100644
--- a/core/fxcrt/shared_copy_on_write_unittest.cpp
+++ b/core/fxcrt/shared_copy_on_write_unittest.cpp
@@ -31,6 +31,11 @@ class Observer {
class Object final : public Retainable {
public:
+ CONSTRUCT_VIA_MAKE_RETAIN;
+
+ RetainPtr<Object> Clone() const { return pdfium::MakeRetain<Object>(*this); }
+
+ private:
Object(Observer* observer, const std::string& name)
: name_(name), observer_(observer) {
observer->OnConstruct(name_);
@@ -40,9 +45,6 @@ class Object final : public Retainable {
}
~Object() override { observer_->OnDestruct(name_); }
- RetainPtr<Object> Clone() const { return pdfium::MakeRetain<Object>(*this); }
-
- private:
std::string name_;
Observer* observer_;
};
diff --git a/core/fxcrt/span_util.h b/core/fxcrt/span_util.h
index c91161709..2a34980ca 100644
--- a/core/fxcrt/span_util.h
+++ b/core/fxcrt/span_util.h
@@ -5,10 +5,9 @@
#ifndef CORE_FXCRT_SPAN_UTIL_H_
#define CORE_FXCRT_SPAN_UTIL_H_
-#include <string.h>
-
+#include "core/fxcrt/fx_memcpy_wrappers.h"
#include "third_party/base/check_op.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace fxcrt {
@@ -18,7 +17,7 @@ template <typename T,
typename = pdfium::internal::EnableIfLegalSpanConversion<T, U>>
void spancpy(pdfium::span<T> dst, pdfium::span<U> src) {
CHECK_GE(dst.size_bytes(), src.size_bytes());
- memcpy(dst.data(), src.data(), src.size_bytes());
+ FXSYS_memcpy(dst.data(), src.data(), src.size_bytes());
}
// Bounds-checked moves from spans into spans.
@@ -27,19 +26,19 @@ template <typename T,
typename = pdfium::internal::EnableIfLegalSpanConversion<T, U>>
void spanmove(pdfium::span<T> dst, pdfium::span<U> src) {
CHECK_GE(dst.size_bytes(), src.size_bytes());
- memmove(dst.data(), src.data(), src.size_bytes());
+ FXSYS_memmove(dst.data(), src.data(), src.size_bytes());
}
// Bounds-checked sets into spans.
template <typename T>
void spanset(pdfium::span<T> dst, uint8_t val) {
- memset(dst.data(), val, dst.size_bytes());
+ FXSYS_memset(dst.data(), val, dst.size_bytes());
}
// Bounds-checked zeroing of spans.
template <typename T>
void spanclr(pdfium::span<T> dst) {
- memset(dst.data(), 0, dst.size_bytes());
+ FXSYS_memset(dst.data(), 0, dst.size_bytes());
}
} // namespace fxcrt
diff --git a/core/fxcrt/string_data_template.cpp b/core/fxcrt/string_data_template.cpp
index 6e750075b..a659cc2b8 100644
--- a/core/fxcrt/string_data_template.cpp
+++ b/core/fxcrt/string_data_template.cpp
@@ -10,6 +10,7 @@
#include <new>
+#include "core/fxcrt/fx_memcpy_wrappers.h"
#include "core/fxcrt/fx_memory.h"
#include "core/fxcrt/fx_safe_types.h"
#include "third_party/base/check.h"
@@ -21,7 +22,7 @@ namespace fxcrt {
template <typename CharType>
StringDataTemplate<CharType>* StringDataTemplate<CharType>::Create(
size_t nLen) {
- DCHECK_GT(nLen, 0);
+ DCHECK_GT(nLen, 0u);
// Calculate space needed for the fixed portion of the struct plus the
// NUL char that is not included in |m_nAllocLength|.
@@ -57,7 +58,7 @@ StringDataTemplate<CharType>* StringDataTemplate<CharType>::Create(
template <typename CharType>
void StringDataTemplate<CharType>::Release() {
if (--m_nRefs <= 0)
- FX_Free(this);
+ FX_StringFree(this);
}
template <typename CharType>
@@ -71,9 +72,9 @@ void StringDataTemplate<CharType>::CopyContents(
template <typename CharType>
void StringDataTemplate<CharType>::CopyContents(const CharType* pStr,
size_t nLen) {
- DCHECK_GE(nLen, 0);
+ DCHECK_GE(nLen, 0u);
DCHECK_LE(nLen, m_nAllocLength);
- memcpy(m_String, pStr, nLen * sizeof(CharType));
+ FXSYS_memcpy(m_String, pStr, nLen * sizeof(CharType));
m_String[nLen] = 0;
}
@@ -81,10 +82,10 @@ template <typename CharType>
void StringDataTemplate<CharType>::CopyContentsAt(size_t offset,
const CharType* pStr,
size_t nLen) {
- DCHECK_GE(offset, 0);
- DCHECK_GE(nLen, 0);
+ DCHECK_GE(offset, 0u);
+ DCHECK_GE(nLen, 0u);
DCHECK_LE(offset + nLen, m_nAllocLength);
- memcpy(m_String + offset, pStr, nLen * sizeof(CharType));
+ FXSYS_memcpy(m_String + offset, pStr, nLen * sizeof(CharType));
m_String[offset + nLen] = 0;
}
@@ -92,7 +93,7 @@ template <typename CharType>
StringDataTemplate<CharType>::StringDataTemplate(size_t dataLen,
size_t allocLen)
: m_nDataLength(dataLen), m_nAllocLength(allocLen) {
- DCHECK_GE(dataLen, 0);
+ DCHECK_GE(dataLen, 0u);
DCHECK_LE(dataLen, allocLen);
m_String[dataLen] = 0;
}
diff --git a/core/fxcrt/string_test_support.cpp b/core/fxcrt/string_test_support.cpp
new file mode 100644
index 000000000..cbb122053
--- /dev/null
+++ b/core/fxcrt/string_test_support.cpp
@@ -0,0 +1,20 @@
+// Copyright 2023 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <ostream>
+
+#include "core/fxcrt/bytestring.h"
+#include "core/fxcrt/widestring.h"
+
+namespace fxcrt {
+
+void PrintTo(const ByteString& str, std::ostream* os) {
+ *os << str;
+}
+
+void PrintTo(const WideString& str, std::ostream* os) {
+ *os << str;
+}
+
+} // namespace fxcrt
diff --git a/core/fxcrt/string_view_template.h b/core/fxcrt/string_view_template.h
index 67cd3fff4..475490f83 100644
--- a/core/fxcrt/string_view_template.h
+++ b/core/fxcrt/string_view_template.h
@@ -13,9 +13,10 @@
#include <iterator>
#include <type_traits>
+#include "core/fxcrt/fx_memcpy_wrappers.h"
#include "core/fxcrt/fx_system.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace fxcrt {
@@ -214,7 +215,7 @@ class StringViewTemplate {
if (!IsValidIndex(first + count - 1))
return StringViewTemplate();
- return StringViewTemplate(m_Span.data() + first, count);
+ return StringViewTemplate(m_Span.subspan(first, count));
}
StringViewTemplate First(size_t count) const {
diff --git a/core/fxcrt/tree_node.h b/core/fxcrt/tree_node.h
index d30b6a405..b86d793aa 100644
--- a/core/fxcrt/tree_node.h
+++ b/core/fxcrt/tree_node.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include "core/fxcrt/unowned_ptr_exclusion.h"
#include "third_party/base/check.h"
namespace fxcrt {
@@ -182,11 +183,11 @@ class TreeNode : public TreeNodeBase<T> {
private:
friend class TreeNodeBase<T>;
- T* m_pParent = nullptr; // Raw, intra-tree pointer.
- T* m_pFirstChild = nullptr; // Raw, intra-tree pointer.
- T* m_pLastChild = nullptr; // Raw, intra-tree pointer.
- T* m_pNextSibling = nullptr; // Raw, intra-tree pointer
- T* m_pPrevSibling = nullptr; // Raw, intra-tree pointer
+ UNOWNED_PTR_EXCLUSION T* m_pParent = nullptr; // intra-tree pointer.
+ UNOWNED_PTR_EXCLUSION T* m_pFirstChild = nullptr; // intra-tree pointer.
+ UNOWNED_PTR_EXCLUSION T* m_pLastChild = nullptr; // intra-tree pointer.
+ UNOWNED_PTR_EXCLUSION T* m_pNextSibling = nullptr; // intra-tree pointer.
+ UNOWNED_PTR_EXCLUSION T* m_pPrevSibling = nullptr; // intra-tree pointer.
};
} // namespace fxcrt
diff --git a/core/fxcrt/unowned_ptr.h b/core/fxcrt/unowned_ptr.h
index 1a2c9bb2b..fa78bebdf 100644
--- a/core/fxcrt/unowned_ptr.h
+++ b/core/fxcrt/unowned_ptr.h
@@ -5,25 +5,24 @@
#ifndef CORE_FXCRT_UNOWNED_PTR_H_
#define CORE_FXCRT_UNOWNED_PTR_H_
-#include <cstddef>
-#include <functional>
-#include <type_traits>
-#include <utility>
-
-#include "third_party/base/compiler_specific.h"
-
// UnownedPtr is a smart pointer class that behaves very much like a
-// standard C-style pointer. The advantages of using it over raw
+// standard C-style pointer. The advantages of using it over native T*
// 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.
+// explaining that is it // Not owned.
+//
+// 2. 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 using the memory tool ASAN, the class provides a destructor
+// 3. When built using the memory tool ASAN, the class provides a destructor
// which checks that the object being pointed to is still alive.
//
+// 4. When built against PartitionAlloc's BRP feature, it provides the same
+// UaF protections as base::raw_ptr<T>
+//
+// 5. It is initialized to nullptr by default.
+//
// 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
@@ -37,6 +36,42 @@
// other heap object. Use pdfium::span<> for the cases where indexing
// into an unowned array is desired, which performs the same checks.
+#include "build/build_config.h"
+
+#if defined(PDF_USE_PARTITION_ALLOC)
+#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
+
+// Can only use base::raw_ptr<> impls that force nullptr initialization.
+#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || BUILDFLAG(USE_ASAN_UNOWNED_PTR)
+#define UNOWNED_PTR_IS_BASE_RAW_PTR
+#endif
+
+#if BUILDFLAG(ENABLE_DANGLING_RAW_PTR_CHECKS) || BUILDFLAG(USE_ASAN_UNOWNED_PTR)
+#define UNOWNED_PTR_DANGLING_CHECKS
+#endif
+#endif // PDF_USE_PARTITION_ALLOC
+
+#if defined(UNOWNED_PTR_IS_BASE_RAW_PTR)
+#include "base/allocator/partition_allocator/pointers/raw_ptr.h"
+
+template <typename T>
+using UnownedPtr = raw_ptr<T>;
+
+#else // UNOWNED_PTR_IS_BASE_RAW_PTR
+
+#include <cstddef>
+#include <functional>
+#include <type_traits>
+#include <utility>
+
+#include "core/fxcrt/unowned_ptr_exclusion.h"
+#include "third_party/base/compiler_specific.h"
+
+#if defined(ADDRESS_SANITIZER)
+#include <cstdint>
+#define UNOWNED_PTR_DANGLING_CHECKS
+#endif
+
namespace pdfium {
template <typename T>
@@ -177,13 +212,15 @@ class TRIVIAL_ABI GSL_POINTER UnownedPtr {
#endif
}
- T* m_pObj = nullptr;
+ UNOWNED_PTR_EXCLUSION T* m_pObj = nullptr;
};
} // namespace fxcrt
using fxcrt::UnownedPtr;
+#endif // defined(UNOWNED_PTR_IS_BASE_RAW_PTR)
+
namespace pdfium {
// Type-deducing wrapper to make an UnownedPtr from an ordinary pointer,
diff --git a/core/fxcrt/unowned_ptr_exclusion.h b/core/fxcrt/unowned_ptr_exclusion.h
new file mode 100644
index 000000000..059496548
--- /dev/null
+++ b/core/fxcrt/unowned_ptr_exclusion.h
@@ -0,0 +1,17 @@
+// Copyright 2023 The PDFium Authors
+// 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_EXCLUSION_H_
+#define CORE_FXCRT_UNOWNED_PTR_EXCLUSION_H_
+
+#include "build/build_config.h"
+
+#if defined(PDF_ENABLE_UNOWNED_PTR_EXCLUSION)
+// TODO(tsepez): convert to PA copy of this code.
+#define UNOWNED_PTR_EXCLUSION __attribute__((annotate("raw_ptr_exclusion")))
+#else
+#define UNOWNED_PTR_EXCLUSION
+#endif
+
+#endif // CORE_FXCRT_UNOWNED_PTR_EXCLUSION_H_
diff --git a/core/fxcrt/unowned_ptr_unittest.cpp b/core/fxcrt/unowned_ptr_unittest.cpp
index f0c10ee3f..8c55108df 100644
--- a/core/fxcrt/unowned_ptr_unittest.cpp
+++ b/core/fxcrt/unowned_ptr_unittest.cpp
@@ -4,6 +4,7 @@
#include "core/fxcrt/unowned_ptr.h"
+#include <atomic>
#include <functional>
#include <memory>
#include <set>
@@ -12,6 +13,10 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/base/containers/contains.h"
+#if defined(PDF_USE_PARTITION_ALLOC)
+#include "base/allocator/partition_allocator/shim/allocator_shim_default_dispatch_to_partition_alloc.h"
+#endif
+
namespace fxcrt {
namespace {
@@ -162,7 +167,7 @@ TEST(UnownedPtr, PtrOk) {
}
TEST(UnownedPtr, PtrNotOk) {
-#if defined(ADDRESS_SANITIZER)
+#if defined(UNOWNED_PTR_DANGLING_CHECKS)
EXPECT_DEATH(DeleteDangling(), "");
#else
DeleteDangling();
@@ -179,7 +184,7 @@ TEST(UnownedPtr, AssignOk) {
}
TEST(UnownedPtr, AssignNotOk) {
-#if defined(ADDRESS_SANITIZER)
+#if defined(UNOWNED_PTR_DANGLING_CHECKS)
EXPECT_DEATH(AssignDangling(), "");
#else
AssignDangling();
@@ -196,7 +201,7 @@ TEST(UnownedPtr, ReleaseOk) {
}
TEST(UnownedPtr, ReleaseNotOk) {
-#if defined(ADDRESS_SANITIZER)
+#if defined(UNOWNED_PTR_DANGLING_CHECKS)
EXPECT_DEATH(ReleaseDangling(), "");
#else
ReleaseDangling();
@@ -259,4 +264,34 @@ TEST(UnownedPtr, TransparentCompare) {
EXPECT_FALSE(pdfium::Contains(holder, &foos[1]));
}
+#if defined(PDF_USE_PARTITION_ALLOC)
+#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \
+ BUILDFLAG(HAS_64_BIT_POINTERS) && BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+
+TEST(UnownedPtr, DanglingGetsQuarantined) {
+ partition_alloc::PartitionRoot* root =
+ allocator_shim::internal::PartitionAllocMalloc::Allocator();
+ size_t original_byte_count =
+ root->total_size_of_brp_quarantined_bytes.load(std::memory_order_relaxed);
+
+ auto ptr = std::make_unique<double>(4.0);
+ UnownedPtr<double> dangler = ptr.get();
+ EXPECT_EQ(
+ root->total_size_of_brp_quarantined_bytes.load(std::memory_order_relaxed),
+ original_byte_count);
+
+ ptr.reset();
+ EXPECT_GE(
+ root->total_size_of_brp_quarantined_bytes.load(std::memory_order_relaxed),
+ original_byte_count + sizeof(double));
+
+ dangler = nullptr;
+ EXPECT_EQ(
+ root->total_size_of_brp_quarantined_bytes.load(std::memory_order_relaxed),
+ original_byte_count);
+}
+
+#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) ...
+#endif // PDF_USE_PARTITION_ALLOC
+
} // namespace fxcrt
diff --git a/core/fxcrt/utf16.h b/core/fxcrt/utf16.h
new file mode 100644
index 000000000..f42f19098
--- /dev/null
+++ b/core/fxcrt/utf16.h
@@ -0,0 +1,107 @@
+// Copyright 2023 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CORE_FXCRT_UTF16_H_
+#define CORE_FXCRT_UTF16_H_
+
+#include "third_party/base/check.h"
+
+namespace pdfium {
+
+// The number of suffix bits in a UTF-16 surrogate.
+inline constexpr int kSurrogateBits = 10;
+
+// A bitmask for the suffix of a UTF-16 surrogate.
+inline constexpr char16_t kSurrogateMask = (1 << kSurrogateBits) - 1;
+
+// The first supplementary code point, `U+10000`.
+inline constexpr char32_t kMinimumSupplementaryCodePoint = 0x10000;
+
+// The last supplementary code point, `U+10FFFF`.
+inline constexpr char32_t kMaximumSupplementaryCodePoint =
+ kMinimumSupplementaryCodePoint +
+ (kSurrogateMask << kSurrogateBits | kSurrogateMask);
+
+// The first UTF-16 high surrogate code unit, `U+D800`.
+inline constexpr char16_t kMinimumHighSurrogateCodeUnit = 0xd800;
+
+// The last UTF-16 high surrogate code unit, `U+DBFF`.
+inline constexpr char16_t kMaximumHighSurrogateCodeUnit =
+ kMinimumHighSurrogateCodeUnit | kSurrogateMask;
+
+// The first UTF-16 low surrogate code unit, `U+DC00`.
+inline constexpr char16_t kMinimumLowSurrogateCodeUnit =
+ kMaximumHighSurrogateCodeUnit + 1;
+
+// The last UTF-16 low surrogate code unit, `U+DFFF`.
+inline constexpr char16_t kMaximumLowSurrogateCodeUnit =
+ kMinimumLowSurrogateCodeUnit | kSurrogateMask;
+
+// Returns `true` if `code_point` is in a supplementary plane, and therefore
+// requires encoding as a UTF-16 surrogate pair.
+constexpr bool IsSupplementary(char32_t code_point) {
+ return code_point >= kMinimumSupplementaryCodePoint &&
+ code_point <= kMaximumSupplementaryCodePoint;
+}
+
+// Returns `true` if `code_point` is a UTF-16 high surrogate.
+constexpr bool IsHighSurrogate(char32_t code_point) {
+ return code_point >= kMinimumHighSurrogateCodeUnit &&
+ code_point <= kMaximumHighSurrogateCodeUnit;
+}
+
+// Returns `true` if `code_point` is a UTF-16 low surrogate.
+constexpr bool IsLowSurrogate(char32_t code_point) {
+ return code_point >= kMinimumLowSurrogateCodeUnit &&
+ code_point <= kMaximumLowSurrogateCodeUnit;
+}
+
+// A UTF-16 surrogate pair.
+class SurrogatePair final {
+ public:
+ // Constructs a surrogate pair from a high and a low surrogate.
+ constexpr SurrogatePair(char16_t high, char16_t low)
+ : high_(high), low_(low) {
+ DCHECK(IsHighSurrogate(high_));
+ DCHECK(IsLowSurrogate(low_));
+ }
+
+ // Constructs a surrogate pair from a code point.
+ explicit constexpr SurrogatePair(char32_t code_point)
+ : high_(GetHighSurrogate(code_point)), low_(GetLowSurrogate(code_point)) {
+ // This constructor initializes `high_` and `low_` using helper functions
+ // because C++17 requires it for `constexpr` constructors.
+ DCHECK(IsSupplementary(code_point));
+ }
+
+ constexpr char16_t high() const { return high_; }
+ constexpr char16_t low() const { return low_; }
+
+ // Decodes this surrogate pair to a code point.
+ constexpr char32_t ToCodePoint() const {
+ char32_t code_point = low_ & kSurrogateMask;
+ code_point |= (high_ & kSurrogateMask) << kSurrogateBits;
+ return kMinimumSupplementaryCodePoint + code_point;
+ }
+
+ private:
+ static constexpr char16_t GetHighSurrogate(char32_t code_point) {
+ code_point -= kMinimumSupplementaryCodePoint;
+ char16_t code_unit = (code_point >> kSurrogateBits) & kSurrogateMask;
+ return kMinimumHighSurrogateCodeUnit | code_unit;
+ }
+
+ static constexpr char16_t GetLowSurrogate(char32_t code_point) {
+ code_point -= kMinimumSupplementaryCodePoint;
+ char16_t code_unit = code_point & kSurrogateMask;
+ return kMinimumLowSurrogateCodeUnit | code_unit;
+ }
+
+ char16_t high_;
+ char16_t low_;
+};
+
+} // namespace pdfium
+
+#endif // CORE_FXCRT_UTF16_H_
diff --git a/core/fxcrt/utf16_unittest.cpp b/core/fxcrt/utf16_unittest.cpp
new file mode 100644
index 000000000..bab1bdd73
--- /dev/null
+++ b/core/fxcrt/utf16_unittest.cpp
@@ -0,0 +1,61 @@
+// Copyright 2023 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/fxcrt/utf16.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace pdfium {
+
+static_assert(kSurrogateMask == 0x3ff);
+static_assert(kMaximumSupplementaryCodePoint == 0x10ffff);
+static_assert(kMaximumHighSurrogateCodeUnit == 0xdbff);
+static_assert(kMinimumLowSurrogateCodeUnit == 0xdc00);
+static_assert(kMaximumLowSurrogateCodeUnit == 0xdfff);
+
+static_assert(!IsSupplementary(0xffff));
+static_assert(IsSupplementary(0x10000));
+static_assert(IsSupplementary(0x10ffff));
+static_assert(!IsSupplementary(0x110000));
+
+static_assert(!IsHighSurrogate(0xd7ff));
+static_assert(IsHighSurrogate(0xd800));
+static_assert(IsHighSurrogate(0xdbff));
+static_assert(!IsHighSurrogate(0xdc00));
+
+static_assert(!IsLowSurrogate(0xdbff));
+static_assert(IsLowSurrogate(0xdc00));
+static_assert(IsLowSurrogate(0xdfff));
+static_assert(!IsLowSurrogate(0xe000));
+
+static_assert(SurrogatePair(0xd800, 0xdc00).high() == 0xd800);
+static_assert(SurrogatePair(0xd800, 0xdc00).low() == 0xdc00);
+static_assert(SurrogatePair(0xd800, 0xdc00).ToCodePoint() == 0x10000);
+
+static_assert(SurrogatePair(0xdbff, 0xdfff).high() == 0xdbff);
+static_assert(SurrogatePair(0xdbff, 0xdfff).low() == 0xdfff);
+static_assert(SurrogatePair(0xdbff, 0xdfff).ToCodePoint() == 0x10ffff);
+
+static_assert(SurrogatePair(0x10000).high() == 0xd800);
+static_assert(SurrogatePair(0x10000).low() == 0xdc00);
+static_assert(SurrogatePair(0x10000).ToCodePoint() == 0x10000);
+
+static_assert(SurrogatePair(0x10ffff).high() == 0xdbff);
+static_assert(SurrogatePair(0x10ffff).low() == 0xdfff);
+static_assert(SurrogatePair(0x10ffff).ToCodePoint() == 0x10ffff);
+
+TEST(SurrogatePairTest, RoundTrip) {
+ for (char32_t code_point = kMinimumSupplementaryCodePoint;
+ code_point <= kMaximumSupplementaryCodePoint; ++code_point) {
+ SurrogatePair from_code_point(code_point);
+ EXPECT_EQ(code_point, from_code_point.ToCodePoint());
+
+ SurrogatePair from_pair(from_code_point.high(), from_code_point.low());
+ EXPECT_EQ(from_code_point.high(), from_pair.high());
+ EXPECT_EQ(from_code_point.low(), from_pair.low());
+ EXPECT_EQ(code_point, from_pair.ToCodePoint());
+ }
+}
+
+} // namespace pdfium
diff --git a/core/fxcrt/widestring.cpp b/core/fxcrt/widestring.cpp
index f87447da3..241e544d5 100644
--- a/core/fxcrt/widestring.cpp
+++ b/core/fxcrt/widestring.cpp
@@ -14,12 +14,12 @@
#include "core/fxcrt/fx_codepage.h"
#include "core/fxcrt/fx_extension.h"
+#include "core/fxcrt/fx_memcpy_wrappers.h"
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/fx_system.h"
#include "core/fxcrt/string_pool_template.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
-#include "third_party/base/cxx17_backports.h"
#include "third_party/base/numerics/safe_math.h"
template class fxcrt::StringDataTemplate<wchar_t>;
@@ -465,7 +465,7 @@ bool WideString::operator==(const wchar_t* ptr) const {
return m_pData->m_nDataLength == 0;
return wcslen(ptr) == m_pData->m_nDataLength &&
- wmemcmp(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0;
+ FXSYS_wmemcmp(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0;
}
bool WideString::operator==(WideStringView str) const {
@@ -473,8 +473,8 @@ bool WideString::operator==(WideStringView str) const {
return str.IsEmpty();
return m_pData->m_nDataLength == str.GetLength() &&
- wmemcmp(m_pData->m_String, str.unterminated_c_str(),
- str.GetLength()) == 0;
+ FXSYS_wmemcmp(m_pData->m_String, str.unterminated_c_str(),
+ str.GetLength()) == 0;
}
bool WideString::operator==(const WideString& other) const {
@@ -504,8 +504,8 @@ bool WideString::operator<(WideStringView str) const {
size_t len = GetLength();
size_t other_len = str.GetLength();
- int result =
- wmemcmp(c_str(), str.unterminated_c_str(), std::min(len, other_len));
+ int result = FXSYS_wmemcmp(c_str(), str.unterminated_c_str(),
+ std::min(len, other_len));
return result < 0 || (result == 0 && len < other_len);
}
@@ -607,8 +607,9 @@ size_t WideString::Delete(size_t index, size_t count) {
return 0;
size_t old_length = m_pData->m_nDataLength;
- if (count == 0 || index != pdfium::clamp<size_t>(index, 0, old_length))
+ if (count == 0 || index != std::clamp<size_t>(index, 0, old_length)) {
return old_length;
+ }
size_t removal_length = index + count;
if (removal_length > old_length)
@@ -769,8 +770,8 @@ size_t WideString::Insert(size_t index, wchar_t ch) {
const size_t new_length = cur_length + 1;
ReallocBeforeWrite(new_length);
- wmemmove(m_pData->m_String + index + 1, m_pData->m_String + index,
- new_length - index);
+ FXSYS_wmemmove(m_pData->m_String + index + 1, m_pData->m_String + index,
+ new_length - index);
m_pData->m_String[index] = ch;
m_pData->m_nDataLength = new_length;
return new_length;
@@ -783,8 +784,8 @@ absl::optional<size_t> WideString::Find(wchar_t ch, size_t start) const {
if (!IsValidIndex(start))
return absl::nullopt;
- const wchar_t* pStr =
- wmemchr(m_pData->m_String + start, ch, m_pData->m_nDataLength - start);
+ const wchar_t* pStr = FXSYS_wmemchr(m_pData->m_String + start, ch,
+ m_pData->m_nDataLength - start);
return pStr ? absl::optional<size_t>(
static_cast<size_t>(pStr - m_pData->m_String))
: absl::nullopt;
@@ -905,13 +906,13 @@ size_t WideString::Replace(WideStringView pOld, WideStringView pNew) {
const wchar_t* pTarget =
FX_wcsstr(pStart, static_cast<size_t>(pEnd - pStart),
pOld.unterminated_c_str(), nSourceLen);
- wmemcpy(pDest, pStart, pTarget - pStart);
+ FXSYS_wmemcpy(pDest, pStart, pTarget - pStart);
pDest += pTarget - pStart;
- wmemcpy(pDest, pNew.unterminated_c_str(), pNew.GetLength());
+ FXSYS_wmemcpy(pDest, pNew.unterminated_c_str(), pNew.GetLength());
pDest += pNew.GetLength();
pStart = pTarget + nSourceLen;
}
- wmemcpy(pDest, pStart, pEnd - pStart);
+ FXSYS_wmemcpy(pDest, pStart, pEnd - pStart);
m_pData.Swap(pNewData);
return count;
}
@@ -1010,7 +1011,7 @@ int WideString::Compare(const WideString& str) const {
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);
+ int result = FXSYS_wmemcmp(m_pData->m_String, str.m_pData->m_String, min_len);
if (result != 0)
return result;
if (this_len == that_len)
diff --git a/core/fxcrt/widestring.h b/core/fxcrt/widestring.h
index 24547dde4..a01e96008 100644
--- a/core/fxcrt/widestring.h
+++ b/core/fxcrt/widestring.h
@@ -22,7 +22,7 @@
#include "core/fxcrt/string_view_template.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/base/check.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace fxcrt {
@@ -32,6 +32,7 @@ class ByteString;
// avoids the cost of std::string's iterator stability guarantees.
class WideString {
public:
+ // TODO(crbug.com/pdfium/2031): Consider switching to `char16_t` instead.
using CharType = wchar_t;
using const_iterator = const CharType*;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
@@ -303,6 +304,13 @@ std::ostream& operator<<(std::ostream& os, const WideString& str);
std::wostream& operator<<(std::wostream& os, WideStringView str);
std::ostream& operator<<(std::ostream& os, WideStringView str);
+// This is declared here for use in gtest-based tests but is defined in a test
+// support target. This should not be used in production code. Just use
+// operator<< from above instead.
+// In some cases, gtest will automatically use operator<< as well, but in this
+// case, it needs PrintTo() because WideString looks like a container to gtest.
+void PrintTo(const WideString& str, std::ostream* os);
+
} // namespace fxcrt
using WideString = fxcrt::WideString;
diff --git a/core/fxcrt/widestring_unittest.cpp b/core/fxcrt/widestring_unittest.cpp
index d45c4e8e2..947926ce2 100644
--- a/core/fxcrt/widestring_unittest.cpp
+++ b/core/fxcrt/widestring_unittest.cpp
@@ -12,7 +12,7 @@
#include "core/fxcrt/fx_string.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/base/containers/contains.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace fxcrt {
diff --git a/core/fxcrt/widetext_buffer.h b/core/fxcrt/widetext_buffer.h
index a02d12861..5c29a0bd0 100644
--- a/core/fxcrt/widetext_buffer.h
+++ b/core/fxcrt/widetext_buffer.h
@@ -11,7 +11,7 @@
#include "core/fxcrt/binary_buffer.h"
#include "core/fxcrt/fx_string.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace fxcrt {
diff --git a/core/fxcrt/xml/cfx_xmlparser.cpp b/core/fxcrt/xml/cfx_xmlparser.cpp
index a6f371f3b..6ca9ea4e9 100644
--- a/core/fxcrt/xml/cfx_xmlparser.cpp
+++ b/core/fxcrt/xml/cfx_xmlparser.cpp
@@ -13,6 +13,7 @@
#include <stack>
#include <utility>
+#include "core/fxcrt/autorestorer.h"
#include "core/fxcrt/cfx_seekablestreamproxy.h"
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/fx_codepage.h"
@@ -84,8 +85,8 @@ CFX_XMLParser::~CFX_XMLParser() = default;
std::unique_ptr<CFX_XMLDocument> CFX_XMLParser::Parse() {
auto doc = std::make_unique<CFX_XMLDocument>();
+ AutoRestorer<UnownedPtr<CFX_XMLNode>> restorer(&current_node_);
current_node_ = doc->GetRoot();
-
return DoSyntaxParse(doc.get()) ? std::move(doc) : nullptr;
}
@@ -458,8 +459,6 @@ bool CFX_XMLParser::DoSyntaxParse(CFX_XMLDocument* doc) {
current_buffer_idx++;
}
break;
- default:
- break;
}
}
}
diff --git a/core/fxcrt/xml/cfx_xmlparser.h b/core/fxcrt/xml/cfx_xmlparser.h
index 7a30b7c7f..268c9f25b 100644
--- a/core/fxcrt/xml/cfx_xmlparser.h
+++ b/core/fxcrt/xml/cfx_xmlparser.h
@@ -11,6 +11,7 @@
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/retain_ptr.h"
+#include "core/fxcrt/unowned_ptr.h"
#include "core/fxcrt/widestring.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -53,7 +54,7 @@ class CFX_XMLParser final {
void ProcessTextChar(wchar_t ch);
void ProcessTargetData();
- CFX_XMLNode* current_node_ = nullptr;
+ UnownedPtr<CFX_XMLNode> current_node_;
RetainPtr<CFX_SeekableStreamProxy> stream_;
DataVector<wchar_t> current_text_;
size_t xml_plane_size_ = 1024;
diff --git a/core/fxge/BUILD.gn b/core/fxge/BUILD.gn
index c526c06a9..a3d2b0e16 100644
--- a/core/fxge/BUILD.gn
+++ b/core/fxge/BUILD.gn
@@ -134,7 +134,10 @@ source_set("fxge") {
}
if (pdf_use_skia) {
- sources += [ "skia/fx_skia_device.cpp" ]
+ sources += [
+ "skia/cfx_dibbase_skia.cpp",
+ "skia/fx_skia_device.cpp",
+ ]
public_deps += [ "//skia" ]
}
@@ -173,8 +176,6 @@ source_set("fxge") {
sources += [
"cfx_windowsrenderdevice.cpp",
"cfx_windowsrenderdevice.h",
- "dib/cfx_dibextractor.cpp",
- "dib/cfx_dibextractor.h",
"win32/cfx_psfonttracker.cpp",
"win32/cfx_psfonttracker.h",
"win32/cfx_psrenderer.cpp",
@@ -236,6 +237,8 @@ pdfium_embeddertest_source_set("embeddertests") {
deps += [
":fxge",
"../../fpdfsdk",
+ "../fpdfapi/page",
+ "../fpdfapi/render",
"//skia",
]
}
diff --git a/core/fxge/DEPS b/core/fxge/DEPS
index 6492756b7..90942366a 100644
--- a/core/fxge/DEPS
+++ b/core/fxge/DEPS
@@ -1,3 +1,5 @@
-include_rules = [
- '+third_party/skia/include'
-]
+specific_include_rules = {
+ 'cfx_dibbase\.h|cfx_glyphcache\.(cpp|h)|cfx_renderdevice\.cpp': [
+ '+third_party/skia/include',
+ ],
+}
diff --git a/core/fxge/agg/fx_agg_driver.cpp b/core/fxge/agg/fx_agg_driver.cpp
index a1949de54..e1fd404f0 100644
--- a/core/fxge/agg/fx_agg_driver.cpp
+++ b/core/fxge/agg/fx_agg_driver.cpp
@@ -15,6 +15,7 @@
#include "build/build_config.h"
#include "core/fxcrt/fx_2d_size.h"
#include "core/fxcrt/fx_safe_types.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
#include "core/fxge/cfx_cliprgn.h"
#include "core/fxge/cfx_defaultrenderdevice.h"
#include "core/fxge/cfx_graphstatedata.h"
@@ -24,9 +25,8 @@
#include "core/fxge/dib/cfx_imagestretcher.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
-#include "third_party/base/cxx17_backports.h"
+#include "third_party/base/containers/span.h"
#include "third_party/base/notreached.h"
-#include "third_party/base/span.h"
// Ignore fallthrough warnings in agg23 headers.
#if defined(__clang__)
@@ -52,8 +52,8 @@ namespace {
const float kMaxPos = 32000.0f;
CFX_PointF HardClip(const CFX_PointF& pos) {
- return CFX_PointF(pdfium::clamp(pos.x, -kMaxPos, kMaxPos),
- pdfium::clamp(pos.y, -kMaxPos, kMaxPos));
+ return CFX_PointF(std::clamp(pos.x, -kMaxPos, kMaxPos),
+ std::clamp(pos.y, -kMaxPos, kMaxPos));
}
void RgbByteOrderCompositeRect(const RetainPtr<CFX_DIBitmap>& pBitmap,
@@ -74,7 +74,7 @@ void RgbByteOrderCompositeRect(const RetainPtr<CFX_DIBitmap>& pBitmap,
int src_b = FXARGB_B(argb);
int Bpp = pBitmap->GetBPP() / 8;
int dib_argb = FXARGB_TOBGRORDERDIB(argb);
- pdfium::span<uint8_t> pBuffer = pBitmap->GetBuffer();
+ pdfium::span<uint8_t> pBuffer = pBitmap->GetWritableBuffer();
if (src_alpha == 255) {
for (int row = rect.top; row < rect.bottom; row++) {
uint8_t* dest_scan =
@@ -151,8 +151,9 @@ void RgbByteOrderTransferBitmap(const RetainPtr<CFX_DIBitmap>& pBitmap,
const size_t dest_x_offset = Fx2DSizeOrDie(dest_left, Bpp);
const size_t dest_y_offset = Fx2DSizeOrDie(dest_top, dest_pitch);
- pdfium::span<uint8_t> dest_span =
- pBitmap->GetBuffer().subspan(dest_y_offset).subspan(dest_x_offset);
+ pdfium::span<uint8_t> dest_span = pBitmap->GetWritableBuffer()
+ .subspan(dest_y_offset)
+ .subspan(dest_x_offset);
if (dest_format == src_format) {
const size_t src_x_offset = Fx2DSizeOrDie(src_left, Bpp);
for (int row = 0; row < height; row++) {
@@ -340,55 +341,61 @@ class CFX_Renderer {
void render(const Scanline& sl);
private:
- using CompositeSpanFunc = void (
- CFX_Renderer::*)(uint8_t*, int, int, int, uint8_t*, int, int, uint8_t*);
+ using CompositeSpanFunc = void (CFX_Renderer::*)(uint8_t*,
+ int,
+ int,
+ int,
+ const uint8_t*,
+ int,
+ int,
+ const uint8_t*);
void CompositeSpan(uint8_t* dest_scan,
- uint8_t* backdrop_scan,
+ const uint8_t* backdrop_scan,
int Bpp,
bool bDestAlpha,
int span_left,
int span_len,
- uint8_t* cover_scan,
+ const uint8_t* cover_scan,
int clip_left,
int clip_right,
- uint8_t* clip_scan);
+ const uint8_t* clip_scan);
void CompositeSpan1bpp(uint8_t* dest_scan,
int Bpp,
int span_left,
int span_len,
- uint8_t* cover_scan,
+ const uint8_t* cover_scan,
int clip_left,
int clip_right,
- uint8_t* clip_scan);
+ const uint8_t* clip_scan);
void CompositeSpanGray(uint8_t* dest_scan,
int Bpp,
int span_left,
int span_len,
- uint8_t* cover_scan,
+ const uint8_t* cover_scan,
int clip_left,
int clip_right,
- uint8_t* clip_scan);
+ const uint8_t* clip_scan);
void CompositeSpanARGB(uint8_t* dest_scan,
int Bpp,
int span_left,
int span_len,
- uint8_t* cover_scan,
+ const uint8_t* cover_scan,
int clip_left,
int clip_right,
- uint8_t* clip_scan);
+ const uint8_t* clip_scan);
void CompositeSpanRGB(uint8_t* dest_scan,
int Bpp,
int span_left,
int span_len,
- uint8_t* cover_scan,
+ const uint8_t* cover_scan,
int clip_left,
int clip_right,
- uint8_t* clip_scan);
+ const uint8_t* clip_scan);
void CompositeSpan1bppHelper(uint8_t* dest_scan,
int col_start,
@@ -445,15 +452,15 @@ class CFX_Renderer {
};
void CFX_Renderer::CompositeSpan(uint8_t* dest_scan,
- uint8_t* backdrop_scan,
+ const uint8_t* backdrop_scan,
int Bpp,
bool bDestAlpha,
int span_left,
int span_len,
- uint8_t* cover_scan,
+ const uint8_t* cover_scan,
int clip_left,
int clip_right,
- uint8_t* clip_scan) {
+ const uint8_t* clip_scan) {
int col_start = GetColStart(span_left, clip_left);
int col_end = GetColEnd(span_left, span_len, clip_right);
if (Bpp) {
@@ -592,10 +599,10 @@ void CFX_Renderer::CompositeSpan1bpp(uint8_t* dest_scan,
int Bpp,
int span_left,
int span_len,
- uint8_t* cover_scan,
+ const uint8_t* cover_scan,
int clip_left,
int clip_right,
- uint8_t* clip_scan) {
+ const uint8_t* clip_scan) {
DCHECK(!m_bRgbByteOrder);
int col_start = GetColStart(span_left, clip_left);
int col_end = GetColEnd(span_left, span_len, clip_right);
@@ -608,10 +615,10 @@ void CFX_Renderer::CompositeSpanGray(uint8_t* dest_scan,
int Bpp,
int span_left,
int span_len,
- uint8_t* cover_scan,
+ const uint8_t* cover_scan,
int clip_left,
int clip_right,
- uint8_t* clip_scan) {
+ const uint8_t* clip_scan) {
DCHECK(!m_bRgbByteOrder);
int col_start = GetColStart(span_left, clip_left);
int col_end = GetColEnd(span_left, span_len, clip_right);
@@ -632,10 +639,10 @@ void CFX_Renderer::CompositeSpanARGB(uint8_t* dest_scan,
int Bpp,
int span_left,
int span_len,
- uint8_t* cover_scan,
+ const uint8_t* cover_scan,
int clip_left,
int clip_right,
- uint8_t* clip_scan) {
+ const uint8_t* clip_scan) {
int col_start = GetColStart(span_left, clip_left);
int col_end = GetColEnd(span_left, span_len, clip_right);
dest_scan += col_start * Bpp;
@@ -700,10 +707,10 @@ void CFX_Renderer::CompositeSpanRGB(uint8_t* dest_scan,
int Bpp,
int span_left,
int span_len,
- uint8_t* cover_scan,
+ const uint8_t* cover_scan,
int clip_left,
int clip_right,
- uint8_t* clip_scan) {
+ const uint8_t* clip_scan) {
int col_start = GetColStart(span_left, clip_left);
int col_end = GetColEnd(span_left, span_len, clip_right);
dest_scan += col_start * Bpp;
@@ -796,8 +803,8 @@ void CFX_Renderer::render(const Scanline& sl) {
return;
uint8_t* dest_scan =
- m_pDevice->GetBuffer().subspan(m_pDevice->GetPitch() * y).data();
- uint8_t* backdrop_scan = nullptr;
+ m_pDevice->GetWritableBuffer().subspan(m_pDevice->GetPitch() * y).data();
+ const uint8_t* backdrop_scan = nullptr;
if (m_pBackdropDevice) {
backdrop_scan = m_pBackdropDevice->GetBuffer()
.subspan(m_pBackdropDevice->GetPitch() * y)
@@ -813,7 +820,7 @@ void CFX_Renderer::render(const Scanline& sl) {
int x = span->x;
uint8_t* dest_pos = nullptr;
- uint8_t* backdrop_pos = nullptr;
+ const uint8_t* backdrop_pos = nullptr;
if (Bpp) {
backdrop_pos = backdrop_scan ? backdrop_scan + x * Bpp : nullptr;
dest_pos = dest_scan + x * Bpp;
@@ -821,7 +828,7 @@ void CFX_Renderer::render(const Scanline& sl) {
dest_pos = dest_scan + x / 8;
backdrop_pos = backdrop_scan ? backdrop_scan + x / 8 : nullptr;
}
- uint8_t* clip_pos = nullptr;
+ const uint8_t* clip_pos = nullptr;
if (m_pClipMask) {
// TODO(crbug.com/1382604): use subspan arithmetic.
clip_pos = m_pClipMask->GetBuffer().data() +
@@ -902,7 +909,7 @@ class RendererScanLineAaOffset {
}
private:
- base_ren_type* m_ren;
+ UNOWNED_PTR_EXCLUSION base_ren_type* m_ren;
color_type m_color;
unsigned m_left;
unsigned m_top;
@@ -1020,8 +1027,7 @@ int CFX_AggDeviceDriver::GetDeviceCaps(int caps_id) const {
return flags;
}
default:
- NOTREACHED();
- return 0;
+ NOTREACHED_NORETURN();
}
}
@@ -1054,7 +1060,7 @@ void CFX_AggDeviceDriver::SetClipMask(agg::rasterizer_scanline_aa& rasterizer) {
auto pThisLayer = pdfium::MakeRetain<CFX_DIBitmap>();
pThisLayer->Create(path_rect.Width(), path_rect.Height(),
FXDIB_Format::k8bppMask);
- agg::rendering_buffer raw_buf(pThisLayer->GetBuffer().data(),
+ agg::rendering_buffer raw_buf(pThisLayer->GetWritableBuffer().data(),
pThisLayer->GetWidth(), pThisLayer->GetHeight(),
pThisLayer->GetPitch());
agg::pixfmt_gray8 pixel_buf(raw_buf);
diff --git a/core/fxge/agg/fx_agg_driver.h b/core/fxge/agg/fx_agg_driver.h
index 3b3d8dc23..523bb0ca9 100644
--- a/core/fxge/agg/fx_agg_driver.h
+++ b/core/fxge/agg/fx_agg_driver.h
@@ -15,6 +15,10 @@
#include "core/fxge/cfx_fillrenderoptions.h"
#include "core/fxge/renderdevicedriver_iface.h"
+#if BUILDFLAG(IS_APPLE)
+#include "core/fxcrt/unowned_ptr_exclusion.h"
+#endif
+
class CFX_ClipRgn;
class CFX_GraphStateData;
class CFX_Matrix;
@@ -109,7 +113,7 @@ class CFX_AggDeviceDriver final : public RenderDeviceDriverIface {
std::unique_ptr<CFX_ClipRgn> m_pClipRgn;
std::vector<std::unique_ptr<CFX_ClipRgn>> m_StateStack;
#if BUILDFLAG(IS_APPLE)
- void* m_pPlatformGraphics = nullptr;
+ UNOWNED_PTR_EXCLUSION void* m_pPlatformGraphics = nullptr;
#endif
CFX_FillRenderOptions m_FillOptions;
const bool m_bRgbByteOrder;
diff --git a/core/fxge/android/cfpf_skiafont.h b/core/fxge/android/cfpf_skiafont.h
index 840db635f..c320806ff 100644
--- a/core/fxge/android/cfpf_skiafont.h
+++ b/core/fxge/android/cfpf_skiafont.h
@@ -15,7 +15,7 @@
#include "core/fxcrt/unowned_ptr.h"
#include "core/fxge/cfx_face.h"
#include "core/fxge/freetype/fx_freetype.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFPF_SkiaFontMgr;
class CFPF_SkiaPathFont;
diff --git a/core/fxge/android/cfx_androidfontinfo.h b/core/fxge/android/cfx_androidfontinfo.h
index 5f6889973..54500baa1 100644
--- a/core/fxge/android/cfx_androidfontinfo.h
+++ b/core/fxge/android/cfx_androidfontinfo.h
@@ -12,7 +12,7 @@
#include "core/fxcrt/unowned_ptr.h"
#include "core/fxge/cfx_fontmapper.h"
#include "core/fxge/systemfontinfo_iface.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFPF_SkiaFontMgr;
diff --git a/core/fxge/android/fx_android_impl.cpp b/core/fxge/android/fx_android_impl.cpp
index e06d611ee..12783f5ea 100644
--- a/core/fxge/android/fx_android_impl.cpp
+++ b/core/fxge/android/fx_android_impl.cpp
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include "core/fxcrt/unowned_ptr.h"
#include "core/fxge/android/cfpf_skiadevicemodule.h"
#include "core/fxge/android/cfx_androidfontinfo.h"
#include "core/fxge/cfx_fontmgr.h"
@@ -33,7 +34,7 @@ class CAndroidPlatform : public CFX_GEModule::PlatformIface {
}
private:
- CFPF_SkiaDeviceModule* m_pDeviceModule = nullptr;
+ UnownedPtr<CFPF_SkiaDeviceModule> m_pDeviceModule;
};
// static
diff --git a/core/fxge/apple/fx_apple_impl.cpp b/core/fxge/apple/fx_apple_impl.cpp
index 54f694f1a..fa397c0e1 100644
--- a/core/fxge/apple/fx_apple_impl.cpp
+++ b/core/fxge/apple/fx_apple_impl.cpp
@@ -23,7 +23,7 @@
#include "core/fxge/dib/cfx_dibitmap.h"
#include "core/fxge/freetype/fx_freetype.h"
#include "core/fxge/text_char_pos.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace {
diff --git a/core/fxge/apple/fx_quartz_device.cpp b/core/fxge/apple/fx_quartz_device.cpp
index 9f5f13fef..24e0c9c15 100644
--- a/core/fxge/apple/fx_quartz_device.cpp
+++ b/core/fxge/apple/fx_quartz_device.cpp
@@ -33,8 +33,8 @@ void* CQuartz2D::CreateGraphics(const RetainPtr<CFX_DIBitmap>& pBitmap) {
}
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(
- pBitmap->GetBuffer().data(), pBitmap->GetWidth(), pBitmap->GetHeight(), 8,
- pBitmap->GetPitch(), colorSpace, bmpInfo);
+ pBitmap->GetWritableBuffer().data(), pBitmap->GetWidth(),
+ pBitmap->GetHeight(), 8, pBitmap->GetPitch(), colorSpace, bmpInfo);
CGColorSpaceRelease(colorSpace);
return context;
}
diff --git a/core/fxge/apple/fx_quartz_device.h b/core/fxge/apple/fx_quartz_device.h
index 0aaf520b1..97080e3fa 100644
--- a/core/fxge/apple/fx_quartz_device.h
+++ b/core/fxge/apple/fx_quartz_device.h
@@ -12,7 +12,7 @@
#include "core/fxcrt/retain_ptr.h"
#include "core/fxge/dib/fx_dib.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_DIBitmap;
class CFX_Matrix;
diff --git a/core/fxge/cfx_color.cpp b/core/fxge/cfx_color.cpp
index 23cdd0faa..35e03a5bb 100644
--- a/core/fxge/cfx_color.cpp
+++ b/core/fxge/cfx_color.cpp
@@ -87,8 +87,7 @@ CFX_Color CFX_Color::ConvertColorType(Type nConvertColorType) const {
case CFX_Color::Type::kTransparent:
break;
case CFX_Color::Type::kGray:
- NOTREACHED();
- break;
+ NOTREACHED_NORETURN();
case CFX_Color::Type::kRGB:
ret = ConvertGRAY2RGB(fColor1);
break;
@@ -105,8 +104,7 @@ CFX_Color CFX_Color::ConvertColorType(Type nConvertColorType) const {
ret = ConvertRGB2GRAY(fColor1, fColor2, fColor3);
break;
case CFX_Color::Type::kRGB:
- NOTREACHED();
- break;
+ NOTREACHED_NORETURN();
case CFX_Color::Type::kCMYK:
ret = ConvertRGB2CMYK(fColor1, fColor2, fColor3);
break;
@@ -123,8 +121,7 @@ CFX_Color CFX_Color::ConvertColorType(Type nConvertColorType) const {
ret = ConvertCMYK2RGB(fColor1, fColor2, fColor3, fColor4);
break;
case CFX_Color::Type::kCMYK:
- NOTREACHED();
- break;
+ NOTREACHED_NORETURN();
}
break;
}
diff --git a/core/fxge/cfx_defaultrenderdevice.h b/core/fxge/cfx_defaultrenderdevice.h
index f9c20fe99..4d94b7aef 100644
--- a/core/fxge/cfx_defaultrenderdevice.h
+++ b/core/fxge/cfx_defaultrenderdevice.h
@@ -13,8 +13,7 @@
#include "core/fxge/cfx_renderdevice.h"
#include "core/fxge/dib/fx_dib.h"
-class SkPictureRecorder;
-struct SkRect;
+class SkCanvas;
class CFX_DefaultRenderDevice final : public CFX_RenderDevice {
public:
@@ -34,15 +33,8 @@ class CFX_DefaultRenderDevice final : public CFX_RenderDevice {
RetainPtr<CFX_DIBitmap> pBackdropBitmap);
#if defined(_SKIA_SUPPORT_)
- bool AttachRecorder(SkPictureRecorder* recorder);
+ bool AttachCanvas(SkCanvas* canvas);
void Clear(uint32_t color);
- std::unique_ptr<SkPictureRecorder> CreateRecorder(const SkRect& bounds);
- bool SetBitsWithMask(const RetainPtr<CFX_DIBBase>& pBitmap,
- const RetainPtr<CFX_DIBBase>& pMask,
- int left,
- int top,
- int bitmap_alpha,
- BlendMode blend_type) override;
#endif
// Runtime check to see if Skia is the renderer variant in use.
diff --git a/core/fxge/cfx_face.h b/core/fxge/cfx_face.h
index 6f1ee5a58..6c74eae18 100644
--- a/core/fxge/cfx_face.h
+++ b/core/fxge/cfx_face.h
@@ -8,7 +8,7 @@
#include "core/fxcrt/observed_ptr.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxge/freetype/fx_freetype.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_Face final : public Retainable, public Observable {
public:
diff --git a/core/fxge/cfx_font.cpp b/core/fxge/cfx_font.cpp
index e9ca56b2a..033038651 100644
--- a/core/fxge/cfx_font.cpp
+++ b/core/fxge/cfx_font.cpp
@@ -28,8 +28,8 @@
#include "core/fxge/fx_font.h"
#include "core/fxge/scoped_font_transform.h"
#include "third_party/base/check.h"
+#include "third_party/base/containers/span.h"
#include "third_party/base/numerics/safe_conversions.h"
-#include "third_party/base/span.h"
#define EM_ADJUST(em, a) (em == 0 ? (a) : (a)*1000 / em)
@@ -45,30 +45,6 @@ struct OUTLINE_PARAMS {
float m_CoordUnit;
};
-// TODO(crbug.com/pdfium/1400): When FT_Done_MM_Var() is more likely to be
-// available to all users in the future, remove FreeMMVar() and use
-// FT_Done_MM_Var() directly.
-//
-// Use weak symbols to check if FT_Done_MM_Var() is available at runtime.
-#if !BUILDFLAG(IS_WIN)
-extern "C" __attribute__((weak)) decltype(FT_Done_MM_Var) FT_Done_MM_Var;
-#endif
-
-void FreeMMVar(FXFT_FaceRec* rec, FXFT_MM_VarPtr variation_desc) {
-#if BUILDFLAG(IS_WIN)
- // Assume `use_system_freetype` GN var is never set on Windows.
- constexpr bool has_ft_done_mm_var_func = true;
-#else
- static const bool has_ft_done_mm_var_func = !!FT_Done_MM_Var;
-#endif
- if (has_ft_done_mm_var_func) {
- FT_Done_MM_Var(CFX_GEModule::Get()->GetFontMgr()->GetFTLibrary(),
- variation_desc);
- } else {
- FXFT_Free(rec, variation_desc);
- }
-}
-
FX_RECT FXRectFromFTPos(FT_Pos left, FT_Pos top, FT_Pos right, FT_Pos bottom) {
return FX_RECT(pdfium::base::checked_cast<int32_t>(left),
pdfium::base::checked_cast<int32_t>(top),
@@ -637,10 +613,6 @@ absl::optional<FX_RECT> CFX_Font::GetBBox() const {
return result;
}
-void CFX_Font::AllocSubData(size_t size) {
- m_pSubData.reset(FX_Alloc(uint8_t, size));
-}
-
RetainPtr<CFX_GlyphCache> CFX_Font::GetOrCreateGlyphCache() const {
if (!m_GlyphCache)
m_GlyphCache = CFX_GEModule::Get()->GetFontCache()->GetGlyphCache(this);
@@ -655,24 +627,23 @@ void CFX_Font::AdjustMMParams(int glyph_index,
int dest_width,
int weight) const {
DCHECK(dest_width >= 0);
- FXFT_MM_VarPtr pMasters = nullptr;
- FT_Get_MM_Var(m_Face->GetRec(), &pMasters);
- if (!pMasters)
+ ScopedFXFTMMVar variation_desc(m_Face->GetRec());
+ if (!variation_desc) {
return;
+ }
FT_Pos coords[2];
- if (weight == 0)
- coords[0] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 0)) / 65536;
- else
+ if (weight == 0) {
+ coords[0] = variation_desc.GetAxisDefault(0) / 65536;
+ } else {
coords[0] = weight;
+ }
if (dest_width == 0) {
- coords[1] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 1)) / 65536;
+ coords[1] = variation_desc.GetAxisDefault(1) / 65536;
} else {
- FT_Long min_param =
- FXFT_Get_MM_Axis_Min(FXFT_Get_MM_Axis(pMasters, 1)) / 65536;
- FT_Long max_param =
- FXFT_Get_MM_Axis_Max(FXFT_Get_MM_Axis(pMasters, 1)) / 65536;
+ FT_Long min_param = variation_desc.GetAxisMin(1) / 65536;
+ FT_Long max_param = variation_desc.GetAxisMax(1) / 65536;
coords[1] = min_param;
FT_Set_MM_Design_Coordinates(m_Face->GetRec(), 2, coords);
FT_Load_Glyph(m_Face->GetRec(), glyph_index,
@@ -686,7 +657,6 @@ void CFX_Font::AdjustMMParams(int glyph_index,
FT_Pos max_width = FXFT_Get_Glyph_HoriAdvance(m_Face->GetRec()) * 1000 /
FXFT_Get_Face_UnitsPerEM(m_Face->GetRec());
if (max_width == min_width) {
- FreeMMVar(m_Face->GetRec(), pMasters);
return;
}
FT_Pos param = min_param + (max_param - min_param) *
@@ -694,7 +664,6 @@ void CFX_Font::AdjustMMParams(int glyph_index,
(max_width - min_width);
coords[1] = param;
}
- FreeMMVar(m_Face->GetRec(), pMasters);
FT_Set_MM_Design_Coordinates(m_Face->GetRec(), 2, coords);
}
diff --git a/core/fxge/cfx_font.h b/core/fxge/cfx_font.h
index bf948743b..d1cc83de2 100644
--- a/core/fxge/cfx_font.h
+++ b/core/fxge/cfx_font.h
@@ -16,12 +16,12 @@
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/fx_codepage_forward.h"
#include "core/fxcrt/fx_coordinates.h"
-#include "core/fxcrt/fx_memory_wrappers.h"
#include "core/fxcrt/retain_ptr.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
#include "core/fxge/cfx_face.h"
#include "core/fxge/freetype/fx_freetype.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#if defined(_SKIA_SUPPORT_)
#include "core/fxge/fx_font.h"
@@ -128,8 +128,6 @@ class CFX_Font {
absl::optional<FX_RECT> GetBBox() const;
bool IsEmbedded() const { return m_bEmbedded; }
- void AllocSubData(size_t size);
- uint8_t* GetSubData() const { return m_pSubData.get(); }
FontType GetFontType() const { return m_FontType; }
void SetFontType(FontType type) { m_FontType = type; }
uint64_t GetObjectTag() const { return m_ObjectTag; }
@@ -166,7 +164,6 @@ class CFX_Font {
mutable RetainPtr<CFX_Face> m_Face;
mutable RetainPtr<CFX_GlyphCache> m_GlyphCache;
std::unique_ptr<CFX_SubstFont> m_pSubstFont;
- std::unique_ptr<uint8_t, FxFreeDeleter> m_pSubData;
DataVector<uint8_t> m_FontDataAllocation;
pdfium::span<uint8_t> m_FontData;
FontType m_FontType = FontType::kUnknown;
@@ -174,7 +171,7 @@ class CFX_Font {
bool m_bEmbedded = false;
bool m_bVertical = false;
#if BUILDFLAG(IS_APPLE)
- void* m_pPlatformFont = nullptr;
+ UNOWNED_PTR_EXCLUSION void* m_pPlatformFont = nullptr;
#endif
};
diff --git a/core/fxge/cfx_fontmapper.cpp b/core/fxge/cfx_fontmapper.cpp
index 34c70a854..63173b6ea 100644
--- a/core/fxge/cfx_fontmapper.cpp
+++ b/core/fxge/cfx_fontmapper.cpp
@@ -19,13 +19,13 @@
#include "core/fxcrt/fx_memory.h"
#include "core/fxcrt/fx_memory_wrappers.h"
#include "core/fxcrt/stl_util.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
#include "core/fxge/cfx_fontmgr.h"
#include "core/fxge/cfx_substfont.h"
#include "core/fxge/fx_font.h"
#include "core/fxge/systemfontinfo_iface.h"
#include "third_party/base/check_op.h"
#include "third_party/base/containers/contains.h"
-#include "third_party/base/cxx17_backports.h"
namespace {
@@ -390,7 +390,7 @@ class ScopedFontDeleter {
private:
UnownedPtr<SystemFontInfoIface> const font_info_;
- void* const font_;
+ UNOWNED_PTR_EXCLUSION void* const font_; // void type incompatible.
};
} // namespace
@@ -715,7 +715,7 @@ RetainPtr<CFX_Face> CFX_FontMapper::FindSubstFont(const ByteString& name,
}
if (Charset == FX_Charset::kSymbol) {
-#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_ANDROID)
+#if !BUILDFLAG(IS_WIN)
if (subst_name == "Symbol") {
subst_font->m_Family = "Chrome Symbol";
subst_font->m_Charset = FX_Charset::kSymbol;
diff --git a/core/fxge/cfx_fontmgr.h b/core/fxge/cfx_fontmgr.h
index 31539aaad..2936e261c 100644
--- a/core/fxge/cfx_fontmgr.h
+++ b/core/fxge/cfx_fontmgr.h
@@ -20,7 +20,7 @@
#include "core/fxcrt/retain_ptr.h"
#include "core/fxge/cfx_face.h"
#include "core/fxge/freetype/fx_freetype.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_FontMapper;
@@ -29,7 +29,6 @@ class CFX_FontMgr {
class FontDesc final : public Retainable, public Observable {
public:
CONSTRUCT_VIA_MAKE_RETAIN;
- ~FontDesc() override;
pdfium::span<const uint8_t> FontData() const { return m_pFontData; }
void SetFace(size_t index, CFX_Face* face);
@@ -37,6 +36,7 @@ class CFX_FontMgr {
private:
explicit FontDesc(FixedUninitDataVector<uint8_t> data);
+ ~FontDesc() override;
const FixedUninitDataVector<uint8_t> m_pFontData;
ObservedPtr<CFX_Face> m_TTCFaces[16];
diff --git a/core/fxge/cfx_gemodule.h b/core/fxge/cfx_gemodule.h
index f1f00f6a9..f6846ce4c 100644
--- a/core/fxge/cfx_gemodule.h
+++ b/core/fxge/cfx_gemodule.h
@@ -12,9 +12,10 @@
#include <memory>
#include "build/build_config.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
#if BUILDFLAG(IS_APPLE)
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#endif
class CFX_FontCache;
@@ -52,7 +53,9 @@ class CFX_GEModule {
std::unique_ptr<PlatformIface> const m_pPlatform;
std::unique_ptr<CFX_FontMgr> const m_pFontMgr;
std::unique_ptr<CFX_FontCache> const m_pFontCache;
- const char** const m_pUserFontPaths;
+
+ // Exclude because taken from public API.
+ UNOWNED_PTR_EXCLUSION const char** const m_pUserFontPaths;
};
#endif // CORE_FXGE_CFX_GEMODULE_H_
diff --git a/core/fxge/cfx_glyphcache.cpp b/core/fxge/cfx_glyphcache.cpp
index 1f12d7bd3..ba308d4ba 100644
--- a/core/fxge/cfx_glyphcache.cpp
+++ b/core/fxge/cfx_glyphcache.cpp
@@ -204,7 +204,7 @@ std::unique_ptr<CFX_GlyphBitmap> CFX_GlyphCache::RenderGlyph(
: FXDIB_Format::k8bppMask);
int dest_pitch = pGlyphBitmap->GetBitmap()->GetPitch();
int src_pitch = FXFT_Get_Bitmap_Pitch(FXFT_Get_Glyph_Bitmap(GetFaceRec()));
- uint8_t* pDestBuf = pGlyphBitmap->GetBitmap()->GetBuffer().data();
+ uint8_t* pDestBuf = pGlyphBitmap->GetBitmap()->GetWritableBuffer().data();
uint8_t* pSrcBuf = static_cast<uint8_t*>(
FXFT_Get_Bitmap_Buffer(FXFT_Get_Glyph_Bitmap(GetFaceRec())));
if (anti_alias != FT_RENDER_MODE_MONO &&
diff --git a/core/fxge/cfx_glyphcache.h b/core/fxge/cfx_glyphcache.h
index ff2e7409c..c71ae3c8d 100644
--- a/core/fxge/cfx_glyphcache.h
+++ b/core/fxge/cfx_glyphcache.h
@@ -18,7 +18,7 @@
#if defined(_SKIA_SUPPORT_)
#include "core/fxge/fx_font.h"
-#include "third_party/skia/include/core/SkTypeface.h" // nogncheck
+#include "third_party/skia/include/core/SkRefCnt.h" // nogncheck
#endif
class CFX_Font;
@@ -30,7 +30,6 @@ struct CFX_TextRenderOptions;
class CFX_GlyphCache final : public Retainable, public Observable {
public:
CONSTRUCT_VIA_MAKE_RETAIN;
- ~CFX_GlyphCache() override;
const CFX_GlyphBitmap* LoadGlyphBitmap(const CFX_Font* pFont,
uint32_t glyph_index,
@@ -56,6 +55,7 @@ class CFX_GlyphCache final : public Retainable, public Observable {
private:
explicit CFX_GlyphCache(RetainPtr<CFX_Face> face);
+ ~CFX_GlyphCache() override;
using SizeGlyphCache = std::map<uint32_t, std::unique_ptr<CFX_GlyphBitmap>>;
// <glyph_index, width, weight, angle, vertical>
diff --git a/core/fxge/cfx_renderdevice.cpp b/core/fxge/cfx_renderdevice.cpp
index d39a02f06..2280f6fe7 100644
--- a/core/fxge/cfx_renderdevice.cpp
+++ b/core/fxge/cfx_renderdevice.cpp
@@ -33,7 +33,7 @@
#include "core/fxge/text_glyph_pos.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#if defined(_SKIA_SUPPORT_)
#include "third_party/skia/include/core/SkTypes.h" // nogncheck
@@ -426,7 +426,7 @@ bool GetZeroAreaPath(pdfium::span<const CFX_Path::Point> points,
for (size_t i = 0; i < points.size(); i++) {
CFX_Path::Point::Type point_type = points[i].m_Type;
if (point_type == CFX_Path::Point::Type::kMove) {
- DCHECK_EQ(0, i);
+ DCHECK_EQ(0u, i);
continue;
}
@@ -1186,14 +1186,6 @@ bool CFX_RenderDevice::DrawNormalText(pdfium::span<const TextCharPos> pCharPos,
end_col, normalize, x_subpixel, a, r, g, b);
}
-#if defined(_SKIA_SUPPORT_)
- if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
- // DrawNormalTextHelper() can result in unpremultiplied bitmaps for
- // rendering glyphs. Make sure `bitmap` is premultiplied before proceeding.
- bitmap->PreMultiply();
- }
-#endif
-
if (bitmap->IsMaskFormat())
SetBitMask(bitmap, bmp_rect.left, bmp_rect.top, fill_color);
else
@@ -1349,7 +1341,6 @@ void CFX_RenderDevice::DrawBorder(const CFX_Matrix* pUser2Device,
const float fHalfWidth = fWidth / 2.0f;
switch (nStyle) {
- default:
case BorderStyle::kSolid: {
CFX_Path path;
path.AppendRect(fLeft, fBottom, fRight, fTop);
diff --git a/core/fxge/cfx_renderdevice.h b/core/fxge/cfx_renderdevice.h
index e1d9487f2..8e6e38014 100644
--- a/core/fxge/cfx_renderdevice.h
+++ b/core/fxge/cfx_renderdevice.h
@@ -18,7 +18,7 @@
#include "core/fxge/dib/fx_dib.h"
#include "core/fxge/render_defines.h"
#include "core/fxge/renderdevicedriver_iface.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_DIBBase;
class CFX_DIBitmap;
@@ -215,12 +215,12 @@ class CFX_RenderDevice {
bool MultiplyAlpha(const RetainPtr<CFX_DIBBase>& mask);
#if defined(_SKIA_SUPPORT_)
- virtual bool SetBitsWithMask(const RetainPtr<CFX_DIBBase>& pBitmap,
- const RetainPtr<CFX_DIBBase>& pMask,
- int left,
- int top,
- int bitmap_alpha,
- BlendMode blend_type);
+ bool SetBitsWithMask(const RetainPtr<CFX_DIBBase>& pBitmap,
+ const RetainPtr<CFX_DIBBase>& pMask,
+ int left,
+ int top,
+ int bitmap_alpha,
+ BlendMode blend_type);
#endif
protected:
diff --git a/core/fxge/dib/cfx_bitmapcomposer.cpp b/core/fxge/dib/cfx_bitmapcomposer.cpp
index 009a61889..e924034b6 100644
--- a/core/fxge/dib/cfx_bitmapcomposer.cpp
+++ b/core/fxge/dib/cfx_bitmapcomposer.cpp
@@ -131,7 +131,7 @@ void CFX_BitmapComposer::ComposeScanlineV(
int Bpp = m_pBitmap->GetBPP() / 8;
int dest_pitch = m_pBitmap->GetPitch();
int dest_x = m_DestLeft + (m_bFlipX ? (m_DestWidth - line - 1) : line);
- pdfium::span<uint8_t> dest_span = m_pBitmap->GetBuffer();
+ pdfium::span<uint8_t> dest_span = m_pBitmap->GetWritableBuffer();
if (!dest_span.empty()) {
const size_t dest_x_offset = Fx2DSizeOrDie(dest_x, Bpp);
const size_t dest_y_offset = Fx2DSizeOrDie(m_DestTop, dest_pitch);
diff --git a/core/fxge/dib/cfx_bitmapstorer.h b/core/fxge/dib/cfx_bitmapstorer.h
index de934e22f..7a5e3ffe7 100644
--- a/core/fxge/dib/cfx_bitmapstorer.h
+++ b/core/fxge/dib/cfx_bitmapstorer.h
@@ -9,7 +9,7 @@
#include "core/fxcrt/retain_ptr.h"
#include "core/fxge/dib/scanlinecomposer_iface.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_DIBitmap;
diff --git a/core/fxge/dib/cfx_dibbase.cpp b/core/fxge/dib/cfx_dibbase.cpp
index 07c7b744d..97f8440ae 100644
--- a/core/fxge/dib/cfx_dibbase.cpp
+++ b/core/fxge/dib/cfx_dibbase.cpp
@@ -26,8 +26,8 @@
#include "core/fxge/dib/cfx_imagetransformer.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
+#include "third_party/base/containers/span.h"
#include "third_party/base/notreached.h"
-#include "third_party/base/span.h"
namespace {
@@ -620,8 +620,8 @@ CFX_DIBBase::CFX_DIBBase() = default;
CFX_DIBBase::~CFX_DIBBase() = default;
-pdfium::span<uint8_t> CFX_DIBBase::GetBuffer() const {
- return pdfium::span<uint8_t>();
+pdfium::span<const uint8_t> CFX_DIBBase::GetBuffer() const {
+ return pdfium::span<const uint8_t>();
}
bool CFX_DIBBase::SkipToScanline(int line, PauseIndicatorIface* pPause) const {
@@ -956,8 +956,9 @@ RetainPtr<CFX_DIBitmap> CFX_DIBBase::ConvertTo(FXDIB_Format dest_format) const {
RetainPtr<const CFX_DIBBase> holder(this);
DataVector<uint32_t> pal_8bpp;
- if (!ConvertBuffer(dest_format, pClone->GetBuffer(), pClone->GetPitch(),
- m_Width, m_Height, holder, 0, 0, &pal_8bpp)) {
+ if (!ConvertBuffer(dest_format, pClone->GetWritableBuffer(),
+ pClone->GetPitch(), m_Width, m_Height, holder, 0, 0,
+ &pal_8bpp)) {
return nullptr;
}
if (!pal_8bpp.empty())
@@ -979,8 +980,8 @@ RetainPtr<CFX_DIBitmap> CFX_DIBBase::SwapXY(bool bXFlip, bool bYFlip) const {
pTransBitmap->SetPalette(GetPaletteSpan());
const int dest_pitch = pTransBitmap->GetPitch();
- pdfium::span<uint8_t> dest_span =
- pTransBitmap->GetBuffer().first(Fx2DSizeOrDie(dest_pitch, result_height));
+ pdfium::span<uint8_t> dest_span = pTransBitmap->GetWritableBuffer().first(
+ Fx2DSizeOrDie(dest_pitch, result_height));
const size_t dest_last_row_offset =
Fx2DSizeOrDie(dest_pitch, result_height - 1);
const int row_start = bXFlip ? m_Height - dest_clip.right : dest_clip.left;
@@ -1128,7 +1129,6 @@ bool CFX_DIBBase::ConvertBuffer(FXDIB_Format dest_format,
height, pSrcBitmap, src_left, src_top);
}
default:
- NOTREACHED();
- return false;
+ NOTREACHED_NORETURN();
}
}
diff --git a/core/fxge/dib/cfx_dibbase.h b/core/fxge/dib/cfx_dibbase.h
index 9f0deeb52..ebf1eacd8 100644
--- a/core/fxge/dib/cfx_dibbase.h
+++ b/core/fxge/dib/cfx_dibbase.h
@@ -12,7 +12,11 @@
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxge/dib/fx_dib.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
+
+#if defined(_SKIA_SUPPORT_)
+#include "third_party/skia/include/core/SkRefCnt.h" // nogncheck
+#endif
class CFX_ClipRgn;
class CFX_DIBitmap;
@@ -20,6 +24,10 @@ class CFX_Matrix;
class PauseIndicatorIface;
struct FX_RECT;
+#if defined(_SKIA_SUPPORT_)
+class SkImage;
+#endif // defined(_SKIA_SUPPORT_)
+
// Base class for all Device-Independent Bitmaps.
class CFX_DIBBase : public Retainable {
public:
@@ -32,17 +40,11 @@ class CFX_DIBBase : public Retainable {
static constexpr uint32_t kPaletteSize = 256;
- ~CFX_DIBBase() override;
-
- virtual pdfium::span<uint8_t> GetBuffer() const;
+ virtual pdfium::span<const uint8_t> GetBuffer() const;
virtual pdfium::span<const uint8_t> GetScanline(int line) const = 0;
virtual bool SkipToScanline(int line, PauseIndicatorIface* pPause) const;
virtual size_t GetEstimatedImageMemoryBurden() const;
- pdfium::span<uint8_t> GetWritableScanline(int line) {
- pdfium::span<const uint8_t> src = GetScanline(line);
- return {const_cast<uint8_t*>(src.data()), src.size()};
- }
int GetWidth() const { return m_Width; }
int GetHeight() const { return m_Height; }
uint32_t GetPitch() const { return m_Pitch; }
@@ -87,8 +89,17 @@ class CFX_DIBBase : public Retainable {
int& src_top,
const CFX_ClipRgn* pClipRgn) const;
+#if defined(_SKIA_SUPPORT_)
+ // Realizes an `SkImage` from this DIB.
+ //
+ // This may share the underlying pixels, in which case, this DIB should not be
+ // modified during the lifetime of the `SkImage`.
+ virtual sk_sp<SkImage> RealizeSkImage() const;
+#endif // defined(_SKIA_SUPPORT_)
+
protected:
CFX_DIBBase();
+ ~CFX_DIBBase() override;
static bool ConvertBuffer(FXDIB_Format dest_format,
pdfium::span<uint8_t> dest_buf,
@@ -100,6 +111,11 @@ class CFX_DIBBase : public Retainable {
int src_top,
DataVector<uint32_t>* pal);
+#if defined(_SKIA_SUPPORT_)
+ // Whether alpha is premultiplied (if `IsAlphaFormat()`).
+ virtual bool IsPremultiplied() const;
+#endif // defined(_SKIA_SUPPORT_)
+
RetainPtr<CFX_DIBitmap> ClipToInternal(const FX_RECT* pClip) const;
void BuildPalette();
int FindPalette(uint32_t color) const;
diff --git a/core/fxge/dib/cfx_dibextractor.cpp b/core/fxge/dib/cfx_dibextractor.cpp
deleted file mode 100644
index 9dcfbec52..000000000
--- a/core/fxge/dib/cfx_dibextractor.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2017 The PDFium Authors
-// Use of this source code is governed by 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_dibbase.h"
-#include "core/fxge/dib/cfx_dibitmap.h"
-
-CFX_DIBExtractor::CFX_DIBExtractor(const RetainPtr<CFX_DIBBase>& pSrc) {
- if (pSrc->GetBuffer().empty()) {
- m_pBitmap = pSrc->Realize();
- return;
- }
- m_pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
- if (!m_pBitmap->Create(pSrc->GetWidth(), pSrc->GetHeight(), pSrc->GetFormat(),
- pSrc->GetBuffer().data(),
- /*pitch=*/0)) {
- m_pBitmap.Reset();
- return;
- }
-
- m_pBitmap->SetPalette(pSrc->GetPaletteSpan());
-}
-
-CFX_DIBExtractor::~CFX_DIBExtractor() = default;
diff --git a/core/fxge/dib/cfx_dibextractor.h b/core/fxge/dib/cfx_dibextractor.h
deleted file mode 100644
index 455eca144..000000000
--- a/core/fxge/dib/cfx_dibextractor.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2017 The PDFium Authors
-// Use of this source code is governed by 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"
-
-class CFX_DIBBase;
-class CFX_DIBitmap;
-
-class CFX_DIBExtractor {
- public:
- explicit CFX_DIBExtractor(const RetainPtr<CFX_DIBBase>& pSrc);
- ~CFX_DIBExtractor();
-
- RetainPtr<CFX_DIBitmap> GetBitmap() { return m_pBitmap; }
-
- private:
- RetainPtr<CFX_DIBitmap> 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
index 62881a629..6df1eee1e 100644
--- a/core/fxge/dib/cfx_dibitmap.cpp
+++ b/core/fxge/dib/cfx_dibitmap.cpp
@@ -85,9 +85,9 @@ bool CFX_DIBitmap::Copy(const RetainPtr<CFX_DIBBase>& pSrc) {
CFX_DIBitmap::~CFX_DIBitmap() = default;
-pdfium::span<uint8_t> CFX_DIBitmap::GetBuffer() const {
+pdfium::span<const uint8_t> CFX_DIBitmap::GetBuffer() const {
if (!m_pBuffer)
- return pdfium::span<uint8_t>();
+ return pdfium::span<const uint8_t>();
return {m_pBuffer.Get(), m_Height * m_Pitch};
}
@@ -237,7 +237,7 @@ bool CFX_DIBitmap::TransferWithUnequalFormats(
if (!offset.IsValid())
return false;
- pdfium::span<uint8_t> dest_buf = GetBuffer().subspan(
+ pdfium::span<uint8_t> dest_buf = GetWritableBuffer().subspan(
dest_top * m_Pitch + static_cast<uint32_t>(offset.ValueOrDie()));
DataVector<uint32_t> d_plt;
return ConvertBuffer(dest_format, dest_buf, m_Pitch, width, height,
@@ -389,11 +389,9 @@ bool CFX_DIBitmap::SetUniformOpaqueAlpha() {
}
bool CFX_DIBitmap::MultiplyAlpha(const RetainPtr<CFX_DIBBase>& pSrcBitmap) {
- if (!m_pBuffer)
- return false;
+ CHECK(pSrcBitmap->IsMaskFormat());
- if (!pSrcBitmap->IsMaskFormat()) {
- NOTREACHED();
+ if (!m_pBuffer) {
return false;
}
@@ -698,11 +696,8 @@ bool CFX_DIBitmap::CompositeBitmap(int dest_left,
BlendMode blend_type,
const CFX_ClipRgn* pClipRgn,
bool bRgbByteOrder) {
- if (pSrcBitmap->IsMaskFormat()) {
- // Should have called CompositeMask().
- NOTREACHED();
- return false;
- }
+ // Should have called CompositeMask().
+ CHECK(!pSrcBitmap->IsMaskFormat());
if (!m_pBuffer)
return false;
@@ -765,11 +760,8 @@ bool CFX_DIBitmap::CompositeMask(int dest_left,
BlendMode blend_type,
const CFX_ClipRgn* pClipRgn,
bool bRgbByteOrder) {
- if (!pMask->IsMaskFormat()) {
- // Should have called CompositeBitmap().
- NOTREACHED();
- return false;
- }
+ // Should have called CompositeBitmap().
+ CHECK(pMask->IsMaskFormat());
if (!m_pBuffer)
return false;
@@ -926,11 +918,7 @@ bool CFX_DIBitmap::CompositeRect(int left,
return true;
}
- if (GetBppFromFormat(m_Format) < 24) {
- NOTREACHED();
- return false;
- }
-
+ CHECK_GE(GetBppFromFormat(m_Format), 24);
color_p[3] = static_cast<uint8_t>(src_alpha);
int Bpp = GetBppFromFormat(m_Format) / 8;
const bool bAlpha = IsAlphaFormat();
diff --git a/core/fxge/dib/cfx_dibitmap.h b/core/fxge/dib/cfx_dibitmap.h
index 58171554d..34f588722 100644
--- a/core/fxge/dib/cfx_dibitmap.h
+++ b/core/fxge/dib/cfx_dibitmap.h
@@ -13,6 +13,7 @@
#include "core/fxge/dib/cfx_dibbase.h"
#include "core/fxge/dib/fx_dib.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/base/containers/span.h"
class CFX_DIBitmap final : public CFX_DIBBase {
public:
@@ -33,10 +34,20 @@ class CFX_DIBitmap final : public CFX_DIBBase {
bool Copy(const RetainPtr<CFX_DIBBase>& pSrc);
// CFX_DIBBase
- pdfium::span<uint8_t> GetBuffer() const override;
+ pdfium::span<const uint8_t> GetBuffer() const override;
pdfium::span<const uint8_t> GetScanline(int line) const override;
size_t GetEstimatedImageMemoryBurden() const override;
+ pdfium::span<uint8_t> GetWritableBuffer() {
+ pdfium::span<const uint8_t> src = GetBuffer();
+ return {const_cast<uint8_t*>(src.data()), src.size()};
+ }
+
+ pdfium::span<uint8_t> GetWritableScanline(int line) {
+ pdfium::span<const uint8_t> src = GetScanline(line);
+ return {const_cast<uint8_t*>(src.data()), src.size()};
+ }
+
void TakeOver(RetainPtr<CFX_DIBitmap>&& pSrcBitmap);
bool ConvertFormat(FXDIB_Format format);
void Clear(uint32_t color);
@@ -114,21 +125,19 @@ class CFX_DIBitmap final : public CFX_DIBBase {
uint32_t pitch);
#if defined(_SKIA_SUPPORT_)
- // Converts to pre-multiplied alpha if necessary.
- void PreMultiply();
-
// Converts to un-pre-multiplied alpha if necessary.
void UnPreMultiply();
// Forces pre-multiplied alpha without conversion.
// TODO(crbug.com/pdfium/2011): Remove the need for this.
void ForcePreMultiply();
-
- // Forces un-pre-multiplied alpha without conversion.
- // TODO(crbug.com/pdfium/2011): Remove the need for this.
- void ForceUnPreMultiply();
#endif
+ protected:
+#if defined(_SKIA_SUPPORT_)
+ bool IsPremultiplied() const override;
+#endif // defined(_SKIA_SUPPORT_)
+
private:
enum class Channel : uint8_t { kRed, kAlpha };
diff --git a/core/fxge/dib/cfx_dibitmap_unittest.cpp b/core/fxge/dib/cfx_dibitmap_unittest.cpp
index ce79a0180..ef448c238 100644
--- a/core/fxge/dib/cfx_dibitmap_unittest.cpp
+++ b/core/fxge/dib/cfx_dibitmap_unittest.cpp
@@ -10,7 +10,7 @@
#include "core/fxge/dib/fx_dib.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace {
@@ -114,16 +114,6 @@ TEST(CFX_DIBitmap, CalculatePitchAndSizeBoundary) {
}
#if defined(_SKIA_SUPPORT_)
-TEST(CFX_DIBitmap, PreMultiply_FromCleared) {
- auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
- ASSERT_TRUE(bitmap->Create(1, 1, FXDIB_Format::kArgb));
- FXARGB_SETDIB(bitmap->GetBuffer().data(), 0x7f'ff'ff'ff);
-
- bitmap->PreMultiply();
-
- EXPECT_THAT(bitmap->GetBuffer(), ElementsAre(0x7f, 0x7f, 0x7f, 0x7f));
-}
-
TEST(CFX_DIBitmap, UnPreMultiply_FromCleared) {
auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
ASSERT_TRUE(bitmap->Create(1, 1, FXDIB_Format::kArgb));
@@ -134,21 +124,10 @@ TEST(CFX_DIBitmap, UnPreMultiply_FromCleared) {
EXPECT_THAT(bitmap->GetBuffer(), ElementsAre(0xff, 0xff, 0xff, 0x7f));
}
-TEST(CFX_DIBitmap, PreMultiply_FromPreMultiplied) {
- auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
- ASSERT_TRUE(bitmap->Create(1, 1, FXDIB_Format::kArgb));
- bitmap->PreMultiply();
- FXARGB_SETDIB(bitmap->GetBuffer().data(), 0x7f'7f'7f'7f);
-
- bitmap->PreMultiply();
-
- EXPECT_THAT(bitmap->GetBuffer(), ElementsAre(0x7f, 0x7f, 0x7f, 0x7f));
-}
-
TEST(CFX_DIBitmap, UnPreMultiply_FromPreMultiplied) {
auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
ASSERT_TRUE(bitmap->Create(1, 1, FXDIB_Format::kArgb));
- bitmap->PreMultiply();
+ bitmap->ForcePreMultiply();
FXARGB_SETDIB(bitmap->GetBuffer().data(), 0x7f'7f'7f'7f);
bitmap->UnPreMultiply();
@@ -156,17 +135,6 @@ TEST(CFX_DIBitmap, UnPreMultiply_FromPreMultiplied) {
EXPECT_THAT(bitmap->GetBuffer(), ElementsAre(0xff, 0xff, 0xff, 0x7f));
}
-TEST(CFX_DIBitmap, PreMultiply_FromUnPreMultiplied) {
- auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
- ASSERT_TRUE(bitmap->Create(1, 1, FXDIB_Format::kArgb));
- bitmap->UnPreMultiply();
- FXARGB_SETDIB(bitmap->GetBuffer().data(), 0x7f'ff'ff'ff);
-
- bitmap->PreMultiply();
-
- EXPECT_THAT(bitmap->GetBuffer(), ElementsAre(0x7f, 0x7f, 0x7f, 0x7f));
-}
-
TEST(CFX_DIBitmap, UnPreMultiply_FromUnPreMultiplied) {
auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
ASSERT_TRUE(bitmap->Create(1, 1, FXDIB_Format::kArgb));
@@ -177,26 +145,4 @@ TEST(CFX_DIBitmap, UnPreMultiply_FromUnPreMultiplied) {
EXPECT_THAT(bitmap->GetBuffer(), ElementsAre(0xff, 0xff, 0xff, 0x7f));
}
-
-TEST(CFX_DIBitmap, ForcePreMultiply) {
- auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
- ASSERT_TRUE(bitmap->Create(1, 1, FXDIB_Format::kArgb));
- FXARGB_SETDIB(bitmap->GetBuffer().data(), 0x7f'7f'7f'7f);
-
- bitmap->ForcePreMultiply();
-
- bitmap->PreMultiply();
- EXPECT_THAT(bitmap->GetBuffer(), ElementsAre(0x7f, 0x7f, 0x7f, 0x7f));
-}
-
-TEST(CFX_DIBitmap, ForceUnPreMultiply) {
- auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
- ASSERT_TRUE(bitmap->Create(1, 1, FXDIB_Format::kArgb));
- FXARGB_SETDIB(bitmap->GetBuffer().data(), 0x7f'ff'ff'ff);
-
- bitmap->ForceUnPreMultiply();
-
- bitmap->UnPreMultiply();
- EXPECT_THAT(bitmap->GetBuffer(), ElementsAre(0xff, 0xff, 0xff, 0x7f));
-}
#endif // defined(_SKIA_SUPPORT_)
diff --git a/core/fxge/dib/cfx_imagestretcher.cpp b/core/fxge/dib/cfx_imagestretcher.cpp
index f9b828a9e..1eafa408b 100644
--- a/core/fxge/dib/cfx_imagestretcher.cpp
+++ b/core/fxge/dib/cfx_imagestretcher.cpp
@@ -13,7 +13,7 @@
#include "core/fxge/dib/fx_dib.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace {
diff --git a/core/fxge/dib/cfx_imagetransformer.cpp b/core/fxge/dib/cfx_imagetransformer.cpp
index 904a7f526..12bc14da4 100644
--- a/core/fxge/dib/cfx_imagetransformer.cpp
+++ b/core/fxge/dib/cfx_imagetransformer.cpp
@@ -157,7 +157,7 @@ CFX_ImageTransformer::CFX_ImageTransformer(
&m_Storer, m_pSrc, dest_height, dest_width, result_clip,
m_ResampleOptions);
m_Stretcher->Start();
- m_type = kRotate;
+ m_type = StretchType::kRotate;
return;
}
if (fabs(m_matrix.b) < kFix16 && fabs(m_matrix.c) < kFix16) {
@@ -170,7 +170,7 @@ CFX_ImageTransformer::CFX_ImageTransformer(
&m_Storer, m_pSrc, dest_width, dest_height, result_clip,
m_ResampleOptions);
m_Stretcher->Start();
- m_type = kNormal;
+ m_type = StretchType::kNormal;
return;
}
@@ -200,32 +200,32 @@ CFX_ImageTransformer::CFX_ImageTransformer(
&m_Storer, m_pSrc, stretch_width, stretch_height, m_StretchClip,
m_ResampleOptions);
m_Stretcher->Start();
- m_type = kOther;
+ m_type = StretchType::kOther;
}
CFX_ImageTransformer::~CFX_ImageTransformer() = default;
bool CFX_ImageTransformer::Continue(PauseIndicatorIface* pPause) {
- if (m_type == kNone)
+ if (m_type == StretchType::kNone) {
return false;
+ }
if (m_Stretcher->Continue(pPause))
return true;
switch (m_type) {
- case kNormal:
- break;
- case kRotate:
+ case StretchType::kNone:
+ // Already handled separately at the beginning of this method.
+ NOTREACHED_NORETURN();
+ case StretchType::kNormal:
+ return false;
+ case StretchType::kRotate:
ContinueRotate(pPause);
- break;
- case kOther:
+ return false;
+ case StretchType::kOther:
ContinueOther(pPause);
- break;
- default:
- NOTREACHED();
- break;
+ return false;
}
- return false;
}
void CFX_ImageTransformer::ContinueRotate(PauseIndicatorIface* pPause) {
diff --git a/core/fxge/dib/cfx_imagetransformer.h b/core/fxge/dib/cfx_imagetransformer.h
index abd60c477..2329e9b4c 100644
--- a/core/fxge/dib/cfx_imagetransformer.h
+++ b/core/fxge/dib/cfx_imagetransformer.h
@@ -11,6 +11,7 @@
#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/retain_ptr.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
#include "core/fxge/dib/cfx_bitmapstorer.h"
class CFX_DIBBase;
@@ -32,7 +33,7 @@ class CFX_ImageTransformer {
};
struct CalcData {
- CFX_DIBitmap* bitmap;
+ UNOWNED_PTR_EXCLUSION CFX_DIBitmap* bitmap; // POD struct.
const CFX_Matrix& matrix;
const uint8_t* buf;
uint32_t pitch;
@@ -50,7 +51,7 @@ class CFX_ImageTransformer {
RetainPtr<CFX_DIBitmap> DetachBitmap();
private:
- enum StretchType {
+ enum class StretchType {
kNone,
kNormal,
kRotate,
@@ -72,7 +73,7 @@ class CFX_ImageTransformer {
std::unique_ptr<CFX_ImageStretcher> m_Stretcher;
CFX_BitmapStorer m_Storer;
const FXDIB_ResampleOptions m_ResampleOptions;
- StretchType m_type = kNone;
+ StretchType m_type = StretchType::kNone;
};
#endif // CORE_FXGE_DIB_CFX_IMAGETRANSFORMER_H_
diff --git a/core/fxge/dib/cfx_scanlinecompositor.h b/core/fxge/dib/cfx_scanlinecompositor.h
index 9fa6a8691..c7e95fd3e 100644
--- a/core/fxge/dib/cfx_scanlinecompositor.h
+++ b/core/fxge/dib/cfx_scanlinecompositor.h
@@ -11,7 +11,7 @@
#include "core/fxcrt/fx_memory_wrappers.h"
#include "core/fxge/dib/fx_dib.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_ScanlineCompositor {
public:
diff --git a/core/fxge/dib/cstretchengine.cpp b/core/fxge/dib/cstretchengine.cpp
index e9629fc82..920645ab9 100644
--- a/core/fxge/dib/cstretchengine.cpp
+++ b/core/fxge/dib/cstretchengine.cpp
@@ -21,7 +21,6 @@
#include "core/fxge/dib/fx_dib.h"
#include "core/fxge/dib/scanlinecomposer_iface.h"
#include "third_party/base/check.h"
-#include "third_party/base/cxx17_backports.h"
static_assert(
std::is_trivially_destructible<CStretchEngine::PixelWeight>::value,
@@ -500,9 +499,9 @@ void CStretchEngine::StretchVert() {
int r = static_cast<uint32_t>(dest_r) * 255 / dest_a;
int g = static_cast<uint32_t>(dest_g) * 255 / dest_a;
int b = static_cast<uint32_t>(dest_b) * 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);
+ dest_scan[0] = std::clamp(b, 0, 255);
+ dest_scan[1] = std::clamp(g, 0, 255);
+ dest_scan[2] = std::clamp(r, 0, 255);
}
dest_scan[3] = PixelFromFixed(dest_a);
dest_scan += DestBpp;
diff --git a/core/fxge/dib/cstretchengine.h b/core/fxge/dib/cstretchengine.h
index 2ee14774a..4f0d71f2d 100644
--- a/core/fxge/dib/cstretchengine.h
+++ b/core/fxge/dib/cstretchengine.h
@@ -17,7 +17,7 @@
#include "core/fxcrt/unowned_ptr.h"
#include "core/fxge/dib/fx_dib.h"
#include "third_party/base/check_op.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_DIBBase;
class PauseIndicatorIface;
diff --git a/core/fxge/dib/scanlinecomposer_iface.h b/core/fxge/dib/scanlinecomposer_iface.h
index 57baf9b77..ef997cf97 100644
--- a/core/fxge/dib/scanlinecomposer_iface.h
+++ b/core/fxge/dib/scanlinecomposer_iface.h
@@ -8,7 +8,7 @@
#define CORE_FXGE_DIB_SCANLINECOMPOSER_IFACE_H_
#include "core/fxge/dib/fx_dib.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class ScanlineComposerIface {
public:
diff --git a/core/fxge/freetype/fx_freetype.cpp b/core/fxge/freetype/fx_freetype.cpp
index 1c3deeebe..effd16023 100644
--- a/core/fxge/freetype/fx_freetype.cpp
+++ b/core/fxge/freetype/fx_freetype.cpp
@@ -8,6 +8,9 @@
#include <stdint.h>
+#include "core/fxge/cfx_fontmgr.h"
+#include "core/fxge/cfx_gemodule.h"
+
#define DEFINE_PS_TABLES
#include "third_party/freetype/include/pstables.h"
@@ -57,8 +60,36 @@ int xyq_search_node(char* glyph_name,
return 0;
}
+FT_MM_Var* GetVariationDescriptor(FXFT_FaceRec* face) {
+ FT_MM_Var* variation_desc = nullptr;
+ FT_Get_MM_Var(face, &variation_desc);
+ return variation_desc;
+}
+
} // namespace
+void FXFTMMVarDeleter::operator()(FT_MM_Var* variation_desc) {
+ FT_Done_MM_Var(CFX_GEModule::Get()->GetFontMgr()->GetFTLibrary(),
+ variation_desc);
+}
+
+ScopedFXFTMMVar::ScopedFXFTMMVar(FXFT_FaceRec* face)
+ : variation_desc_(GetVariationDescriptor(face)) {}
+
+ScopedFXFTMMVar::~ScopedFXFTMMVar() = default;
+
+FT_Pos ScopedFXFTMMVar::GetAxisDefault(size_t index) const {
+ return variation_desc_->axis[index].def;
+}
+
+FT_Long ScopedFXFTMMVar::GetAxisMin(size_t index) const {
+ return variation_desc_->axis[index].minimum;
+}
+
+FT_Long ScopedFXFTMMVar::GetAxisMax(size_t index) const {
+ return variation_desc_->axis[index].maximum;
+}
+
int FXFT_unicode_from_adobe_name(const char* glyph_name) {
/* If the name begins with `uni', then the glyph name may be a */
/* hard-coded unicode character code. */
diff --git a/core/fxge/freetype/fx_freetype.h b/core/fxge/freetype/fx_freetype.h
index 3da0372ef..96c3d2fe2 100644
--- a/core/fxge/freetype/fx_freetype.h
+++ b/core/fxge/freetype/fx_freetype.h
@@ -21,7 +21,6 @@
using FXFT_LibraryRec = struct FT_LibraryRec_;
using FXFT_FaceRec = struct FT_FaceRec_;
using FXFT_StreamRec = struct FT_StreamRec_;
-using FXFT_MM_VarPtr = FT_MM_Var*;
struct FXFTFaceRecDeleter {
inline void operator()(FXFT_FaceRec* pRec) { FT_Done_Face(pRec); }
@@ -31,10 +30,29 @@ struct FXFTLibraryRecDeleter {
inline void operator()(FXFT_LibraryRec* pRec) { FT_Done_FreeType(pRec); }
};
+struct FXFTMMVarDeleter {
+ void operator()(FT_MM_Var* variation_desc);
+};
+
using ScopedFXFTFaceRec = std::unique_ptr<FXFT_FaceRec, FXFTFaceRecDeleter>;
using ScopedFXFTLibraryRec =
std::unique_ptr<FXFT_LibraryRec, FXFTLibraryRecDeleter>;
+class ScopedFXFTMMVar {
+ public:
+ explicit ScopedFXFTMMVar(FXFT_FaceRec* face);
+ ~ScopedFXFTMMVar();
+
+ explicit operator bool() const { return !!variation_desc_; }
+
+ FT_Pos GetAxisDefault(size_t index) const;
+ FT_Long GetAxisMin(size_t index) const;
+ FT_Long GetAxisMax(size_t index) const;
+
+ private:
+ std::unique_ptr<FT_MM_Var, FXFTMMVarDeleter> const variation_desc_;
+};
+
#define FXFT_Select_Charmap(face, encoding) \
FT_Select_Charmap(face, static_cast<FT_Encoding>(encoding))
#define FXFT_Render_Glyph(face, mode) \
@@ -72,11 +90,6 @@ using ScopedFXFTLibraryRec =
#define FXFT_Get_Face_Ascender(face) (face)->ascender
#define FXFT_Get_Face_Descender(face) (face)->descender
#define FXFT_Get_Glyph_HoriAdvance(face) (face)->glyph->metrics.horiAdvance
-#define FXFT_Get_MM_Axis(var, index) (var)->axis[index]
-#define FXFT_Get_MM_Axis_Min(axis) (axis).minimum
-#define FXFT_Get_MM_Axis_Max(axis) (axis).maximum
-#define FXFT_Get_MM_Axis_Def(axis) (axis).def
-#define FXFT_Free(face, p) (face)->memory->free((face)->memory, p)
#define FXFT_Get_Glyph_Outline(face) &((face)->glyph->outline)
#define FXFT_Get_Glyph_Bitmap(face) (face)->glyph->bitmap
#define FXFT_Get_Bitmap_Width(bitmap) (bitmap).width
diff --git a/core/fxge/fx_font.h b/core/fxge/fx_font.h
index 60a27ed7a..7770f7fe7 100644
--- a/core/fxge/fx_font.h
+++ b/core/fxge/fx_font.h
@@ -11,7 +11,7 @@
#include "core/fxcrt/bytestring.h"
#include "core/fxcrt/fx_coordinates.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
/* Font pitch and family flags */
#define FXFONT_FF_FIXEDPITCH (1 << 0)
diff --git a/core/fxge/renderdevicedriver_iface.h b/core/fxge/renderdevicedriver_iface.h
index a25eca38e..09dd93cc0 100644
--- a/core/fxge/renderdevicedriver_iface.h
+++ b/core/fxge/renderdevicedriver_iface.h
@@ -14,7 +14,7 @@
#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxge/dib/fx_dib.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_DIBBase;
class CFX_DIBitmap;
diff --git a/core/fxge/skia/DEPS b/core/fxge/skia/DEPS
index 17c026539..9927648c3 100644
--- a/core/fxge/skia/DEPS
+++ b/core/fxge/skia/DEPS
@@ -1,5 +1,9 @@
include_rules = [
- '+fpdfsdk',
- '+public',
'+third_party/skia/include',
]
+
+specific_include_rules = {
+ 'fx_skia_device_embeddertest.cpp': [
+ '+fpdfsdk',
+ ]
+}
diff --git a/core/fxge/skia/cfx_dibbase_skia.cpp b/core/fxge/skia/cfx_dibbase_skia.cpp
new file mode 100644
index 000000000..417aa93b6
--- /dev/null
+++ b/core/fxge/skia/cfx_dibbase_skia.cpp
@@ -0,0 +1,288 @@
+// Copyright 2023 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/fxge/dib/cfx_dibbase.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+#include "core/fxcrt/fx_2d_size.h"
+#include "core/fxcrt/fx_memory.h"
+#include "core/fxcrt/fx_memory_wrappers.h"
+#include "core/fxcrt/fx_safe_types.h"
+#include "core/fxcrt/retain_ptr.h"
+#include "core/fxge/calculate_pitch.h"
+#include "core/fxge/dib/cfx_dibitmap.h"
+#include "core/fxge/dib/fx_dib.h"
+#include "third_party/base/check_op.h"
+#include "third_party/base/containers/span.h"
+#include "third_party/base/notreached.h"
+#include "third_party/skia/include/core/SkAlphaType.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkColorPriv.h"
+#include "third_party/skia/include/core/SkColorType.h"
+#include "third_party/skia/include/core/SkImage.h"
+#include "third_party/skia/include/core/SkImageInfo.h"
+#include "third_party/skia/include/core/SkPixmap.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
+
+namespace {
+
+// Releases `CFX_DIBBase` "leaked" by `CreateSkiaImageFromDib()`.
+void ReleaseRetainedHeldBySkImage(const void* /*pixels*/,
+ SkImages::ReleaseContext context) {
+ RetainPtr<const CFX_DIBBase> retained;
+ retained.Unleak(reinterpret_cast<const CFX_DIBBase*>(context));
+}
+
+// Creates an `SkImage` from a `CFX_DIBBase`, sharing the underlying pixels if
+// possible.
+//
+// Note that an `SkImage` must be immutable, so if sharing pixels, they must not
+// be modified during the lifetime of the `SkImage`.
+sk_sp<SkImage> CreateSkiaImageFromDib(const CFX_DIBBase* source,
+ SkColorType color_type,
+ SkAlphaType alpha_type) {
+ // Make sure the DIB is backed by a buffer.
+ RetainPtr<const CFX_DIBBase> retained;
+ if (source->GetBuffer().empty()) {
+ retained = source->Realize();
+ if (!retained) {
+ return nullptr;
+ }
+ DCHECK(!retained->GetBuffer().empty());
+ } else {
+ retained.Reset(source);
+ }
+
+ // Convert unowned pointer to a retained pointer, then "leak" to `SkImage`.
+ source = retained.Leak();
+ SkImageInfo info = SkImageInfo::Make(source->GetWidth(), source->GetHeight(),
+ color_type, alpha_type);
+ return SkImages::RasterFromPixmap(
+ SkPixmap(info, source->GetBuffer().data(), source->GetPitch()),
+ /*rasterReleaseProc=*/ReleaseRetainedHeldBySkImage,
+ /*releaseContext=*/const_cast<CFX_DIBBase*>(source));
+}
+
+// Releases allocated memory "leaked" by `CreateSkiaImageFromTransformedDib()`.
+void ReleaseAllocatedHeldBySkImage(const void* pixels,
+ SkImages::ReleaseContext /*context*/) {
+ FX_Free(const_cast<void*>(pixels));
+}
+
+// Template defining traits of a pixel transform function.
+template <size_t source_bits_per_pixel, typename PixelTransform>
+class PixelTransformTraits;
+
+template <typename PixelTransform>
+class PixelTransformTraits<1, PixelTransform> {
+ public:
+ using Result = std::invoke_result_t<PixelTransform, bool>;
+
+ static Result Invoke(PixelTransform&& pixel_transform,
+ const uint8_t* scanline,
+ size_t column) {
+ uint8_t kMask = 1 << (7 - column % 8);
+ return pixel_transform(!!(scanline[column / 8] & kMask));
+ }
+};
+
+template <typename PixelTransform>
+class PixelTransformTraits<8, PixelTransform> {
+ public:
+ using Result = std::invoke_result_t<PixelTransform, uint8_t>;
+
+ static Result Invoke(PixelTransform&& pixel_transform,
+ const uint8_t* scanline,
+ size_t column) {
+ return pixel_transform(scanline[column]);
+ }
+};
+
+template <typename PixelTransform>
+class PixelTransformTraits<24, PixelTransform> {
+ public:
+ using Result =
+ std::invoke_result_t<PixelTransform, uint8_t, uint8_t, uint8_t>;
+
+ static Result Invoke(PixelTransform&& pixel_transform,
+ const uint8_t* scanline,
+ size_t column) {
+ size_t offset = column * 3;
+ return pixel_transform(scanline[offset + 2], scanline[offset + 1],
+ scanline[offset]);
+ }
+};
+
+void ValidateScanlineSize(pdfium::span<const uint8_t> scanline,
+ size_t min_row_bytes) {
+ DCHECK_GE(scanline.size(), min_row_bytes);
+}
+
+void ValidateBufferSize(pdfium::span<const uint8_t> buffer,
+ const CFX_DIBBase& source) {
+#if DCHECK_IS_ON()
+ if (source.GetHeight() == 0) {
+ return;
+ }
+
+ FX_SAFE_SIZE_T buffer_size = source.GetHeight() - 1;
+ buffer_size *= source.GetPitch();
+ buffer_size += fxge::CalculatePitch8OrDie(source.GetBPP(), /*components=*/1,
+ source.GetWidth());
+
+ DCHECK_GE(buffer.size(), buffer_size.ValueOrDie());
+#endif // DCHECK_IS_ON()
+}
+
+// Creates an `SkImage` from a `CFX_DIBBase`, transforming the source pixels
+// using `pixel_transform`.
+//
+// TODO(crbug.com/pdfium/2048): Consolidate with `CFX_DIBBase::ConvertBuffer()`.
+template <size_t source_bits_per_pixel, typename PixelTransform>
+sk_sp<SkImage> CreateSkiaImageFromTransformedDib(
+ const CFX_DIBBase& source,
+ SkColorType color_type,
+ SkAlphaType alpha_type,
+ PixelTransform&& pixel_transform) {
+ using Traits = PixelTransformTraits<source_bits_per_pixel, PixelTransform>;
+ using Result = typename Traits::Result;
+
+ // Allocate output buffer.
+ const int width = source.GetWidth();
+ const int height = source.GetHeight();
+ SkImageInfo info = SkImageInfo::Make(width, height, color_type, alpha_type);
+ DCHECK_EQ(info.minRowBytes(), width * sizeof(Result));
+
+ size_t output_size = Fx2DSizeOrDie(info.minRowBytes(), height);
+ std::unique_ptr<void, FxFreeDeleter> output(
+ FX_TryAlloc(uint8_t, output_size));
+ if (!output) {
+ return nullptr;
+ }
+
+ // Transform source pixels to output pixels.
+ pdfium::span<const uint8_t> source_buffer = source.GetBuffer();
+ Result* output_cursor = reinterpret_cast<Result*>(output.get());
+ if (source_buffer.empty()) {
+ // No buffer; iterate by individual scanline.
+ const size_t min_row_bytes =
+ fxge::CalculatePitch8OrDie(source.GetBPP(), /*components=*/1, width);
+ DCHECK_LE(min_row_bytes, source.GetPitch());
+
+ int line = 0;
+ for (int row = 0; row < height; ++row) {
+ pdfium::span<const uint8_t> scanline = source.GetScanline(line++);
+ ValidateScanlineSize(scanline, min_row_bytes);
+
+ for (int column = 0; column < width; ++column) {
+ *output_cursor++ =
+ Traits::Invoke(std::forward<PixelTransform>(pixel_transform),
+ scanline.data(), column);
+ }
+ }
+ } else {
+ // Iterate over the entire buffer.
+ ValidateBufferSize(source_buffer, source);
+ const size_t row_bytes = source.GetPitch();
+
+ const uint8_t* next_scanline = source_buffer.data();
+ for (int row = 0; row < height; ++row) {
+ const uint8_t* scanline = next_scanline;
+ next_scanline += row_bytes;
+
+ for (int column = 0; column < width; ++column) {
+ *output_cursor++ = Traits::Invoke(
+ std::forward<PixelTransform>(pixel_transform), scanline, column);
+ }
+ }
+ }
+
+ // "Leak" allocated memory to `SkImage`.
+ return SkImages::RasterFromPixmap(
+ SkPixmap(info, output.release(), info.minRowBytes()),
+ /*rasterReleaseProc=*/ReleaseAllocatedHeldBySkImage,
+ /*releaseContext=*/nullptr);
+}
+
+bool IsRGBColorGrayScale(uint32_t color) {
+ return FXARGB_R(color) == FXARGB_G(color) &&
+ FXARGB_R(color) == FXARGB_B(color);
+}
+
+} // namespace
+
+sk_sp<SkImage> CFX_DIBBase::RealizeSkImage() const {
+ switch (GetBPP()) {
+ case 1: {
+ // By default, the two colors for grayscale are 0xFF and 0x00 unless they
+ // are specified in the palette.
+ uint8_t color0 = 0x00;
+ uint8_t color1 = 0xFF;
+
+ if (GetFormat() == FXDIB_Format::k1bppRgb && HasPalette()) {
+ uint32_t palette_color0 = GetPaletteArgb(0);
+ uint32_t palette_color1 = GetPaletteArgb(1);
+ bool use_gray_colors = IsRGBColorGrayScale(palette_color0) &&
+ IsRGBColorGrayScale(palette_color1);
+ if (!use_gray_colors) {
+ return CreateSkiaImageFromTransformedDib</*source_bits_per_pixel=*/1>(
+ *this, kBGRA_8888_SkColorType, kPremul_SkAlphaType,
+ [palette_color0, palette_color1](bool bit) {
+ return bit ? palette_color1 : palette_color0;
+ });
+ }
+
+ color0 = FXARGB_R(palette_color0);
+ color1 = FXARGB_R(palette_color1);
+ }
+
+ return CreateSkiaImageFromTransformedDib</*source_bits_per_pixel=*/1>(
+ *this, IsMaskFormat() ? kAlpha_8_SkColorType : kGray_8_SkColorType,
+ kPremul_SkAlphaType,
+ [color0, color1](bool bit) { return bit ? color1 : color0; });
+ }
+
+ case 8:
+ // we upscale ctables to 32bit.
+ if (HasPalette()) {
+ return CreateSkiaImageFromTransformedDib</*source_bits_per_pixel=*/8>(
+ *this, kBGRA_8888_SkColorType, kPremul_SkAlphaType,
+ [palette = GetPaletteSpan().first(GetRequiredPaletteSize())](
+ uint8_t index) {
+ if (index >= palette.size()) {
+ index = 0;
+ }
+ return palette[index];
+ });
+ }
+ return CreateSkiaImageFromDib(
+ this, IsMaskFormat() ? kAlpha_8_SkColorType : kGray_8_SkColorType,
+ kPremul_SkAlphaType);
+
+ case 24:
+ return CreateSkiaImageFromTransformedDib</*source_bits_per_pixel=*/24>(
+ *this, kBGRA_8888_SkColorType, kOpaque_SkAlphaType,
+ [](uint8_t red, uint8_t green, uint8_t blue) {
+ return SkPackARGB32NoCheck(0xFF, red, green, blue);
+ });
+
+ case 32:
+ return CreateSkiaImageFromDib(
+ this, kBGRA_8888_SkColorType,
+ IsPremultiplied() ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
+
+ default:
+ NOTREACHED_NORETURN();
+ }
+}
+
+bool CFX_DIBBase::IsPremultiplied() const {
+ return false;
+}
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp
index ef3218d7f..6bff316e5 100644
--- a/core/fxge/skia/fx_skia_device.cpp
+++ b/core/fxge/skia/fx_skia_device.cpp
@@ -5,6 +5,7 @@
#include "core/fxge/skia/fx_skia_device.h"
#include <math.h>
+#include <stddef.h>
#include <stdint.h>
#include <algorithm>
@@ -28,9 +29,9 @@
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/fx_2d_size.h"
#include "core/fxcrt/fx_coordinates.h"
+#include "core/fxcrt/fx_memory.h"
#include "core/fxcrt/fx_system.h"
#include "core/fxcrt/stl_util.h"
-#include "core/fxge/calculate_pitch.h"
#include "core/fxge/cfx_defaultrenderdevice.h"
#include "core/fxge/cfx_fillrenderoptions.h"
#include "core/fxge/cfx_font.h"
@@ -46,11 +47,10 @@
#include "core/fxge/text_char_pos.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
+#include "third_party/base/containers/span.h"
+#include "third_party/base/memory/ptr_util.h"
#include "third_party/base/notreached.h"
#include "third_party/base/numerics/safe_conversions.h"
-#include "third_party/base/ptr_util.h"
-#include "third_party/base/span.h"
-#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkBlendMode.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkClipOp.h"
@@ -64,14 +64,16 @@
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkPathEffect.h"
#include "third_party/skia/include/core/SkPathUtils.h"
-#include "third_party/skia/include/core/SkPictureRecorder.h"
+#include "third_party/skia/include/core/SkPixmap.h"
#include "third_party/skia/include/core/SkRSXform.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkSamplingOptions.h"
#include "third_party/skia/include/core/SkShader.h"
#include "third_party/skia/include/core/SkStream.h"
+#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/core/SkTextBlob.h"
+#include "third_party/skia/include/core/SkTileMode.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "third_party/skia/include/effects/SkDashPathEffect.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
@@ -154,66 +156,6 @@ void DebugShowSkiaDrawRect(CFX_SkiaDeviceDriver* driver,
#endif // SHOW_SKIA_PATH
}
-bool IsRGBColorGrayScale(uint32_t color) {
- return FXARGB_R(color) == FXARGB_G(color) &&
- FXARGB_R(color) == FXARGB_B(color);
-}
-
-// Called by Upsample, return a 32 bit-per-pixel buffer filled with 2 colors
-// from a 1 bit-per-pixel source palette.
-DataVector<uint32_t> Fill32BppDestStorageWith1BppSource(
- const RetainPtr<CFX_DIBBase>& source) {
- DCHECK_EQ(1, source->GetBPP());
- int width = source->GetWidth();
- int height = source->GetHeight();
- void* buffer = source->GetBuffer().data();
- DCHECK(buffer);
-
- uint32_t color0 = source->GetPaletteArgb(0);
- uint32_t color1 = source->GetPaletteArgb(1);
- DataVector<uint32_t> dst32_storage(Fx2DSizeOrDie(width, height));
- pdfium::span<SkPMColor> dst32_pixels(dst32_storage);
-
- for (int y = 0; y < height; ++y) {
- const uint8_t* src_row =
- static_cast<const uint8_t*>(buffer) + y * source->GetPitch();
- pdfium::span<uint32_t> dst_row = dst32_pixels.subspan(y * width);
- for (int x = 0; x < width; ++x) {
- bool use_color1 = src_row[x / 8] & (1 << (7 - x % 8));
- dst_row[x] = use_color1 ? color1 : color0;
- }
- }
- return dst32_storage;
-}
-
-// Called by Upsample(), returns a 32 bit-per-pixel buffer filled with colors
-// from `palette`.
-DataVector<uint32_t> Fill32BppDestStorageWithPalette(
- const RetainPtr<CFX_DIBBase>& source,
- pdfium::span<const uint32_t> palette) {
- DCHECK_EQ(8, source->GetBPP());
- int width = source->GetWidth();
- int height = source->GetHeight();
- void* buffer = source->GetBuffer().data();
- DCHECK(buffer);
- DataVector<uint32_t> dst32_storage(Fx2DSizeOrDie(width, height));
- pdfium::span<SkPMColor> dst32_pixels(dst32_storage);
-
- for (int y = 0; y < height; ++y) {
- const uint8_t* src_row =
- static_cast<const uint8_t*>(buffer) + y * source->GetPitch();
- pdfium::span<uint32_t> dst_row = dst32_pixels.subspan(y * width);
- for (int x = 0; x < width; ++x) {
- unsigned index = src_row[x];
- if (index >= palette.size()) {
- index = 0;
- }
- dst_row[x] = palette[index];
- }
- }
- return dst32_storage;
-}
-
static void DebugValidate(const RetainPtr<CFX_DIBitmap>& bitmap,
const RetainPtr<CFX_DIBitmap>& device) {
if (bitmap) {
@@ -331,7 +273,6 @@ SkBlendMode GetSkiaBlendMode(BlendMode blend_type) {
case BlendMode::kLuminosity:
return SkBlendMode::kLuminosity;
case BlendMode::kNormal:
- default:
return SkBlendMode::kSrcOver;
}
}
@@ -668,104 +609,6 @@ void SetBitmapPaintForMerge(bool is_mask,
paint->setBlendMode(GetSkiaBlendMode(blend_type));
}
-bool Upsample(const RetainPtr<CFX_DIBBase>& pSource,
- DataVector<uint32_t>& dst32_storage,
- SkBitmap* skBitmap,
- bool forceAlpha) {
- void* buffer = pSource->GetBuffer().data();
- if (!buffer)
- return false;
- SkColorType colorType = forceAlpha || pSource->IsMaskFormat()
- ? SkColorType::kAlpha_8_SkColorType
- : SkColorType::kGray_8_SkColorType;
- SkAlphaType alphaType = kPremul_SkAlphaType;
- int width = pSource->GetWidth();
- int height = pSource->GetHeight();
- int rowBytes = pSource->GetPitch();
- switch (pSource->GetBPP()) {
- case 1: {
- // By default, the two colors for grayscale are 0xFF and 0x00 unless they
- // are specified in the palette.
- uint8_t color0 = 0x00;
- uint8_t color1 = 0xFF;
-
- if (pSource->GetFormat() == FXDIB_Format::k1bppRgb &&
- pSource->HasPalette()) {
- uint32_t palette_color0 = pSource->GetPaletteArgb(0);
- uint32_t palette_color1 = pSource->GetPaletteArgb(1);
- bool use_gray_colors = IsRGBColorGrayScale(palette_color0) &&
- IsRGBColorGrayScale(palette_color1);
- if (!use_gray_colors) {
- dst32_storage = Fill32BppDestStorageWith1BppSource(pSource);
- rowBytes = width * sizeof(uint32_t);
- colorType = kBGRA_8888_SkColorType;
- break;
- }
-
- color0 = FXARGB_R(palette_color0);
- color1 = FXARGB_R(palette_color1);
- }
-
- const int src_row_bytes = rowBytes; // Save original value.
- rowBytes = fxge::CalculatePitch32OrDie(/*bpp=*/8, width);
- dst32_storage = DataVector<uint32_t>(Fx2DSizeOrDie(rowBytes / 4, height));
- pdfium::span<uint8_t> dst8_pixels =
- pdfium::as_writable_bytes(pdfium::make_span(dst32_storage));
- for (int y = 0; y < height; ++y) {
- const uint8_t* src_row =
- static_cast<const uint8_t*>(buffer) + y * src_row_bytes;
- pdfium::span<uint8_t> dst_row = dst8_pixels.subspan(y * rowBytes);
- for (int x = 0; x < width; ++x)
- dst_row[x] = src_row[x >> 3] & (1 << (~x & 0x07)) ? color1 : color0;
- }
- break;
- }
- case 8:
- // we upscale ctables to 32bit.
- if (pSource->HasPalette()) {
- const size_t src_palette_size = pSource->GetRequiredPaletteSize();
- pdfium::span<const uint32_t> src_palette = pSource->GetPaletteSpan();
- CHECK_LE(src_palette_size, src_palette.size());
- if (src_palette_size < src_palette.size())
- src_palette = src_palette.first(src_palette_size);
-
- dst32_storage = Fill32BppDestStorageWithPalette(pSource, src_palette);
- rowBytes = width * sizeof(uint32_t);
- colorType = kBGRA_8888_SkColorType;
- }
- break;
- case 24: {
- dst32_storage = DataVector<uint32_t>(Fx2DSizeOrDie(width, height));
- pdfium::span<uint32_t> dst32_pixels(dst32_storage);
- for (int y = 0; y < height; ++y) {
- const uint8_t* srcRow =
- static_cast<const uint8_t*>(buffer) + y * rowBytes;
- pdfium::span<uint32_t> dst_row = dst32_pixels.subspan(y * width);
- for (int x = 0; x < width; ++x) {
- dst_row[x] = SkPackARGB32NoCheck(
- 0xFF, srcRow[x * 3 + 2], srcRow[x * 3 + 1], srcRow[x * 3 + 0]);
- }
- }
- rowBytes = width * sizeof(uint32_t);
- colorType = kBGRA_8888_SkColorType;
- alphaType = kOpaque_SkAlphaType;
- break;
- }
- case 32:
- colorType = kBGRA_8888_SkColorType;
- break;
- default:
- NOTREACHED();
- }
- if (!dst32_storage.empty()) {
- buffer = dst32_storage.data();
- }
- SkImageInfo imageInfo =
- SkImageInfo::Make(width, height, colorType, alphaType);
- skBitmap->installPixels(imageInfo, buffer, rowBytes);
- return true;
-}
-
// Makes a bitmap filled with a solid color for debugging with `SkPicture`.
RetainPtr<CFX_DIBitmap> MakeDebugBitmap(int width, int height, uint32_t color) {
auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
@@ -833,10 +676,8 @@ CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(
bool bGroupKnockout)
: m_pBitmap(std::move(pBitmap)),
m_pBackdropBitmap(pBackdropBitmap),
- m_pRecorder(nullptr),
m_bRgbByteOrder(bRgbByteOrder),
m_bGroupKnockout(bGroupKnockout) {
- SkBitmap skBitmap;
SkColorType color_type;
const int bpp = m_pBitmap->GetBPP();
if (bpp == 8) {
@@ -866,14 +707,13 @@ CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(
SkImageInfo imageInfo =
SkImageInfo::Make(m_pBitmap->GetWidth(), m_pBitmap->GetHeight(),
color_type, kPremul_SkAlphaType);
- skBitmap.installPixels(imageInfo, m_pBitmap->GetBuffer().data(),
- m_pBitmap->GetPitch());
- m_pCanvas = new SkCanvas(skBitmap);
+ surface_ = SkSurfaces::WrapPixels(
+ imageInfo, m_pBitmap->GetWritableBuffer().data(), m_pBitmap->GetPitch());
+ m_pCanvas = surface_->getCanvas();
}
-CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(SkPictureRecorder* recorder)
- : m_pRecorder(recorder), m_bGroupKnockout(false) {
- m_pCanvas = m_pRecorder->getRecordingCanvas();
+CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(SkCanvas* canvas)
+ : m_pCanvas(canvas), m_bGroupKnockout(false) {
int width = m_pCanvas->imageInfo().width();
int height = m_pCanvas->imageInfo().height();
DCHECK_EQ(kUnknown_SkColorType, m_pCanvas->imageInfo().colorType());
@@ -897,10 +737,6 @@ CFX_SkiaDeviceDriver::~CFX_SkiaDeviceDriver() {
height, m_pBitmap, /*src_left=*/0,
/*src_top=*/0);
}
-
- if (!m_pRecorder) {
- delete m_pCanvas;
- }
}
bool CFX_SkiaDeviceDriver::DrawDeviceText(
@@ -917,21 +753,6 @@ bool CFX_SkiaDeviceDriver::DrawDeviceText(
if (pFont->GetFontSpan().empty())
return false;
- // If a glyph's default width is no less than its width defined in the PDF,
- // draw the glyph with path since it can be scaled to avoid overlapping with
- // the adjacent glyphs (if there are any). Otherwise, use the device driver
- // to render the glyph without any adjustments.
- const CFX_SubstFont* subst_font = pFont->GetSubstFont();
- const int subst_font_weight =
- (subst_font && subst_font->IsBuiltInGenericFont()) ? subst_font->m_Weight
- : 0;
- for (const TextCharPos& cp : pCharPos) {
- const int glyph_width = pFont->GetGlyphWidth(
- cp.m_GlyphIndex, cp.m_FontCharWidth, subst_font_weight);
- if (cp.m_FontCharWidth <= glyph_width)
- return false;
- }
-
if (TryDrawText(pCharPos, pFont, mtObject2Device, font_size, color,
options)) {
return true;
@@ -1007,6 +828,8 @@ bool CFX_SkiaDeviceDriver::DrawDeviceText(
// TODO(crbug.com/pdfium/1999): Merge with `DrawDeviceText()` and refactor
// common logic.
+// TODO(crbug.com/pdfium/1774): Sometimes the thickness of the glyphs is not
+// ideal. Improve text rendering results regarding different font weight.
bool CFX_SkiaDeviceDriver::TryDrawText(pdfium::span<const TextCharPos> char_pos,
const CFX_Font* pFont,
const CFX_Matrix& matrix,
@@ -1091,13 +914,26 @@ bool CFX_SkiaDeviceDriver::TryDrawText(pdfium::span<const TextCharPos> char_pos,
glyphs.data(), glyphs.size() * sizeof(uint16_t), m_rsxform.data(), font,
SkTextEncoding::kGlyphID);
m_pCanvas->drawTextBlob(blob, 0, 0, skPaint);
- } else {
- const DataVector<SkPoint>& positions = m_charDetails.GetPositions();
- for (size_t i = 0; i < m_charDetails.Count(); ++i) {
- sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromText(
- &glyphs[i], sizeof(glyphs[i]), font, SkTextEncoding::kGlyphID);
- m_pCanvas->drawTextBlob(blob, positions[i].fX, positions[i].fY, skPaint);
+ return true;
+ }
+ const DataVector<SkPoint>& positions = m_charDetails.GetPositions();
+ const DataVector<uint32_t>& widths = m_charDetails.GetFontCharWidths();
+ for (size_t i = 0; i < m_charDetails.Count(); ++i) {
+ const uint32_t font_glyph_width =
+ pFont ? pFont->GetGlyphWidth(glyphs[i]) : 0;
+ const uint32_t pdf_glyph_width = widths[i];
+ if (pdf_glyph_width > 0 && font_glyph_width > 0) {
+ // Scale the glyph from its default width `pdf_glyph_width` to the
+ // targeted width `pdf_glyph_width`.
+ font.setScaleX(scaleX * SkIntToScalar(pdf_glyph_width) /
+ font_glyph_width);
+ } else {
+ font.setScaleX(scaleX);
}
+ auto blob =
+ SkTextBlob::MakeFromPosText(&glyphs[i], sizeof(uint16_t), &positions[i],
+ font, SkTextEncoding::kGlyphID);
+ m_pCanvas->drawTextBlob(blob, 0, 0, skPaint);
}
return true;
}
@@ -1115,22 +951,17 @@ bool CFX_SkiaDeviceDriver::MultiplyAlpha(float alpha) {
}
bool CFX_SkiaDeviceDriver::MultiplyAlpha(const RetainPtr<CFX_DIBBase>& mask) {
- if (!mask->IsMaskFormat()) {
- NOTREACHED();
- return false;
- }
+ CHECK(mask->IsMaskFormat());
- // Storage vector must outlive `skia_mask`.
- DataVector<uint32_t> dst32_storage;
- SkBitmap skia_mask;
- if (!Upsample(mask, dst32_storage, &skia_mask, /*forceAlpha=*/true)) {
+ sk_sp<SkImage> skia_mask = mask->RealizeSkImage();
+ if (!skia_mask) {
return false;
}
- skia_mask.setImmutable();
+ DCHECK_EQ(skia_mask->colorType(), kAlpha_8_SkColorType);
SkPaint paint;
paint.setBlendMode(SkBlendMode::kDstIn);
- m_pCanvas->drawImageRect(skia_mask.asImage(),
+ m_pCanvas->drawImageRect(skia_mask,
SkRect::Make(m_pCanvas->imageInfo().bounds()),
SkSamplingOptions(), &paint);
return true;
@@ -1156,8 +987,7 @@ int CFX_SkiaDeviceDriver::GetDeviceCaps(int caps_id) const {
FXRC_BLEND_MODE | FXRC_SOFT_CLIP | FXRC_ALPHA_OUTPUT |
FXRC_FILLSTROKE_PATH | FXRC_SHADING;
default:
- NOTREACHED();
- return 0;
+ NOTREACHED_NORETURN();
}
}
@@ -1518,35 +1348,28 @@ bool CFX_SkiaDeviceDriver::GetDIBits(const RetainPtr<CFX_DIBitmap>& pBitmap,
if (!m_pBitmap)
return true;
- uint8_t* srcBuffer = m_pBitmap->GetBuffer().data();
- if (!srcBuffer)
+ const uint8_t* input_buffer = m_pBitmap->GetBuffer().data();
+ if (!input_buffer) {
return true;
+ }
- int srcWidth = m_pBitmap->GetWidth();
- int srcHeight = m_pBitmap->GetHeight();
- size_t srcRowBytes = m_pBitmap->GetPitch();
- SkImageInfo srcImageInfo = SkImageInfo::Make(
- srcWidth, srcHeight, SkColorType::kN32_SkColorType, kPremul_SkAlphaType);
- SkBitmap skSrcBitmap;
- skSrcBitmap.installPixels(srcImageInfo, srcBuffer, srcRowBytes);
- skSrcBitmap.setImmutable();
-
- uint8_t* dstBuffer = pBitmap->GetBuffer().data();
- DCHECK(dstBuffer);
-
- int dstWidth = pBitmap->GetWidth();
- int dstHeight = pBitmap->GetHeight();
- size_t dstRowBytes = pBitmap->GetPitch();
- SkImageInfo dstImageInfo = SkImageInfo::Make(
- dstWidth, dstHeight, Get32BitSkColorType(m_bRgbByteOrder),
- kPremul_SkAlphaType);
- SkBitmap skDstBitmap;
- skDstBitmap.installPixels(dstImageInfo, dstBuffer, dstRowBytes);
-
- SkCanvas canvas(skDstBitmap);
- canvas.drawImageRect(skSrcBitmap.asImage(),
- SkRect::MakeXYWH(left, top, dstWidth, dstHeight),
- SkSamplingOptions(), /*paint=*/nullptr);
+ uint8_t* output_buffer = pBitmap->GetWritableBuffer().data();
+ DCHECK(output_buffer);
+
+ SkImageInfo input_info =
+ SkImageInfo::Make(m_pBitmap->GetWidth(), m_pBitmap->GetHeight(),
+ SkColorType::kN32_SkColorType, kPremul_SkAlphaType);
+ sk_sp<SkImage> input = SkImages::RasterFromPixmap(
+ SkPixmap(input_info, input_buffer, m_pBitmap->GetPitch()),
+ /*rasterReleaseProc=*/nullptr, /*releaseContext=*/nullptr);
+
+ SkImageInfo output_info = SkImageInfo::Make(
+ pBitmap->GetWidth(), pBitmap->GetHeight(),
+ Get32BitSkColorType(m_bRgbByteOrder), kPremul_SkAlphaType);
+ sk_sp<SkSurface> output =
+ SkSurfaces::WrapPixels(output_info, output_buffer, pBitmap->GetPitch());
+
+ output->getCanvas()->drawImage(input, left, top, SkSamplingOptions());
return true;
}
@@ -1620,41 +1443,16 @@ bool CFX_SkiaDeviceDriver::ContinueDIBits(CFX_ImageRenderer* handle,
return false;
}
-void CFX_DIBitmap::PreMultiply() {
- if (GetBPP() != 32)
- return;
-
- void* buffer = GetBuffer().data();
- if (!buffer)
- return;
-
- Format prior_format = m_nFormat;
- ForcePreMultiply();
- if (prior_format == Format::kPreMultiplied)
- return;
-
- int height = GetHeight();
- int width = GetWidth();
- int row_bytes = GetPitch();
- SkImageInfo unpremultiplied_info =
- SkImageInfo::Make(width, height, kN32_SkColorType, kUnpremul_SkAlphaType);
- SkPixmap unpremultiplied(unpremultiplied_info, buffer, row_bytes);
- SkImageInfo premultiplied_info =
- SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType);
- SkPixmap premultiplied(premultiplied_info, buffer, row_bytes);
- unpremultiplied.readPixels(premultiplied);
-}
-
void CFX_DIBitmap::UnPreMultiply() {
if (GetBPP() != 32)
return;
- void* buffer = GetBuffer().data();
+ void* buffer = GetWritableBuffer().data();
if (!buffer)
return;
Format prior_format = m_nFormat;
- ForceUnPreMultiply();
+ m_nFormat = Format::kUnPreMultiplied;
if (prior_format == Format::kUnPreMultiplied)
return;
@@ -1674,8 +1472,8 @@ void CFX_DIBitmap::ForcePreMultiply() {
m_nFormat = Format::kPreMultiplied;
}
-void CFX_DIBitmap::ForceUnPreMultiply() {
- m_nFormat = Format::kUnPreMultiplied;
+bool CFX_DIBitmap::IsPremultiplied() const {
+ return m_nFormat == Format::kPreMultiplied;
}
bool CFX_SkiaDeviceDriver::DrawBitsWithMask(
@@ -1685,17 +1483,19 @@ bool CFX_SkiaDeviceDriver::DrawBitsWithMask(
const CFX_Matrix& matrix,
BlendMode blend_type) {
DebugValidate(m_pBitmap, m_pBackdropBitmap);
- // Storage vectors must outlive `skBitmap` and `skMask`.
- DataVector<uint32_t> src32_storage;
- DataVector<uint32_t> mask32_storage;
- SkBitmap skBitmap;
- SkBitmap skMask;
- if (!Upsample(pSource, src32_storage, &skBitmap, /*forceAlpha=*/false)) {
+
+ sk_sp<SkImage> skia_source = pSource->RealizeSkImage();
+ if (!skia_source) {
return false;
}
- if (!Upsample(pMask, mask32_storage, &skMask, /*forceAlpha=*/true)) {
+
+ DCHECK(pMask->IsMaskFormat());
+ sk_sp<SkImage> skia_mask = pMask->RealizeSkImage();
+ if (!skia_mask) {
return false;
}
+ DCHECK_EQ(skia_mask->colorType(), kAlpha_8_SkColorType);
+
{
SkAutoCanvasRestore scoped_save_restore(m_pCanvas, /*doSave=*/true);
@@ -1707,17 +1507,17 @@ bool CFX_SkiaDeviceDriver::DrawBitsWithMask(
SkPaint paint;
SetBitmapPaintForMerge(pSource->IsMaskFormat(), !m_FillOptions.aliased_path,
0xFFFFFFFF, bitmap_alpha, blend_type, &paint);
- sk_sp<SkImage> skSrc = SkImages::RasterFromBitmap(skBitmap);
- sk_sp<SkShader> skSrcShader = skSrc->makeShader(
+ sk_sp<SkShader> source_shader = skia_source->makeShader(
SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions());
- sk_sp<SkImage> skMaskImage = SkImages::RasterFromBitmap(skMask);
- sk_sp<SkShader> skMaskShader = skMaskImage->makeShader(
+ sk_sp<SkShader> mask_shader = skia_mask->makeShader(
SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions());
- paint.setShader(
- SkShaders::Blend(SkBlendMode::kSrcIn, skMaskShader, skSrcShader));
- SkRect r = {0, 0, SkIntToScalar(src_width), SkIntToScalar(src_height)};
- m_pCanvas->drawRect(r, paint);
+ paint.setShader(SkShaders::Blend(
+ SkBlendMode::kSrcIn, std::move(mask_shader), std::move(source_shader)));
+ m_pCanvas->drawRect(
+ SkRect::MakeWH(SkIntToScalar(src_width), SkIntToScalar(src_height)),
+ paint);
}
+
DebugValidate(m_pBitmap, m_pBackdropBitmap);
return true;
}
@@ -1755,13 +1555,10 @@ bool CFX_SkiaDeviceDriver::StartDIBitsSkia(
BlendMode blend_type) {
DebugValidate(m_pBitmap, m_pBackdropBitmap);
- // Storage vector must outlive `skBitmap`.
- DataVector<uint32_t> dst32_storage;
- SkBitmap skBitmap;
- if (!Upsample(pSource, dst32_storage, &skBitmap, /*forceAlpha=*/false)) {
+ sk_sp<SkImage> skia_source = pSource->RealizeSkImage();
+ if (!skia_source) {
return false;
}
- skBitmap.setImmutable();
{
SkAutoCanvasRestore scoped_save_restore(m_pCanvas, /*doSave=*/true);
@@ -1793,12 +1590,13 @@ bool CFX_SkiaDeviceDriver::StartDIBitsSkia(
}
m_pCanvas->drawImageRect(
- skBitmap.asImage(),
+ skia_source,
SkRect::MakeLTRB(src_rect.left, src_rect.top, src_rect.right,
src_rect.bottom),
SkRect::MakeWH(src_rect.Width(), src_rect.Height()), sampling_options,
&paint, SkCanvas::kFast_SrcRectConstraint);
}
+
DebugValidate(m_pBitmap, m_pBackdropBitmap);
return true;
}
@@ -1810,15 +1608,6 @@ void CFX_DefaultRenderDevice::Clear(uint32_t color) {
static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver())->Clear(color);
}
-std::unique_ptr<SkPictureRecorder> CFX_DefaultRenderDevice::CreateRecorder(
- const SkRect& bounds) {
- auto recorder = std::make_unique<SkPictureRecorder>();
- recorder->beginRecording(bounds);
-
- SetDeviceDriver(std::make_unique<CFX_SkiaDeviceDriver>(recorder.get()));
- return recorder;
-}
-
bool CFX_DefaultRenderDevice::AttachSkiaImpl(
RetainPtr<CFX_DIBitmap> pBitmap,
bool bRgbByteOrder,
@@ -1837,10 +1626,11 @@ bool CFX_DefaultRenderDevice::AttachSkiaImpl(
return true;
}
-bool CFX_DefaultRenderDevice::AttachRecorder(SkPictureRecorder* recorder) {
- if (!recorder)
+bool CFX_DefaultRenderDevice::AttachCanvas(SkCanvas* canvas) {
+ if (!canvas) {
return false;
- SetDeviceDriver(std::make_unique<CFX_SkiaDeviceDriver>(recorder));
+ }
+ SetDeviceDriver(std::make_unique<CFX_SkiaDeviceDriver>(canvas));
return true;
}
@@ -1862,14 +1652,3 @@ bool CFX_DefaultRenderDevice::CreateSkia(
SetDeviceDriver(std::move(driver));
return true;
}
-
-bool CFX_DefaultRenderDevice::SetBitsWithMask(
- const RetainPtr<CFX_DIBBase>& pBitmap,
- const RetainPtr<CFX_DIBBase>& pMask,
- int left,
- int top,
- int bitmap_alpha,
- BlendMode blend_type) {
- return static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver())
- ->SetBitsWithMask(pBitmap, pMask, left, top, bitmap_alpha, blend_type);
-}
diff --git a/core/fxge/skia/fx_skia_device.h b/core/fxge/skia/fx_skia_device.h
index beed9a308..3285f8fb0 100644
--- a/core/fxge/skia/fx_skia_device.h
+++ b/core/fxge/skia/fx_skia_device.h
@@ -12,18 +12,20 @@
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/fx_memory_wrappers.h"
#include "core/fxcrt/retain_ptr.h"
+#include "core/fxcrt/unowned_ptr.h"
#include "core/fxge/cfx_fillrenderoptions.h"
#include "core/fxge/cfx_path.h"
#include "core/fxge/renderdevicedriver_iface.h"
#include "third_party/base/check_op.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#include "third_party/skia/include/core/SkPoint.h"
#include "third_party/skia/include/core/SkRSXform.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
class CFX_Font;
class CFX_Matrix;
class SkCanvas;
-class SkPictureRecorder;
+class SkSurface;
class TextCharPos;
struct CFX_TextRenderOptions;
@@ -39,7 +41,7 @@ class CFX_SkiaDeviceDriver final : public RenderDeviceDriverIface {
RetainPtr<CFX_DIBitmap> pBackdropBitmap,
bool bGroupKnockout);
- explicit CFX_SkiaDeviceDriver(SkPictureRecorder* recorder);
+ explicit CFX_SkiaDeviceDriver(SkCanvas* canvas);
~CFX_SkiaDeviceDriver() override;
/** Options */
@@ -217,8 +219,8 @@ class CFX_SkiaDeviceDriver final : public RenderDeviceDriverIface {
// bitmap is 24 bpp and cannot be directly used as the back of a SkCanvas.
RetainPtr<CFX_DIBitmap> m_pOriginalBitmap;
- SkCanvas* m_pCanvas;
- SkPictureRecorder* const m_pRecorder;
+ sk_sp<SkSurface> surface_;
+ UnownedPtr<SkCanvas> m_pCanvas;
CFX_FillRenderOptions m_FillOptions;
bool m_bRgbByteOrder;
bool m_bGroupKnockout;
diff --git a/core/fxge/skia/fx_skia_device_embeddertest.cpp b/core/fxge/skia/fx_skia_device_embeddertest.cpp
index 517d86369..ca38a1ed0 100644
--- a/core/fxge/skia/fx_skia_device_embeddertest.cpp
+++ b/core/fxge/skia/fx_skia_device_embeddertest.cpp
@@ -5,7 +5,12 @@
#include "core/fxge/skia/fx_skia_device.h"
#include <memory>
+#include <set>
+#include <utility>
+#include "core/fpdfapi/page/cpdf_page.h"
+#include "core/fpdfapi/render/cpdf_pagerendercontext.h"
+#include "core/fxcrt/fx_codepage.h"
#include "core/fxge/cfx_defaultrenderdevice.h"
#include "core/fxge/cfx_fillrenderoptions.h"
#include "core/fxge/cfx_font.h"
@@ -13,15 +18,26 @@
#include "core/fxge/cfx_path.h"
#include "core/fxge/cfx_renderdevice.h"
#include "core/fxge/cfx_textrenderoptions.h"
+#include "core/fxge/dib/cfx_dibitmap.h"
#include "core/fxge/text_char_pos.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
+#include "fpdfsdk/cpdfsdk_renderpage.h"
#include "public/cpp/fpdf_scopers.h"
#include "public/fpdfview.h"
+#include "testing/embedder_test.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkPictureRecorder.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkImage.h"
+#include "third_party/skia/include/core/SkSize.h"
+#include "third_party/skia/include/utils/SkNoDrawCanvas.h"
namespace {
+using ::testing::NiceMock;
+using ::testing::SizeIs;
+using ::testing::WithArg;
+
struct State {
enum class Change { kNo, kYes };
enum class Save { kNo, kYes };
@@ -44,11 +60,14 @@ void EmptyTest(CFX_SkiaDeviceDriver* driver, const State&) {
void CommonTest(CFX_SkiaDeviceDriver* driver, const State& state) {
TextCharPos charPos[1];
charPos[0].m_Origin = CFX_PointF(0, 1);
- charPos[0].m_GlyphIndex = 1;
+ charPos[0].m_GlyphIndex = 0;
charPos[0].m_FontCharWidth = 4;
CFX_Font font;
- float fontSize = 1;
+ font.LoadSubst("Courier", /*bTrueType=*/true, /*flags=*/0,
+ /*weight=*/400, /*italic_angle=*/0, FX_CodePage::kShiftJIS,
+ /*bVertical=*/false);
+ float fontSize = 20;
CFX_Path clipPath;
CFX_Path clipPath2;
clipPath.AppendRect(0, 0, 3, 1);
@@ -63,7 +82,10 @@ void CommonTest(CFX_SkiaDeviceDriver* driver, const State& state) {
CFX_Matrix matrix2;
matrix2.Translate(1, 0);
CFX_GraphStateData graphState;
- static constexpr CFX_TextRenderOptions kTextOptions;
+ // Turn off anti-aliasing so that pixels with transitional colors can be
+ // avoided.
+ static constexpr CFX_TextRenderOptions kTextOptions(
+ CFX_TextRenderOptions::kAliasing);
if (state.m_save == State::Save::kYes)
driver->SaveState();
if (state.m_clip != State::Clip::kNo)
@@ -141,6 +163,47 @@ void Harness(void (*Test)(CFX_SkiaDeviceDriver*, const State&),
EXPECT_EQ(state.m_pixel, pixel);
}
+void RenderPageToSkCanvas(FPDF_PAGE page,
+ int start_x,
+ int start_y,
+ int size_x,
+ int size_y,
+ SkCanvas* canvas) {
+ CPDF_Page* cpdf_page = CPDFPageFromFPDFPage(page);
+
+ auto context = std::make_unique<CPDF_PageRenderContext>();
+ CPDF_PageRenderContext* unowned_context = context.get();
+
+ CPDF_Page::RenderContextClearer clearer(cpdf_page);
+ cpdf_page->SetRenderContext(std::move(context));
+
+ auto default_device = std::make_unique<CFX_DefaultRenderDevice>();
+ default_device->AttachCanvas(canvas);
+ unowned_context->m_pDevice = std::move(default_device);
+
+ CPDFSDK_RenderPageWithContext(unowned_context, cpdf_page, start_x, start_y,
+ size_x, size_y, /*rotate=*/0, /*flags=*/0,
+ /*color_scheme=*/nullptr,
+ /*need_to_restore=*/true, /*pause=*/nullptr);
+}
+
+class MockCanvas : public SkNoDrawCanvas {
+ public:
+ MockCanvas(int width, int height) : SkNoDrawCanvas(width, height) {}
+
+ MOCK_METHOD(void,
+ onDrawImageRect2,
+ (const SkImage*,
+ const SkRect&,
+ const SkRect&,
+ const SkSamplingOptions&,
+ const SkPaint*,
+ SrcRectConstraint),
+ (override));
+};
+
+using FxgeSkiaEmbedderTest = EmbedderTest;
+
} // namespace
TEST(fxge, SkiaStateEmpty) {
@@ -165,8 +228,7 @@ TEST(fxge, SkiaStatePath) {
State::Graphic::kPath, 0xFF112233});
}
-// TODO(crbug.com/pdfium/11): Fix this test and enable.
-TEST(fxge, DISABLED_SkiaStateText) {
+TEST(fxge, SkiaStateText) {
if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
return;
@@ -182,3 +244,48 @@ TEST(fxge, SkiaStateOOSClip) {
return;
Harness(&OutOfSequenceClipTest, {});
}
+
+TEST_F(FxgeSkiaEmbedderTest, RenderBigImageTwice) {
+ static constexpr int kImageWidth = 5100;
+ static constexpr int kImageHeight = 6600;
+
+ // Page size that renders 20 image pixels per output pixel. This value evenly
+ // divides both the image width and half the image height.
+ static constexpr int kPageToImageFactor = 20;
+ static constexpr int kPageWidth = kImageWidth / kPageToImageFactor;
+ static constexpr int kPageHeight = kImageHeight / kPageToImageFactor;
+
+ if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ GTEST_SKIP() << "Skia is not the default renderer";
+ }
+
+ ASSERT_TRUE(OpenDocument("bug_2034.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+
+ std::set<int> image_ids;
+ NiceMock<MockCanvas> canvas(kPageWidth, kPageHeight / 2);
+ EXPECT_CALL(canvas, onDrawImageRect2)
+ .WillRepeatedly(WithArg<0>([&image_ids](const SkImage* image) {
+ ASSERT_TRUE(image);
+ image_ids.insert(image->uniqueID());
+
+ // TODO(crbug.com/pdfium/2026): Image dimensions should be clipped to
+ // 5100x3320. The extra `kPageToImageFactor` accounts for anti-aliasing.
+ EXPECT_EQ(SkISize::Make(kImageWidth, kImageHeight), image->dimensions())
+ << "Actual image dimensions: " << image->width() << "x"
+ << image->height();
+ }));
+
+ // Render top half.
+ RenderPageToSkCanvas(page, /*start_x=*/0, /*start_y=*/0,
+ /*size_x=*/kPageWidth, /*size_y=*/kPageHeight, &canvas);
+
+ // Render bottom half.
+ RenderPageToSkCanvas(page, /*start_x=*/0, /*start_y=*/-kPageHeight / 2,
+ /*size_x=*/kPageWidth, /*size_y=*/kPageHeight, &canvas);
+
+ EXPECT_THAT(image_ids, SizeIs(1));
+
+ UnloadPage(page);
+}
diff --git a/core/fxge/systemfontinfo_iface.h b/core/fxge/systemfontinfo_iface.h
index 3e661b863..90cdb198b 100644
--- a/core/fxge/systemfontinfo_iface.h
+++ b/core/fxge/systemfontinfo_iface.h
@@ -13,7 +13,7 @@
#include "core/fxcrt/bytestring.h"
#include "core/fxcrt/fx_codepage_forward.h"
#include "core/fxge/cfx_fontmapper.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
constexpr uint32_t kTableNAME = CFX_FontMapper::MakeTag('n', 'a', 'm', 'e');
constexpr uint32_t kTableTTCF = CFX_FontMapper::MakeTag('t', 't', 'c', 'f');
diff --git a/core/fxge/win32/cfx_psrenderer.cpp b/core/fxge/win32/cfx_psrenderer.cpp
index ae168f4b7..c2da03673 100644
--- a/core/fxge/win32/cfx_psrenderer.cpp
+++ b/core/fxge/win32/cfx_psrenderer.cpp
@@ -29,7 +29,7 @@
#include "core/fxge/cfx_glyphcache.h"
#include "core/fxge/cfx_path.h"
#include "core/fxge/cfx_renderdevice.h"
-#include "core/fxge/dib/cfx_dibextractor.h"
+#include "core/fxge/dib/cfx_dibbase.h"
#include "core/fxge/dib/cfx_dibitmap.h"
#include "core/fxge/dib/fx_dib.h"
#include "core/fxge/freetype/fx_freetype.h"
@@ -555,10 +555,7 @@ bool CFX_PSRenderer::DrawDIBits(const RetainPtr<CFX_DIBBase>& pSource,
WriteStream(buf);
WritePSBinary(compress_result.data);
} else {
- CFX_DIBExtractor source_extractor(pSource);
- RetainPtr<CFX_DIBBase> pConverted = source_extractor.GetBitmap();
- if (!pConverted)
- return false;
+ RetainPtr<CFX_DIBBase> pConverted = pSource;
switch (pSource->GetFormat()) {
case FXDIB_Format::k1bppRgb:
case FXDIB_Format::kRgb32:
diff --git a/core/fxge/win32/cfx_psrenderer.h b/core/fxge/win32/cfx_psrenderer.h
index b8010f6d8..ad914befd 100644
--- a/core/fxge/win32/cfx_psrenderer.h
+++ b/core/fxge/win32/cfx_psrenderer.h
@@ -24,7 +24,7 @@
#include "core/fxcrt/unowned_ptr.h"
#include "core/fxge/cfx_graphstatedata.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_DIBBase;
class CFX_Font;
diff --git a/core/fxge/win32/cfx_psrenderer_unittest.cpp b/core/fxge/win32/cfx_psrenderer_unittest.cpp
index 6186f0fe9..9927692d0 100644
--- a/core/fxge/win32/cfx_psrenderer_unittest.cpp
+++ b/core/fxge/win32/cfx_psrenderer_unittest.cpp
@@ -14,7 +14,7 @@
#include "core/fxge/win32/cfx_psfonttracker.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace {
diff --git a/core/fxge/win32/cgdi_device_driver.cpp b/core/fxge/win32/cgdi_device_driver.cpp
index 048377da7..6ae582e38 100644
--- a/core/fxge/win32/cgdi_device_driver.cpp
+++ b/core/fxge/win32/cgdi_device_driver.cpp
@@ -18,6 +18,7 @@
#include "core/fxge/cfx_fillrenderoptions.h"
#include "core/fxge/cfx_graphstatedata.h"
#include "core/fxge/cfx_path.h"
+#include "core/fxge/dib/cfx_dibbase.h"
#include "core/fxge/dib/cfx_dibitmap.h"
#include "core/fxge/render_defines.h"
#include "core/fxge/win32/cwin32_platform.h"
@@ -152,10 +153,11 @@ void SetPathToDC(HDC hDC, const CFX_Path& path, const CFX_Matrix* pMatrix) {
EndPath(hDC);
}
-ByteString GetBitmapInfo(const RetainPtr<CFX_DIBitmap>& pBitmap) {
+ByteString GetBitmapInfo(const RetainPtr<CFX_DIBBase>& source) {
int len = sizeof(BITMAPINFOHEADER);
- if (pBitmap->GetBPP() == 1 || pBitmap->GetBPP() == 8)
- len += sizeof(DWORD) * (int)(1 << pBitmap->GetBPP());
+ if (source->GetBPP() == 1 || source->GetBPP() == 8) {
+ len += sizeof(DWORD) * (int)(1 << source->GetBPP());
+ }
ByteString result;
{
@@ -164,30 +166,33 @@ ByteString GetBitmapInfo(const RetainPtr<CFX_DIBitmap>& pBitmap) {
BITMAPINFOHEADER* pbmih = reinterpret_cast<BITMAPINFOHEADER*>(cspan.data());
memset(pbmih, 0, sizeof(BITMAPINFOHEADER));
pbmih->biSize = sizeof(BITMAPINFOHEADER);
- pbmih->biBitCount = pBitmap->GetBPP();
+ pbmih->biBitCount = source->GetBPP();
pbmih->biCompression = BI_RGB;
- pbmih->biHeight = -(int)pBitmap->GetHeight();
+ pbmih->biHeight = -(int)source->GetHeight();
pbmih->biPlanes = 1;
- pbmih->biWidth = pBitmap->GetWidth();
- if (pBitmap->GetBPP() == 8) {
- uint32_t* pPalette = (uint32_t*)(pbmih + 1);
- if (pBitmap->HasPalette()) {
- pdfium::span<const uint32_t> palette = pBitmap->GetPaletteSpan();
- for (int i = 0; i < 256; i++)
- pPalette[i] = palette[i];
+ pbmih->biWidth = source->GetWidth();
+ if (source->GetBPP() == 8) {
+ uint32_t* palette = (uint32_t*)(pbmih + 1);
+ if (source->HasPalette()) {
+ pdfium::span<const uint32_t> palette_span = source->GetPaletteSpan();
+ for (int i = 0; i < 256; i++) {
+ palette[i] = palette_span[i];
+ }
} else {
- for (int i = 0; i < 256; i++)
- pPalette[i] = ArgbEncode(0, i, i, i);
+ for (int i = 0; i < 256; i++) {
+ palette[i] = ArgbEncode(0, i, i, i);
+ }
}
}
- if (pBitmap->GetBPP() == 1) {
- uint32_t* pPalette = (uint32_t*)(pbmih + 1);
- if (pBitmap->HasPalette()) {
- pPalette[0] = pBitmap->GetPaletteSpan()[0];
- pPalette[1] = pBitmap->GetPaletteSpan()[1];
+ if (source->GetBPP() == 1) {
+ uint32_t* palette = (uint32_t*)(pbmih + 1);
+ if (source->HasPalette()) {
+ pdfium::span<const uint32_t> palette_span = source->GetPaletteSpan();
+ palette[0] = palette_span[0];
+ palette[1] = palette_span[1];
} else {
- pPalette[0] = 0;
- pPalette[1] = 0xffffff;
+ palette[0] = 0;
+ palette[1] = 0xffffff;
}
}
}
@@ -384,85 +389,85 @@ void CGdiDeviceDriver::RestoreState(bool bKeepSaved) {
SaveDC(m_hDC);
}
-bool CGdiDeviceDriver::GDI_SetDIBits(const RetainPtr<CFX_DIBitmap>& pBitmap1,
+bool CGdiDeviceDriver::GDI_SetDIBits(const RetainPtr<CFX_DIBBase>& source,
const FX_RECT& src_rect,
int left,
int top) {
if (m_DeviceType == DeviceType::kPrinter) {
- RetainPtr<CFX_DIBitmap> pBitmap = pBitmap1->FlipImage(false, true);
- if (!pBitmap)
+ RetainPtr<CFX_DIBBase> flipped_source = source->FlipImage(false, true);
+ if (!flipped_source) {
return false;
+ }
- LPBYTE pBuffer = pBitmap->GetBuffer().data();
- ByteString info = GetBitmapInfo(pBitmap);
+ ByteString info = GetBitmapInfo(flipped_source);
((BITMAPINFOHEADER*)info.c_str())->biHeight *= -1;
FX_RECT dst_rect(0, 0, src_rect.Width(), src_rect.Height());
- dst_rect.Intersect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight());
+ dst_rect.Intersect(0, 0, flipped_source->GetWidth(),
+ flipped_source->GetHeight());
int dst_width = dst_rect.Width();
int dst_height = dst_rect.Height();
::StretchDIBits(m_hDC, left, top, dst_width, dst_height, 0, 0, dst_width,
- dst_height, pBuffer, (BITMAPINFO*)info.c_str(),
- DIB_RGB_COLORS, SRCCOPY);
+ dst_height, flipped_source->GetBuffer().data(),
+ (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS, SRCCOPY);
return true;
}
- RetainPtr<CFX_DIBitmap> pBitmap = pBitmap1;
- LPBYTE pBuffer = pBitmap->GetBuffer().data();
- ByteString info = GetBitmapInfo(pBitmap);
+ ByteString info = GetBitmapInfo(source);
::SetDIBitsToDevice(m_hDC, left, top, src_rect.Width(), src_rect.Height(),
- src_rect.left, pBitmap->GetHeight() - src_rect.bottom, 0,
- pBitmap->GetHeight(), pBuffer, (BITMAPINFO*)info.c_str(),
- DIB_RGB_COLORS);
+ src_rect.left, source->GetHeight() - src_rect.bottom, 0,
+ source->GetHeight(), source->GetBuffer().data(),
+ (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
return true;
}
-bool CGdiDeviceDriver::GDI_StretchDIBits(
- const RetainPtr<CFX_DIBitmap>& pBitmap1,
- int dest_left,
- int dest_top,
- int dest_width,
- int dest_height,
- const FXDIB_ResampleOptions& options) {
- RetainPtr<CFX_DIBitmap> pBitmap = pBitmap1;
- if (!pBitmap || dest_width == 0 || dest_height == 0)
+bool CGdiDeviceDriver::GDI_StretchDIBits(const RetainPtr<CFX_DIBBase>& source,
+ int dest_left,
+ int dest_top,
+ int dest_width,
+ int dest_height,
+ const FXDIB_ResampleOptions& options) {
+ if (!source || dest_width == 0 || dest_height == 0) {
return false;
+ }
- ByteString info = GetBitmapInfo(pBitmap);
+ ByteString info = GetBitmapInfo(source);
if ((int64_t)abs(dest_width) * abs(dest_height) <
- (int64_t)pBitmap1->GetWidth() * pBitmap1->GetHeight() * 4 ||
+ (int64_t)source->GetWidth() * source->GetHeight() * 4 ||
options.bInterpolateBilinear) {
SetStretchBltMode(m_hDC, HALFTONE);
} else {
SetStretchBltMode(m_hDC, COLORONCOLOR);
}
- RetainPtr<CFX_DIBitmap> pToStrechBitmap = pBitmap;
+ RetainPtr<CFX_DIBBase> stretch_source = source;
if (m_DeviceType == DeviceType::kPrinter &&
- ((int64_t)pBitmap->GetWidth() * pBitmap->GetHeight() >
+ ((int64_t)source->GetWidth() * source->GetHeight() >
(int64_t)abs(dest_width) * abs(dest_height))) {
- pToStrechBitmap = pBitmap->StretchTo(dest_width, dest_height,
- FXDIB_ResampleOptions(), nullptr);
+ stretch_source = source->StretchTo(dest_width, dest_height,
+ FXDIB_ResampleOptions(), nullptr);
+ if (!stretch_source) {
+ return false;
+ }
+ info = GetBitmapInfo(stretch_source);
}
- ByteString toStrechBitmapInfo = GetBitmapInfo(pToStrechBitmap);
::StretchDIBits(m_hDC, dest_left, dest_top, dest_width, dest_height, 0, 0,
- pToStrechBitmap->GetWidth(), pToStrechBitmap->GetHeight(),
- pToStrechBitmap->GetBuffer().data(),
- (BITMAPINFO*)toStrechBitmapInfo.c_str(), DIB_RGB_COLORS,
- SRCCOPY);
+ stretch_source->GetWidth(), stretch_source->GetHeight(),
+ stretch_source->GetBuffer().data(), (BITMAPINFO*)info.c_str(),
+ DIB_RGB_COLORS, SRCCOPY);
return true;
}
-bool CGdiDeviceDriver::GDI_StretchBitMask(
- const RetainPtr<CFX_DIBitmap>& pBitmap1,
- int dest_left,
- int dest_top,
- int dest_width,
- int dest_height,
- uint32_t bitmap_color) {
- RetainPtr<CFX_DIBitmap> pBitmap = pBitmap1;
- if (!pBitmap || dest_width == 0 || dest_height == 0)
+bool CGdiDeviceDriver::GDI_StretchBitMask(const RetainPtr<CFX_DIBBase>& source,
+ int dest_left,
+ int dest_top,
+ int dest_width,
+ int dest_height,
+ uint32_t bitmap_color) {
+ if (!source || dest_width == 0 || dest_height == 0) {
return false;
+ }
- int width = pBitmap->GetWidth(), height = pBitmap->GetHeight();
+ int width = source->GetWidth();
+ int height = source->GetHeight();
struct {
BITMAPINFOHEADER bmiHeader;
uint32_t bmiColors[2];
@@ -502,7 +507,7 @@ bool CGdiDeviceDriver::GDI_StretchBitMask(
// 0xB8074A
::StretchDIBits(m_hDC, dest_left, dest_top, dest_width, dest_height, 0, 0,
- width, height, pBitmap->GetBuffer().data(), (BITMAPINFO*)&bmi,
+ width, height, source->GetBuffer().data(), (BITMAPINFO*)&bmi,
DIB_RGB_COLORS, 0xB8074A);
SelectObject(m_hDC, hOld);
diff --git a/core/fxge/win32/cgdi_device_driver.h b/core/fxge/win32/cgdi_device_driver.h
index 59f24c0b2..de8c41e8e 100644
--- a/core/fxge/win32/cgdi_device_driver.h
+++ b/core/fxge/win32/cgdi_device_driver.h
@@ -13,6 +13,8 @@
#include "core/fxge/renderdevicedriver_iface.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+class CFX_DIBBase;
+
class CGdiDeviceDriver : public RenderDeviceDriverIface {
protected:
CGdiDeviceDriver(HDC hDC, DeviceType device_type);
@@ -50,17 +52,17 @@ class CGdiDeviceDriver : public RenderDeviceDriverIface {
void DrawLine(float x1, float y1, float x2, float y2);
- bool GDI_SetDIBits(const RetainPtr<CFX_DIBitmap>& pBitmap,
+ bool GDI_SetDIBits(const RetainPtr<CFX_DIBBase>& source,
const FX_RECT& src_rect,
int left,
int top);
- bool GDI_StretchDIBits(const RetainPtr<CFX_DIBitmap>& pBitmap,
+ bool GDI_StretchDIBits(const RetainPtr<CFX_DIBBase>& source,
int dest_left,
int dest_top,
int dest_width,
int dest_height,
const FXDIB_ResampleOptions& options);
- bool GDI_StretchBitMask(const RetainPtr<CFX_DIBitmap>& pBitmap,
+ bool GDI_StretchBitMask(const RetainPtr<CFX_DIBBase>& source,
int dest_left,
int dest_top,
int dest_width,
diff --git a/core/fxge/win32/cgdi_display_driver.cpp b/core/fxge/win32/cgdi_display_driver.cpp
index 7ba2d766f..763e30080 100644
--- a/core/fxge/win32/cgdi_display_driver.cpp
+++ b/core/fxge/win32/cgdi_display_driver.cpp
@@ -8,7 +8,7 @@
#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/fx_system.h"
-#include "core/fxge/dib/cfx_dibextractor.h"
+#include "core/fxge/dib/cfx_dibbase.h"
#include "core/fxge/dib/cfx_dibitmap.h"
#include "core/fxge/render_defines.h"
#include "core/fxge/win32/cwin32_platform.h"
@@ -51,14 +51,15 @@ bool CGdiDisplayDriver::GetDIBits(const RetainPtr<CFX_DIBitmap>& pBitmap,
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biWidth = width;
if (pBitmap->GetBPP() > 8) {
- ret = ::GetDIBits(hDCMemory, hbmp, 0, height, pBitmap->GetBuffer().data(),
- &bmi, DIB_RGB_COLORS) == height;
+ ret = ::GetDIBits(hDCMemory, hbmp, 0, height,
+ pBitmap->GetWritableBuffer().data(), &bmi,
+ DIB_RGB_COLORS) == height;
} else {
auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
if (bitmap->Create(width, height, FXDIB_Format::kRgb)) {
bmi.bmiHeader.biBitCount = 24;
- ::GetDIBits(hDCMemory, hbmp, 0, height, bitmap->GetBuffer().data(), &bmi,
- DIB_RGB_COLORS);
+ ::GetDIBits(hDCMemory, hbmp, 0, height,
+ bitmap->GetWritableBuffer().data(), &bmi, DIB_RGB_COLORS);
ret = pBitmap->TransferBitmap(0, 0, width, height, bitmap, 0, 0);
} else {
ret = false;
@@ -114,11 +115,7 @@ bool CGdiDisplayDriver::SetDIBits(const RetainPtr<CFX_DIBBase>& pSource,
FX_RECT alpha_src_rect(0, 0, width, height);
return SetDIBits(bitmap, 0, alpha_src_rect, left, top, BlendMode::kNormal);
}
- CFX_DIBExtractor temp(pSource);
- RetainPtr<CFX_DIBitmap> pBitmap = temp.GetBitmap();
- if (!pBitmap)
- return false;
- return GDI_SetDIBits(pBitmap, src_rect, left, top);
+ return GDI_SetDIBits(pSource, src_rect, left, top);
}
bool CGdiDisplayDriver::UseFoxitStretchEngine(
@@ -138,7 +135,7 @@ bool CGdiDisplayDriver::UseFoxitStretchEngine(
dest_top += dest_height;
bitmap_clip.Offset(-dest_left, -dest_top);
- RetainPtr<CFX_DIBitmap> pStretched =
+ RetainPtr<CFX_DIBBase> pStretched =
pSource->StretchTo(dest_width, dest_height, options, &bitmap_clip);
if (!pStretched)
return true;
@@ -198,23 +195,15 @@ bool CGdiDisplayDriver::StretchDIBits(const RetainPtr<CFX_DIBBase>& pSource,
auto* pPlatform =
static_cast<CWin32Platform*>(CFX_GEModule::Get()->GetPlatform());
if (pPlatform->m_GdiplusExt.IsAvailable()) {
- CFX_DIBExtractor temp(pSource);
- RetainPtr<CFX_DIBitmap> pBitmap = temp.GetBitmap();
- if (!pBitmap)
- return false;
return pPlatform->m_GdiplusExt.StretchDIBits(
- m_hDC, pBitmap, dest_left, dest_top, dest_width, dest_height,
+ m_hDC, pSource, dest_left, dest_top, dest_width, dest_height,
pClipRect, FXDIB_ResampleOptions());
}
return UseFoxitStretchEngine(pSource, color, dest_left, dest_top,
dest_width, dest_height, pClipRect,
FXDIB_ResampleOptions());
}
- CFX_DIBExtractor temp(pSource);
- RetainPtr<CFX_DIBitmap> pBitmap = temp.GetBitmap();
- if (!pBitmap)
- return false;
- return GDI_StretchDIBits(pBitmap, dest_left, dest_top, dest_width,
+ return GDI_StretchDIBits(pSource, dest_left, dest_top, dest_width,
dest_height, FXDIB_ResampleOptions());
}
diff --git a/core/fxge/win32/cgdi_plus_ext.cpp b/core/fxge/win32/cgdi_plus_ext.cpp
index 06571dad1..42cf50500 100644
--- a/core/fxge/win32/cgdi_plus_ext.cpp
+++ b/core/fxge/win32/cgdi_plus_ext.cpp
@@ -23,11 +23,12 @@
#include "core/fxge/cfx_gemodule.h"
#include "core/fxge/cfx_graphstatedata.h"
#include "core/fxge/cfx_path.h"
+#include "core/fxge/dib/cfx_dibbase.h"
#include "core/fxge/dib/cfx_dibitmap.h"
#include "core/fxge/win32/cwin32_platform.h"
+#include "third_party/base/containers/span.h"
#include "third_party/base/notreached.h"
#include "third_party/base/numerics/safe_conversions.h"
-#include "third_party/base/span.h"
// Has to come before gdiplus.h
namespace Gdiplus {
@@ -203,7 +204,7 @@ Gdiplus::GpBrush* GdipCreateBrushImpl(DWORD argb) {
}
void OutputImage(Gdiplus::GpGraphics* pGraphics,
- const RetainPtr<CFX_DIBitmap>& pBitmap,
+ const RetainPtr<CFX_DIBBase>& source,
const FX_RECT& src_rect,
int dest_left,
int dest_top,
@@ -212,22 +213,27 @@ void OutputImage(Gdiplus::GpGraphics* pGraphics,
int src_width = src_rect.Width();
int src_height = src_rect.Height();
const CGdiplusExt& GdiplusExt = GetGdiplusExt();
- if (pBitmap->GetBPP() == 1 && (src_rect.left % 8)) {
+ if (source->GetBPP() == 1 && (src_rect.left % 8)) {
FX_RECT new_rect(0, 0, src_width, src_height);
- RetainPtr<CFX_DIBitmap> pCloned = pBitmap->ClipTo(src_rect);
+ RetainPtr<CFX_DIBBase> pCloned = source->ClipTo(src_rect);
if (!pCloned)
return;
OutputImage(pGraphics, pCloned, new_rect, dest_left, dest_top, dest_width,
dest_height);
return;
}
- int src_pitch = pBitmap->GetPitch();
- uint8_t* scan0 = pBitmap->GetBuffer()
- .subspan(src_rect.top * src_pitch +
- pBitmap->GetBPP() * src_rect.left / 8)
- .data();
+ int src_pitch = source->GetPitch();
+
+ // `GdipCreateBitmapFromScan0()` requires a `BYTE*` scanline buffer, but in
+ // this case, the bitmap only gets read by `GdipDrawImagePointsI()`, then
+ // disposed of, so it's safe to cast away `const` here.
+ uint8_t* scan0 =
+ const_cast<uint8_t*>(source->GetBuffer()
+ .subspan(src_rect.top * src_pitch +
+ source->GetBPP() * src_rect.left / 8)
+ .data());
Gdiplus::GpBitmap* bitmap = nullptr;
- switch (pBitmap->GetFormat()) {
+ switch (source->GetFormat()) {
case FXDIB_Format::kArgb:
CallFunc(GdipCreateBitmapFromScan0)(src_width, src_height, src_pitch,
PixelFormat32bppARGB, scan0, &bitmap);
@@ -248,7 +254,7 @@ void OutputImage(Gdiplus::GpGraphics* pGraphics,
pal[0] = 0;
pal[1] = 256;
for (int i = 0; i < 256; i++)
- pal[i + 2] = pBitmap->GetPaletteArgb(i);
+ pal[i + 2] = source->GetPaletteArgb(i);
CallFunc(GdipSetImagePalette)(bitmap, (Gdiplus::ColorPalette*)pal);
break;
}
@@ -575,7 +581,7 @@ void CGdiplusExt::Load() {
}
bool CGdiplusExt::StretchDIBits(HDC hDC,
- const RetainPtr<CFX_DIBitmap>& pBitmap,
+ const RetainPtr<CFX_DIBBase>& source,
int dest_left,
int dest_top,
int dest_width,
@@ -589,16 +595,16 @@ bool CGdiplusExt::StretchDIBits(HDC hDC,
if (options.bNoSmoothing) {
CallFunc(GdipSetInterpolationMode)(
pGraphics, Gdiplus::InterpolationModeNearestNeighbor);
- } else if (pBitmap->GetWidth() > abs(dest_width) / 2 ||
- pBitmap->GetHeight() > abs(dest_height) / 2) {
+ } else if (source->GetWidth() > abs(dest_width) / 2 ||
+ source->GetHeight() > abs(dest_height) / 2) {
CallFunc(GdipSetInterpolationMode)(pGraphics,
Gdiplus::InterpolationModeHighQuality);
} else {
CallFunc(GdipSetInterpolationMode)(pGraphics,
Gdiplus::InterpolationModeBilinear);
}
- FX_RECT src_rect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight());
- OutputImage(pGraphics, pBitmap, src_rect, dest_left, dest_top, dest_width,
+ FX_RECT src_rect(0, 0, source->GetWidth(), source->GetHeight());
+ OutputImage(pGraphics, source, src_rect, dest_left, dest_top, dest_width,
dest_height);
CallFunc(GdipDeleteGraphics)(pGraphics);
CallFunc(GdipDeleteGraphics)(pGraphics);
diff --git a/core/fxge/win32/cgdi_plus_ext.h b/core/fxge/win32/cgdi_plus_ext.h
index ff6f1659d..ced36c976 100644
--- a/core/fxge/win32/cgdi_plus_ext.h
+++ b/core/fxge/win32/cgdi_plus_ext.h
@@ -14,7 +14,7 @@
#include "core/fxcrt/retain_ptr.h"
-class CFX_DIBitmap;
+class CFX_DIBBase;
class CFX_GraphStateData;
class CFX_Matrix;
class CFX_Path;
@@ -30,7 +30,7 @@ class CGdiplusExt {
void Load();
bool IsAvailable() { return !!m_hModule; }
bool StretchDIBits(HDC hDC,
- const RetainPtr<CFX_DIBitmap>& pBitmap,
+ const RetainPtr<CFX_DIBBase>& source,
int dest_left,
int dest_top,
int dest_width,
diff --git a/core/fxge/win32/cgdi_printer_driver.cpp b/core/fxge/win32/cgdi_printer_driver.cpp
index 8286685e4..28bc516bc 100644
--- a/core/fxge/win32/cgdi_printer_driver.cpp
+++ b/core/fxge/win32/cgdi_printer_driver.cpp
@@ -17,7 +17,7 @@
#include "core/fxcrt/retain_ptr.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_dibbase.h"
#include "core/fxge/dib/cfx_dibitmap.h"
#include "core/fxge/render_defines.h"
#include "core/fxge/text_char_pos.h"
@@ -59,12 +59,7 @@ bool CGdiPrinterDriver::SetDIBits(const RetainPtr<CFX_DIBBase>& pSource,
if (pSource->IsAlphaFormat())
return false;
- CFX_DIBExtractor temp(pSource);
- RetainPtr<CFX_DIBitmap> pBitmap = temp.GetBitmap();
- if (!pBitmap)
- return false;
-
- return GDI_SetDIBits(pBitmap, src_rect, left, top);
+ return GDI_SetDIBits(pSource, src_rect, left, top);
}
bool CGdiPrinterDriver::StretchDIBits(const RetainPtr<CFX_DIBBase>& pSource,
@@ -82,7 +77,7 @@ bool CGdiPrinterDriver::StretchDIBits(const RetainPtr<CFX_DIBBase>& pSource,
return false;
if (dest_width < 0 || dest_height < 0) {
- RetainPtr<CFX_DIBitmap> pFlipped =
+ RetainPtr<CFX_DIBBase> pFlipped =
pSource->FlipImage(dest_width < 0, dest_height < 0);
if (!pFlipped)
return false;
@@ -96,11 +91,7 @@ bool CGdiPrinterDriver::StretchDIBits(const RetainPtr<CFX_DIBBase>& pSource,
abs(dest_height), color);
}
- CFX_DIBExtractor temp(pSource);
- RetainPtr<CFX_DIBitmap> pBitmap = temp.GetBitmap();
- if (!pBitmap)
- return false;
- return GDI_StretchBitMask(pBitmap, dest_left, dest_top, dest_width,
+ return GDI_StretchBitMask(pSource, dest_left, dest_top, dest_width,
dest_height, color);
}
@@ -108,7 +99,7 @@ bool CGdiPrinterDriver::StretchDIBits(const RetainPtr<CFX_DIBBase>& pSource,
return false;
if (dest_width < 0 || dest_height < 0) {
- RetainPtr<CFX_DIBitmap> pFlipped =
+ RetainPtr<CFX_DIBBase> pFlipped =
pSource->FlipImage(dest_width < 0, dest_height < 0);
if (!pFlipped)
return false;
@@ -122,11 +113,7 @@ bool CGdiPrinterDriver::StretchDIBits(const RetainPtr<CFX_DIBBase>& pSource,
abs(dest_height), options);
}
- CFX_DIBExtractor temp(pSource);
- RetainPtr<CFX_DIBitmap> pBitmap = temp.GetBitmap();
- if (!pBitmap)
- return false;
- return GDI_StretchDIBits(pBitmap, dest_left, dest_top, dest_width,
+ return GDI_StretchDIBits(pSource, dest_left, dest_top, dest_width,
dest_height, options);
}
@@ -157,7 +144,7 @@ bool CGdiPrinterDriver::StartDIBits(const RetainPtr<CFX_DIBBase>& pSource,
if (fabs(matrix.a) >= 0.5f || fabs(matrix.d) >= 0.5f)
return false;
- RetainPtr<CFX_DIBitmap> pTransformed =
+ RetainPtr<CFX_DIBBase> pTransformed =
pSource->SwapXY(matrix.c > 0, matrix.b < 0);
if (!pTransformed)
return false;
diff --git a/core/fxge/win32/cpsoutput.cpp b/core/fxge/win32/cpsoutput.cpp
index 763a4e562..0b391ee92 100644
--- a/core/fxge/win32/cpsoutput.cpp
+++ b/core/fxge/win32/cpsoutput.cpp
@@ -9,7 +9,7 @@
#include <algorithm>
#include "core/fxcrt/fx_system.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
CPSOutput::CPSOutput(HDC hDC, OutputMode mode) : m_hDC(hDC), m_mode(mode) {}
diff --git a/core/fxge/win32/cwin32_platform.cpp b/core/fxge/win32/cwin32_platform.cpp
index 5794e2ed8..428f132fc 100644
--- a/core/fxge/win32/cwin32_platform.cpp
+++ b/core/fxge/win32/cwin32_platform.cpp
@@ -14,8 +14,8 @@
#include "core/fxge/cfx_folderfontinfo.h"
#include "core/fxge/cfx_gemodule.h"
#include "third_party/base/check.h"
+#include "third_party/base/containers/span.h"
#include "third_party/base/numerics/safe_conversions.h"
-#include "third_party/base/span.h"
#include "third_party/base/win/scoped_select_object.h"
#include "third_party/base/win/win_util.h"
diff --git a/fpdfsdk/BUILD.gn b/fpdfsdk/BUILD.gn
index b97d88141..c8aa54f27 100644
--- a/fpdfsdk/BUILD.gn
+++ b/fpdfsdk/BUILD.gn
@@ -97,10 +97,6 @@ source_set("fpdfsdk") {
]
allow_circular_includes_from += [ "fpdfxfa" ]
}
-
- if (pdf_use_skia) {
- deps += [ "//skia" ]
- }
}
pdfium_unittest_source_set("unittests") {
@@ -159,6 +155,7 @@ pdfium_embeddertest_source_set("embeddertests") {
"../core/fpdfapi/font",
"../core/fpdfapi/page",
"../core/fpdfapi/parser",
+ "../core/fxcrt:test_support",
"../core/fxge",
]
pdfium_root_dir = "../"
diff --git a/fpdfsdk/DEPS b/fpdfsdk/DEPS
index 14d2700e7..1e5251580 100644
--- a/fpdfsdk/DEPS
+++ b/fpdfsdk/DEPS
@@ -2,10 +2,15 @@ include_rules = [
'+core',
'+fxjs',
'+public',
- '+third_party/skia/include',
'+v8',
'+xfa/fgas/font',
'+xfa/fgas/graphics',
'+xfa/fwl',
'+xfa/fxfa',
]
+
+specific_include_rules = {
+ 'fpdf_view_embeddertest\.cpp': [
+ '+third_party/skia/include',
+ ],
+}
diff --git a/fpdfsdk/cpdfsdk_appstream.cpp b/fpdfsdk/cpdfsdk_appstream.cpp
index 030ea1485..55c93bf76 100644
--- a/fpdfsdk/cpdfsdk_appstream.cpp
+++ b/fpdfsdk/cpdfsdk_appstream.cpp
@@ -38,8 +38,8 @@
#include "fpdfsdk/pwl/cpwl_edit.h"
#include "fpdfsdk/pwl/cpwl_edit_impl.h"
#include "fpdfsdk/pwl/cpwl_wnd.h"
+#include "third_party/base/containers/span.h"
#include "third_party/base/numerics/safe_conversions.h"
-#include "third_party/base/span.h"
namespace {
@@ -465,7 +465,6 @@ ByteString GetCircleBorderAppStream(const CFX_FloatRect& rect,
float div = fHalfWidth * 0.75f;
CFX_FloatRect rect_by_75 = rect.GetDeflated(div, div);
switch (nStyle) {
- default:
case BorderStyle::kSolid:
case BorderStyle::kUnderline: {
sColor = GetStrokeColorAppStream(color);
@@ -545,7 +544,6 @@ ByteString GetCheckBoxAppStream(const CFX_FloatRect& rcBBox,
const CFX_Color& crText) {
CFX_FloatRect rcCenter = rcBBox.GetCenterSquare();
switch (nStyle) {
- default:
case CheckStyle::kCheck:
return GetAppStream_Check(rcCenter, crText);
case CheckStyle::kCircle:
@@ -570,7 +568,6 @@ ByteString GetRadioButtonAppStream(const CFX_FloatRect& rcBBox,
const CFX_Color& crText) {
CFX_FloatRect rcCenter = rcBBox.GetCenterSquare();
switch (nStyle) {
- default:
case CheckStyle::kCheck:
return GetAppStream_Check(rcCenter, crText);
case CheckStyle::kCircle:
@@ -957,7 +954,6 @@ ByteString GetBorderAppStreamInternal(const CFX_FloatRect& rect,
AutoClosedQCommand q(&sAppStream);
switch (nStyle) {
- default:
case BorderStyle::kSolid:
sColor = GetFillColorAppStream(color);
if (sColor.GetLength() > 0) {
diff --git a/fpdfsdk/cpdfsdk_baannot.cpp b/fpdfsdk/cpdfsdk_baannot.cpp
index a1751f967..c5d33d60a 100644
--- a/fpdfsdk/cpdfsdk_baannot.cpp
+++ b/fpdfsdk/cpdfsdk_baannot.cpp
@@ -161,8 +161,6 @@ void CPDFSDK_BAAnnot::SetBorderStyle(BorderStyle nStyle) {
case BorderStyle::kUnderline:
name = "U";
break;
- default:
- return;
}
pBSDict->SetNewFor<CPDF_Name>("S", name);
}
diff --git a/fpdfsdk/cpdfsdk_formfillenvironment.cpp b/fpdfsdk/cpdfsdk_formfillenvironment.cpp
index 84df6e14d..9aade3a86 100644
--- a/fpdfsdk/cpdfsdk_formfillenvironment.cpp
+++ b/fpdfsdk/cpdfsdk_formfillenvironment.cpp
@@ -1040,7 +1040,6 @@ void CPDFSDK_FormFillEnvironment::DoActionNoJs(const CPDF_Action& action,
break;
case CPDF_Action::Type::kJavaScript:
NOTREACHED_NORETURN();
- break;
case CPDF_Action::Type::kSetOCGState:
case CPDF_Action::Type::kThread:
case CPDF_Action::Type::kSound:
@@ -1123,7 +1122,6 @@ void CPDFSDK_FormFillEnvironment::RunFieldJavaScript(
break;
default:
NOTREACHED_NORETURN();
- break;
}
});
}
@@ -1170,7 +1168,6 @@ void CPDFSDK_FormFillEnvironment::RunDocumentPageJavaScript(
break;
default:
NOTREACHED_NORETURN();
- break;
}
});
}
diff --git a/fpdfsdk/cpdfsdk_formfillenvironment.h b/fpdfsdk/cpdfsdk_formfillenvironment.h
index f82f34696..3be1962af 100644
--- a/fpdfsdk/cpdfsdk_formfillenvironment.h
+++ b/fpdfsdk/cpdfsdk_formfillenvironment.h
@@ -28,7 +28,7 @@
#include "fpdfsdk/pwl/cpwl_wnd.h"
#include "fpdfsdk/pwl/ipwl_fillernotify.h"
#include "public/fpdf_formfill.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CPDF_Action;
class CPDF_FormField;
diff --git a/fpdfsdk/cpdfsdk_helpers.h b/fpdfsdk/cpdfsdk_helpers.h
index 076cac77d..f66adbfa8 100644
--- a/fpdfsdk/cpdfsdk_helpers.h
+++ b/fpdfsdk/cpdfsdk_helpers.h
@@ -14,7 +14,6 @@
#include "core/fpdfapi/parser/cpdf_parser.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxge/cfx_path.h"
-#include "core/fxge/dib/cfx_dibitmap.h"
#include "public/fpdf_doc.h"
#include "public/fpdf_ext.h"
#include "public/fpdfview.h"
@@ -39,6 +38,7 @@ class CPDF_TextPage;
class CPDF_TextPageFind;
class CPDFSDK_FormFillEnvironment;
class CPDFSDK_InteractiveForm;
+class CFX_DIBitmap;
struct CPDF_JavaScript;
struct XObjectContext;
diff --git a/fpdfsdk/cpdfsdk_renderpage.cpp b/fpdfsdk/cpdfsdk_renderpage.cpp
index 9ffd68317..757aa1f6b 100644
--- a/fpdfsdk/cpdfsdk_renderpage.cpp
+++ b/fpdfsdk/cpdfsdk_renderpage.cpp
@@ -69,6 +69,7 @@ void RenderPageImpl(CPDF_PageRenderContext* pContext,
CPDF_AnnotList* pList = pOwnedList.get();
pContext->m_pAnnots = std::move(pOwnedList);
bool bPrinting =
+ (flags & FPDF_PRINTING) ||
pContext->m_pDevice->GetDeviceType() != DeviceType::kDisplay;
// TODO(https://crbug.com/pdfium/993) - maybe pass true here.
diff --git a/fpdfsdk/cpdfsdk_widget.cpp b/fpdfsdk/cpdfsdk_widget.cpp
index c336f5e94..0b8083e41 100644
--- a/fpdfsdk/cpdfsdk_widget.cpp
+++ b/fpdfsdk/cpdfsdk_widget.cpp
@@ -177,7 +177,6 @@ static XFA_EVENTTYPE GetXFAEventType(CPDF_AAction::AActionType eAAT,
case CPDF_AAction::kDocumentOpen:
case CPDF_AAction::kNumberOfActions:
NOTREACHED_NORETURN();
- break;
}
return eEventType;
diff --git a/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp b/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp
index 5137429ff..843af8cb7 100644
--- a/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp
+++ b/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp
@@ -6,6 +6,8 @@
#include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
+#include <algorithm>
+
#include "constants/access_permissions.h"
#include "constants/ascii.h"
#include "constants/form_flags.h"
@@ -24,7 +26,6 @@
#include "fpdfsdk/formfiller/cffl_textfield.h"
#include "public/fpdf_fwlevent.h"
#include "third_party/base/check.h"
-#include "third_party/base/cxx17_backports.h"
CFFL_InteractiveFormFiller::CFFL_InteractiveFormFiller(
CallbackIface* pCallbackIface)
@@ -652,7 +653,7 @@ void CFFL_InteractiveFormFiller::QueryWherePopup(
constexpr float kMaxListBoxHeight = 140;
const float fMaxListBoxHeight =
- pdfium::clamp(kMaxListBoxHeight, fPopupMin, fPopupMax);
+ std::clamp(kMaxListBoxHeight, fPopupMin, fPopupMax);
if (fBottom > fMaxListBoxHeight) {
*fPopupRet = fMaxListBoxHeight;
diff --git a/fpdfsdk/formfiller/cffl_perwindowdata.cpp b/fpdfsdk/formfiller/cffl_perwindowdata.cpp
index 70dc696f0..85f6d0360 100644
--- a/fpdfsdk/formfiller/cffl_perwindowdata.cpp
+++ b/fpdfsdk/formfiller/cffl_perwindowdata.cpp
@@ -7,7 +7,7 @@
#include "fpdfsdk/formfiller/cffl_perwindowdata.h"
#include "fpdfsdk/cpdfsdk_widget.h"
-#include "third_party/base/ptr_util.h"
+#include "third_party/base/memory/ptr_util.h"
CFFL_PerWindowData::CFFL_PerWindowData(CPDFSDK_Widget* pWidget,
const CPDFSDK_PageView* pPageView,
diff --git a/fpdfsdk/fpdf_annot.cpp b/fpdfsdk/fpdf_annot.cpp
index 7c7d42044..cb7c96d01 100644
--- a/fpdfsdk/fpdf_annot.cpp
+++ b/fpdfsdk/fpdf_annot.cpp
@@ -39,8 +39,8 @@
#include "fpdfsdk/cpdfsdk_interactiveform.h"
#include "third_party/base/check.h"
#include "third_party/base/containers/contains.h"
+#include "third_party/base/memory/ptr_util.h"
#include "third_party/base/numerics/safe_conversions.h"
-#include "third_party/base/ptr_util.h"
namespace {
diff --git a/fpdfsdk/fpdf_annot_embeddertest.cpp b/fpdfsdk/fpdf_annot_embeddertest.cpp
index 06da6a8d2..9769570d6 100644
--- a/fpdfsdk/fpdf_annot_embeddertest.cpp
+++ b/fpdfsdk/fpdf_annot_embeddertest.cpp
@@ -29,7 +29,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/utils/hash.h"
#include "third_party/base/containers/contains.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
using pdfium::AnnotationStampWithApChecksum;
@@ -547,8 +547,13 @@ TEST_F(FPDFAnnotEmbedderTest, ExtractInkMultiple) {
}
{
const char* expected_hash = []() {
- if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "fad91b9c968fe8019a774f5e2419b8fc";
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+#if BUILDFLAG(IS_APPLE)
+ return "6e00cc75639c5314c8273072915d8f92";
+#else
+ return "1fb0dd8dd5f0b9bb8d076e48eb59296d";
+#endif
+ }
return "354002e1c4386d38fdde29ef8d61074a";
}();
ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
@@ -768,8 +773,13 @@ TEST_F(FPDFAnnotEmbedderTest, AddAndSaveUnderlineAnnotation) {
// Open the saved document.
const char* checksum = []() {
- if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "899387ae792390cd0d83cf7e2bbebfb5";
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+#if BUILDFLAG(IS_APPLE)
+ return "24994ad69aa612a66d183eaf9a92aa06";
+#else
+ return "798fa41303381c9ba6d99092f5cd4d2b";
+#endif
+ }
return "dba153419f67b7c0c0e3d22d3e8910d5";
}();
@@ -887,7 +897,7 @@ TEST_F(FPDFAnnotEmbedderTest, GetAndSetQuadPoints) {
TEST_F(FPDFAnnotEmbedderTest, ModifyRectQuadpointsWithAP) {
const char* md5_original = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "0dd4c099b93d24eed9926a948ac5101c";
+ return "2a9d1df839d5ec81a49f982347d9656c";
#if BUILDFLAG(IS_APPLE)
return "fc59468d154f397fd298c69f47ef565a";
#else
@@ -896,7 +906,7 @@ TEST_F(FPDFAnnotEmbedderTest, ModifyRectQuadpointsWithAP) {
}();
const char* md5_modified_highlight = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "92dfe7960d248635a694f43c66db7a4d";
+ return "0fb1653db0e8e8f7ce5d726bb0074bb5";
#if BUILDFLAG(IS_APPLE)
return "e64bf648f6e9354d1f3eedb47a2c9498";
#else
@@ -905,7 +915,7 @@ TEST_F(FPDFAnnotEmbedderTest, ModifyRectQuadpointsWithAP) {
}();
const char* md5_modified_square = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "fac81632e33fd5c06f39082a26d06ba8";
+ return "879c77a2cb9f79ba65ffe0bbdd720ce3";
#if BUILDFLAG(IS_APPLE)
return "a66591662c8e7ad3c6059952e234bebf";
#else
@@ -1106,7 +1116,7 @@ TEST_F(FPDFAnnotEmbedderTest, RemoveAnnotation) {
TEST_F(FPDFAnnotEmbedderTest, AddAndModifyPath) {
const char* md5_modified_path = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "f671765166acf45d80e833ea3aff8b90";
+ return "fb4d5fac05f7eb5d84a4100898c11197";
#if BUILDFLAG(IS_APPLE)
return "34614087e04b729b7b8c37739dcf9af9";
#else
@@ -1115,7 +1125,7 @@ TEST_F(FPDFAnnotEmbedderTest, AddAndModifyPath) {
}();
const char* md5_two_paths = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "491ce8fb274cc83b55b6099f15457b5d";
+ return "fcf3e79b2a91d1294b9bbccff727d3c2";
#if BUILDFLAG(IS_APPLE)
return "6cdaf6b3e5145f435d8ccae6db5cf9af";
#else
@@ -1124,7 +1134,7 @@ TEST_F(FPDFAnnotEmbedderTest, AddAndModifyPath) {
}();
const char* md5_new_annot = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "92bfb06058ff608571a3baf65f7fc05d";
+ return "7db6321c8ffe502f4e60622aa16d5417";
#if BUILDFLAG(IS_APPLE)
return "55dab4f158fdc284e439b88c4306373c";
#else
@@ -1327,7 +1337,7 @@ TEST_F(FPDFAnnotEmbedderTest, ModifyAnnotationFlags) {
TEST_F(FPDFAnnotEmbedderTest, AddAndModifyImage) {
const char* md5_new_image = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "4ba31e174d873b3fda1d7a160d4a0e85";
+ return "476596330c0e7daa31f115005c1d36eb";
#if BUILDFLAG(IS_APPLE)
return "17ac49518eabbb6a7632a547269c40a3";
#else
@@ -1336,7 +1346,7 @@ TEST_F(FPDFAnnotEmbedderTest, AddAndModifyImage) {
}();
const char* md5_modified_image = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "5806fadc1a192bc4bb07511a0711c957";
+ return "0047c3e7ea7658e1a963fc339f1c587d";
#if BUILDFLAG(IS_APPLE)
return "ce68959f74242d588af7fb82be5ba0ab";
#else
@@ -1417,8 +1427,9 @@ TEST_F(FPDFAnnotEmbedderTest, AddAndModifyImage) {
TEST_F(FPDFAnnotEmbedderTest, AddAndModifyText) {
const char* md5_new_text = []() {
- if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "63b931799a9ba21c36d9d4f9711f252b";
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "1e7f98c18775d6e0f4f454747b77cc1a";
+ }
#if BUILDFLAG(IS_APPLE) && defined(ARCH_CPU_ARM64)
return "0c3448974a4e8da2395da917935e5de1";
#elif BUILDFLAG(IS_APPLE) && !defined(ARCH_CPU_ARM64)
@@ -1428,8 +1439,9 @@ TEST_F(FPDFAnnotEmbedderTest, AddAndModifyText) {
#endif
}();
const char* md5_modified_text = []() {
- if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "e29ddba6a49d5c9c5cdde7d1693a251c";
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "37e35705946806f8f98c51e4e25647a2";
+ }
#if BUILDFLAG(IS_APPLE) && defined(ARCH_CPU_ARM64)
return "9cf1c024a9d2d356bcdd14cb71a32324";
#elif BUILDFLAG(IS_APPLE) && !defined(ARCH_CPU_ARM64)
@@ -1567,7 +1579,7 @@ TEST_F(FPDFAnnotEmbedderTest, GetSetStringValue) {
const char* md5 = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "2b9078043cd6130fef4e8542dcda943e";
+ return "a95a65d109eda5671c793ff5f7d2a2df";
#if BUILDFLAG(IS_APPLE)
return "52e93c54796f7f7167edf64e81d12bd7";
#else
@@ -3031,7 +3043,7 @@ TEST_F(FPDFAnnotEmbedderTest, FocusableAnnotRendering) {
{
const char* md5_sum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "08b693ba461a24ee6b9c7f86b5dbe191";
+ return "c09b129c071ec1569deb003676b617b0";
#if BUILDFLAG(IS_APPLE)
return "108a46c517c4eaace9982ee83e8e3296";
#else
@@ -3059,7 +3071,7 @@ TEST_F(FPDFAnnotEmbedderTest, FocusableAnnotRendering) {
{
const char* md5_sum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "3e6ae77a45e49bfd909f3ee0351a4176";
+ return "277f1b9e70031539d034d22bc6064838";
#if BUILDFLAG(IS_APPLE)
return "eb3869335e7a219e1b5f25c1c6037b97";
#else
@@ -3078,7 +3090,7 @@ TEST_F(FPDFAnnotEmbedderTest, FocusableAnnotRendering) {
{
const char* md5_sum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "12bb575d925923ad6672f427c574eef4";
+ return "d980005939cd4ae0a199d8600a0abdf3";
#if BUILDFLAG(IS_APPLE)
return "d20b1978da2362d3942ea0fc6d230997";
#else
@@ -3653,18 +3665,24 @@ TEST_F(FPDFAnnotEmbedderTest, AnnotationBorderRendering) {
EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
const char* original_checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "238dccc7df0ac61ac580c28e1109da3c";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "522a4a6b6c7eab5bf95ded1f21ea372e";
-#endif
+ return "522a4a6b6c7eab5bf95ded1f21ea372e";
+#else
return "12127303aecd80c6288460f7c0d79f3f";
+#endif
}();
const char* modified_checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "0f326acb3eb583125ca584d703ccb13b";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "6844019e07b83cc01723415f58218d06";
-#endif
+ return "6844019e07b83cc01723415f58218d06";
+#else
return "73d06ff4c665fe85029acef30240dcca";
+#endif
}();
{
diff --git a/fpdfsdk/fpdf_dataavail.cpp b/fpdfsdk/fpdf_dataavail.cpp
index e4f85ebf1..f0ce10197 100644
--- a/fpdfsdk/fpdf_dataavail.cpp
+++ b/fpdfsdk/fpdf_dataavail.cpp
@@ -17,6 +17,7 @@
#include "core/fxcrt/fx_stream.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/unowned_ptr.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
#include "public/fpdf_formfill.h"
#include "third_party/base/numerics/safe_conversions.h"
@@ -64,7 +65,8 @@ class FPDF_FileAvailContext final : public CPDF_DataAvail::FileAvail {
}
private:
- FX_FILEAVAIL* const avail_;
+ // TODO(tsepez): fix murky ownership in tests.
+ UNOWNED_PTR_EXCLUSION FX_FILEAVAIL* const avail_;
};
class FPDF_FileAccessContext final : public IFX_SeekableReadStream {
@@ -95,7 +97,8 @@ class FPDF_FileAccessContext final : public IFX_SeekableReadStream {
explicit FPDF_FileAccessContext(FPDF_FILEACCESS* file) : file_(file) {}
~FPDF_FileAccessContext() override = default;
- FPDF_FILEACCESS* const file_;
+ // TODO(tsepez): fix murky ownership in tests.
+ UNOWNED_PTR_EXCLUSION FPDF_FILEACCESS* const file_;
};
class FPDF_DownloadHintsContext final : public CPDF_DataAvail::DownloadHints {
diff --git a/fpdfsdk/fpdf_edit_embeddertest.cpp b/fpdfsdk/fpdf_edit_embeddertest.cpp
index 670892a98..19097d869 100644
--- a/fpdfsdk/fpdf_edit_embeddertest.cpp
+++ b/fpdfsdk/fpdf_edit_embeddertest.cpp
@@ -48,26 +48,32 @@ const char kAllRemovedChecksum[] = "eee4600ac08b458ac7ac2320e225674c";
const wchar_t kBottomText[] = L"I'm at the bottom of the page";
const char* BottomTextChecksum() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "c62d315856a558d2666b80d474831efe";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "81636489006a31fcb00cf29efcdf7909";
-#endif
+ return "81636489006a31fcb00cf29efcdf7909";
+#else
return "891dcb6e914c8360998055f1f47c9727";
+#endif
}
const char* FirstRemovedChecksum() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "3006ab2b12d27246eae4faad509ac575";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "a1dc2812692fcc7ee4f01ca77435df9d";
-#endif
+ return "a1dc2812692fcc7ee4f01ca77435df9d";
+#else
return "e1477dc3b5b3b9c560814c4d1135a02b";
+#endif
}
const wchar_t kLoadedFontText[] = L"I am testing my loaded font, WEE.";
const char* LoadedFontTextChecksum() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "d58570cc045dfb818b92cbabbd1a364c";
+ return "fc2334c350cbd0d2ae6076689da09741";
#if BUILDFLAG(IS_APPLE)
return "0f3e4a7d71f9e7eb8a1a0d69403b9848";
#else
@@ -260,12 +266,21 @@ TEST_F(FPDFEditEmbedderTest, EmbedNotoSansSCFont) {
FPDFPage_InsertObject(page.get(), text_object);
EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
- const char kChecksum[] = "9a31fb87d1c6d2346bba22d1196041cd";
+ const char* checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+#if BUILDFLAG(IS_APPLE)
+ return "9a31fb87d1c6d2346bba22d1196041cd";
+#else
+ return "5bb65e15fc0a685934cd5006dec08a76";
+#endif
+ }
+ return "9a31fb87d1c6d2346bba22d1196041cd";
+ }();
ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
- CompareBitmap(page_bitmap.get(), 400, 400, kChecksum);
+ CompareBitmap(page_bitmap.get(), 400, 400, checksum);
ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
- VerifySavedDocument(400, 400, kChecksum);
+ VerifySavedDocument(400, 400, checksum);
}
TEST_F(FPDFEditEmbedderTest, EmbedNotoSansSCFontWithCharcodes) {
@@ -297,12 +312,21 @@ TEST_F(FPDFEditEmbedderTest, EmbedNotoSansSCFontWithCharcodes) {
FPDFPage_InsertObject(page.get(), text_object);
EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
- const char kChecksum[] = "9a31fb87d1c6d2346bba22d1196041cd";
+ const char* checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+#if BUILDFLAG(IS_APPLE)
+ return "9a31fb87d1c6d2346bba22d1196041cd";
+#else
+ return "5bb65e15fc0a685934cd5006dec08a76";
+#endif
+ }
+ return "9a31fb87d1c6d2346bba22d1196041cd";
+ }();
ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
- CompareBitmap(page_bitmap.get(), 400, 400, kChecksum);
+ CompareBitmap(page_bitmap.get(), 400, 400, checksum);
ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
- VerifySavedDocument(400, 400, kChecksum);
+ VerifySavedDocument(400, 400, checksum);
}
TEST_F(FPDFEditEmbedderTest, EmptyCreation) {
@@ -718,11 +742,14 @@ TEST_F(FPDFEditEmbedderTest, SetText) {
ASSERT_EQ(2, FPDFPage_CountObjects(page));
const char* changed_checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "4a8345a139507932729e07d4831cbe2b";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "b720e83476fd6819d47c533f1f43c728";
-#endif
+ return "b720e83476fd6819d47c533f1f43c728";
+#else
return "9a85b9354a69c61772ed24151c140f46";
+#endif
}();
{
ScopedFPDFBitmap page_bitmap = RenderPage(page);
@@ -775,11 +802,14 @@ TEST_F(FPDFEditEmbedderTest, SetTextKeepClippingPath) {
ASSERT_TRUE(page);
const char* original_checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "3c04e3acc732faaf39fb0c19efd056ac";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "ae7a25c85e0e2dd0c5cb9dd5cd37f6df";
-#endif
+ return "ae7a25c85e0e2dd0c5cb9dd5cd37f6df";
+#else
return "7af7fe5b281298261eb66ac2d22f5054";
+#endif
}();
{
// When opened before any editing and saving, the clipping path is rendered.
@@ -840,11 +870,14 @@ TEST_F(FPDFEditEmbedderTest, BUG_1574) {
ASSERT_TRUE(page);
const char* original_checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "d76a31d931a350f0809226a41029a9a4";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "1226bc2b8072622eb28f52321876e814";
-#endif
+ return "1226bc2b8072622eb28f52321876e814";
+#else
return "c5241eef60b9eac68ed1f2a5fd002703";
+#endif
}();
{
// When opened before any editing and saving, the text object is rendered.
@@ -1243,7 +1276,7 @@ TEST_F(FPDFEditEmbedderTest, RemoveMarkedObjectsPrime) {
{
const char* original_checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "34ac4e0f3ba510760be09d0e19c1b43e";
+ return "efc2206b313fff03be8e701907322b06";
#if BUILDFLAG(IS_APPLE)
#ifdef ARCH_CPU_ARM64
return "cdc8e22cf1e7e06999dc456288672a3b";
@@ -1293,7 +1326,7 @@ TEST_F(FPDFEditEmbedderTest, RemoveMarkedObjectsPrime) {
EXPECT_EQ(11, FPDFPage_CountObjects(page));
const char* non_primes_checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "c671fa07b63e85c4201b9926e880fda8";
+ return "10a6558c9e40ea837922e6f2882a2d57";
#if BUILDFLAG(IS_APPLE)
#ifdef ARCH_CPU_ARM64
return "23c4aec321547f51591fe7363a9ea2d6";
@@ -1306,7 +1339,7 @@ TEST_F(FPDFEditEmbedderTest, RemoveMarkedObjectsPrime) {
}();
const char* non_primes_after_save_checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "c671fa07b63e85c4201b9926e880fda8";
+ return "10a6558c9e40ea837922e6f2882a2d57";
#if BUILDFLAG(IS_APPLE)
#ifdef ARCH_CPU_ARM64
return "6bb1ea0d0a512f29edabda33064a0725";
@@ -1591,11 +1624,14 @@ TEST_F(FPDFEditEmbedderTest, RemoveExistingPageObjectSplitStreamsNotLonely) {
// Verify the "Hello, world!" text is gone.
ASSERT_EQ(2, FPDFPage_CountObjects(page));
const char* hello_removed_checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "204c11472f5b93719487de7b9c1b1c93";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "5508c2f06d104050f74f655693e38c2c";
-#endif
+ return "5508c2f06d104050f74f655693e38c2c";
+#else
return "a8cd82499cf744e0862ca468c9d4ceb8";
+#endif
}();
{
ScopedFPDFBitmap page_bitmap = RenderPage(page);
@@ -1750,7 +1786,7 @@ TEST_F(FPDFEditEmbedderTest, RemoveAllFromStream) {
const char* stream1_removed_checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "b9bb0acfdba4bb5d2e578e7b73341baf";
+ return "0b3ef335b8d86a3f9d609368b9d075e0";
#if BUILDFLAG(IS_APPLE)
#if ARCH_CPU_ARM64
return "08505db7b598f7397a2260ecb1f6d86d";
@@ -2268,7 +2304,7 @@ TEST_F(FPDFEditEmbedderTest, PathOnTopOfText) {
ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
const char* checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "8a48b019826492331454f2809990aba8";
+ return "72523cfac069f8a81057164682998961";
#if BUILDFLAG(IS_APPLE)
return "279693baca9f48da2d75a8e289aed58e";
#else
@@ -2453,11 +2489,14 @@ TEST_F(FPDFEditEmbedderTest, AddStandardFontText) {
{
ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
const char* checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "3fa05f8935a43a38a8923e9d5fb94365";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "983baaa1f688eff7a14b1bf91c171a1a";
-#endif
+ return "983baaa1f688eff7a14b1bf91c171a1a";
+#else
return "161523e196eb5341604cd73e12c97922";
+#endif
}();
CompareBitmap(page_bitmap.get(), 612, 792, checksum);
@@ -2477,11 +2516,14 @@ TEST_F(FPDFEditEmbedderTest, AddStandardFontText) {
{
ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
const char* checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "63385a217934d9ee9e17ef4d7f7b2128";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "e0b3493c5c16e41d0d892ffb48e63fba";
-#endif
+ return "e0b3493c5c16e41d0d892ffb48e63fba";
+#else
return "1fbf772dca8d82b960631e6683934964";
+#endif
}();
CompareBitmap(page_bitmap.get(), 612, 792, checksum);
@@ -2558,7 +2600,7 @@ TEST_F(FPDFEditEmbedderTest, GetTextRenderMode) {
TEST_F(FPDFEditEmbedderTest, SetTextRenderMode) {
const char* original_checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "39a4ac8f1fdc6653edd3b91862ea7b75";
+ return "48c7f21b2a1a1bbeab24cccccc131e47";
#if BUILDFLAG(IS_APPLE)
return "c488514ce0fc949069ff560407edacd2";
#else
@@ -2885,18 +2927,24 @@ TEST_F(FPDFEditEmbedderTest, FormGetObjects) {
TEST_F(FPDFEditEmbedderTest, ModifyFormObject) {
const char* orig_checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "1c6dae4b04fea7430a791135721eaba5";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "a637057185f50aac1aa5490f726aef95";
-#endif
+ return "a637057185f50aac1aa5490f726aef95";
+#else
return "34a9ec0a9581a7970e073c0bcc4ca676";
+#endif
}();
const char* new_checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "7282fe98693c0a7ad2c1b3f3f9563977";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "8ad9d79b02b609ff734e2a2195c96e2d";
-#endif
+ return "8ad9d79b02b609ff734e2a2195c96e2d";
+#else
return "609b5632a21c886fa93182dbc290bf7a";
+#endif
}();
ASSERT_TRUE(OpenDocument("form_object.pdf"));
@@ -3320,7 +3368,7 @@ TEST_F(FPDFEditEmbedderTest, AddTrueTypeFontText) {
ScopedFPDFBitmap page_bitmap2 = RenderPage(page);
const char* insert_true_type_checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "683f4a385a891494100192cb338b11f0";
+ return "4f9a6c7752ac7d4e4c731260fdb5af15";
#if BUILDFLAG(IS_APPLE)
return "c7e2271a7f30e5b919a13ead47cea105";
#else
@@ -3397,10 +3445,16 @@ TEST_F(FPDFEditEmbedderTest, AddCIDFontText) {
}
// Check that the text renders properly.
- static constexpr char kChecksum[] = "84d31d11b76845423a2cfc1879c0fbb9";
+ const char* checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "2e174d17de96a760d42ca3a06acbf36a";
+ }
+ return "84d31d11b76845423a2cfc1879c0fbb9";
+ }();
+
{
ScopedFPDFBitmap page_bitmap = RenderPage(page);
- CompareBitmap(page_bitmap.get(), 612, 792, kChecksum);
+ CompareBitmap(page_bitmap.get(), 612, 792, checksum);
}
// Save the document, close the page.
@@ -3408,7 +3462,7 @@ TEST_F(FPDFEditEmbedderTest, AddCIDFontText) {
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
FPDF_ClosePage(page);
- VerifySavedDocument(612, 792, kChecksum);
+ VerifySavedDocument(612, 792, checksum);
}
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
@@ -4141,13 +4195,15 @@ TEST_F(FPDFEditEmbedderTest, GetRenderedBitmapHandlesSMask) {
ASSERT_EQ(kExpectedObjects, FPDFPage_CountObjects(page));
const char* smask_checksum = []() {
- if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
return "0653a18f3bf9b4d8413a2aa10bc11c38";
+ }
return "5a3ae4a660ce919e29c42ec2258142f1";
}();
const char* no_smask_checksum = []() {
- if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "d568afc908d595224d804448d5d3672f";
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "0da49e63e7d6337aca78b19938e3bf65";
+ }
return "67504e83f5d78214ea00efc19082c5c1";
}();
@@ -4477,21 +4533,31 @@ TEST_F(FPDFEditEmbedderTest, GetRenderedBitmapForHelloWorldText) {
ScopedFPDFBitmap bitmap(
FPDFTextObj_GetRenderedBitmap(document(), page, text_object, 1));
ASSERT_TRUE(bitmap);
- const char kChecksum[] = "bb0abe1accca1cfeaaf78afa35762350";
- CompareBitmap(bitmap.get(), 64, 11, kChecksum);
+ const char* checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "b17801afe8a36d6aad6c2239b88f2a73";
+ }
+ return "bb0abe1accca1cfeaaf78afa35762350";
+ }();
+ CompareBitmap(bitmap.get(), 64, 11, checksum);
ScopedFPDFBitmap x2_bitmap(
FPDFTextObj_GetRenderedBitmap(document(), page, text_object, 2.4f));
ASSERT_TRUE(x2_bitmap);
- const char kX2Checksum[] = "80db528ec7146d92247f2339a8f10ba5";
- CompareBitmap(x2_bitmap.get(), 153, 25, kX2Checksum);
+ const char* x2_checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "33af8b151ab26ebce5a71b39eedea6b1";
+ }
+ return "80db528ec7146d92247f2339a8f10ba5";
+ }();
+ CompareBitmap(x2_bitmap.get(), 153, 25, x2_checksum);
ScopedFPDFBitmap x10_bitmap(
FPDFTextObj_GetRenderedBitmap(document(), page, text_object, 10));
ASSERT_TRUE(x10_bitmap);
const char* x10_checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "f5e86739b9603838cbfb0c7f8e54e4ae";
+ return "93dd7ad07bdaaba9ecd268350cb91596";
return "149f63de758ab01d3b75605cdfd4c176";
}();
CompareBitmap(x10_bitmap.get(), 631, 103, x10_checksum);
@@ -4504,21 +4570,31 @@ TEST_F(FPDFEditEmbedderTest, GetRenderedBitmapForHelloWorldText) {
ScopedFPDFBitmap bitmap(
FPDFTextObj_GetRenderedBitmap(document(), page, text_object, 1));
ASSERT_TRUE(bitmap);
- const char kChecksum[] = "3fc1101b2408c5484adc24ba0a11ff3d";
- CompareBitmap(bitmap.get(), 116, 16, kChecksum);
+ const char* checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "63fd059d984a5bea10f27ba026420202";
+ }
+ return "3fc1101b2408c5484adc24ba0a11ff3d";
+ }();
+ CompareBitmap(bitmap.get(), 116, 16, checksum);
ScopedFPDFBitmap x2_bitmap(
FPDFTextObj_GetRenderedBitmap(document(), page, text_object, 2.4f));
ASSERT_TRUE(x2_bitmap);
- const char kX2Checksum[] = "429960ae7b822f0c630432535e637465";
- CompareBitmap(x2_bitmap.get(), 276, 36, kX2Checksum);
+ const char* x2_checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "fc45021e3ea3ebd406fe6ffaa8c5c5b7";
+ }
+ return "429960ae7b822f0c630432535e637465";
+ }();
+ CompareBitmap(x2_bitmap.get(), 276, 36, x2_checksum);
ScopedFPDFBitmap x10_bitmap(
FPDFTextObj_GetRenderedBitmap(document(), page, text_object, 10));
ASSERT_TRUE(x10_bitmap);
const char* x10_checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "59d0b5f1fc2a1cc0c392e213909bbbb6";
+ return "61476636eaa0da0b93d8b1937cf22b75";
return "f5f93bf64de579b59e775d7076ca0a5a";
}();
CompareBitmap(x10_bitmap.get(), 1143, 150, x10_checksum);
@@ -4538,21 +4614,31 @@ TEST_F(FPDFEditEmbedderTest, GetRenderedBitmapForRotatedText) {
ScopedFPDFBitmap bitmap(
FPDFTextObj_GetRenderedBitmap(document(), page, text_object, 1));
ASSERT_TRUE(bitmap);
- const char kChecksum[] = "08ada0802f780d3fefb161dc6fb45977";
- CompareBitmap(bitmap.get(), 29, 28, kChecksum);
+ const char* checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "f515a7209d7892065d3716ec462f5c10";
+ }
+ return "08ada0802f780d3fefb161dc6fb45977";
+ }();
+ CompareBitmap(bitmap.get(), 29, 28, checksum);
ScopedFPDFBitmap x2_bitmap(
FPDFTextObj_GetRenderedBitmap(document(), page, text_object, 2.4f));
ASSERT_TRUE(x2_bitmap);
- const char kX2Checksum[] = "09d7ddb647b8653cb59aede349a0c3e1";
- CompareBitmap(x2_bitmap.get(), 67, 67, kX2Checksum);
+ const char* x2_checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "c69bbe5318ec149f63228e276e708612";
+ }
+ return "09d7ddb647b8653cb59aede349a0c3e1";
+ }();
+ CompareBitmap(x2_bitmap.get(), 67, 67, x2_checksum);
ScopedFPDFBitmap x10_bitmap(
FPDFTextObj_GetRenderedBitmap(document(), page, text_object, 10));
ASSERT_TRUE(x10_bitmap);
const char* x10_checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "839dc0eed66eab6d545833f25b37031e";
+ return "bb7c2ec575f27cf882dcd38f2563c00f";
return "bbd3842a4b50dbfcbce4eee2b067a297";
}();
CompareBitmap(x10_bitmap.get(), 275, 275, x10_checksum);
@@ -4595,8 +4681,13 @@ TEST_F(FPDFEditEmbedderTest, GetRenderedBitmapForNewlyCreatedText) {
ScopedFPDFBitmap bitmap(
FPDFTextObj_GetRenderedBitmap(document(), nullptr, text_object.get(), 1));
ASSERT_TRUE(bitmap);
- const char kChecksum[] = "fa947759dab76d68a07ccf6f97b2d9c2";
- CompareBitmap(bitmap.get(), 151, 12, kChecksum);
+ const char* checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "574ae982d02e653ab6a8f23a6cdf4085";
+ }
+ return "fa947759dab76d68a07ccf6f97b2d9c2";
+ }();
+ CompareBitmap(bitmap.get(), 151, 12, checksum);
}
TEST_F(FPDFEditEmbedderTest, GetRenderedBitmapForTextWithBadParameters) {
@@ -4647,3 +4738,33 @@ TEST_F(FPDFEditEmbedderTest, GetRenderedBitmapForTextWithBadParameters) {
UnloadPage(page);
}
+
+TEST_F(FPDFEditEmbedderTest, MultipleGraphicsStates) {
+ ASSERT_TRUE(OpenDocument("multiple_graphics_states.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+
+ {
+ ScopedFPDFPageObject path(FPDFPageObj_CreateNewPath(400, 100));
+ EXPECT_TRUE(FPDFPageObj_SetFillColor(path.get(), 255, 0, 0, 255));
+ EXPECT_TRUE(FPDFPath_SetDrawMode(path.get(), FPDF_FILLMODE_ALTERNATE, 0));
+ EXPECT_TRUE(FPDFPath_MoveTo(path.get(), 100, 100));
+ EXPECT_TRUE(FPDFPath_LineTo(path.get(), 100, 125));
+ EXPECT_TRUE(FPDFPath_Close(path.get()));
+
+ FPDFPage_InsertObject(page, path.release());
+ EXPECT_TRUE(FPDFPage_GenerateContent(page));
+ }
+
+ const char* checksum = CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()
+ ? "7ebec75d95c64b522999a710de76c52c"
+ : "f4b36616a7fea81a4f06cc7b01a55ac1";
+
+ ScopedFPDFBitmap bitmap = RenderPage(page);
+ CompareBitmap(bitmap.get(), 200, 300, checksum);
+
+ ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ VerifySavedDocument(200, 300, checksum);
+
+ UnloadPage(page);
+}
diff --git a/fpdfsdk/fpdf_editimg.cpp b/fpdfsdk/fpdf_editimg.cpp
index 3fae5b4ec..8e3402fa9 100644
--- a/fpdfsdk/fpdf_editimg.cpp
+++ b/fpdfsdk/fpdf_editimg.cpp
@@ -24,6 +24,7 @@
#include "core/fpdfapi/render/cpdf_renderstatus.h"
#include "core/fxcrt/stl_util.h"
#include "core/fxge/cfx_defaultrenderdevice.h"
+#include "core/fxge/dib/cfx_dibitmap.h"
#include "fpdfsdk/cpdfsdk_customaccess.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
diff --git a/fpdfsdk/fpdf_editpage.cpp b/fpdfsdk/fpdf_editpage.cpp
index 6cc64f2c4..3e6d7fdf0 100644
--- a/fpdfsdk/fpdf_editpage.cpp
+++ b/fpdfsdk/fpdf_editpage.cpp
@@ -34,10 +34,10 @@
#include "core/fpdfdoc/cpdf_annot.h"
#include "core/fpdfdoc/cpdf_annotlist.h"
#include "core/fxcrt/fx_extension.h"
+#include "core/fxcrt/fx_memcpy_wrappers.h"
#include "core/fxcrt/stl_util.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
#include "public/fpdf_formfill.h"
-#include "third_party/base/cxx17_backports.h"
#include "third_party/base/numerics/safe_conversions.h"
#ifdef PDF_ENABLE_XFA
@@ -202,7 +202,7 @@ FPDF_EXPORT FPDF_PAGE FPDF_CALLCONV FPDFPage_New(FPDF_DOCUMENT document,
if (!pDoc)
return nullptr;
- page_index = pdfium::clamp(page_index, 0, pDoc->GetPageCount());
+ page_index = std::clamp(page_index, 0, pDoc->GetPageCount());
RetainPtr<CPDF_Dictionary> pPageDict(pDoc->CreateNewPage(page_index));
if (!pPageDict)
return nullptr;
@@ -967,7 +967,8 @@ FPDFPageObj_GetDashArray(FPDF_PAGEOBJECT page_object,
if (dash_vector.size() > dash_count)
return false;
- memcpy(dash_array, dash_vector.data(), dash_vector.size() * sizeof(float));
+ FXSYS_memcpy(dash_array, dash_vector.data(),
+ dash_vector.size() * sizeof(float));
return true;
}
diff --git a/fpdfsdk/fpdf_editpage_embeddertest.cpp b/fpdfsdk/fpdf_editpage_embeddertest.cpp
index c74d6dcd1..e6eba89f3 100644
--- a/fpdfsdk/fpdf_editpage_embeddertest.cpp
+++ b/fpdfsdk/fpdf_editpage_embeddertest.cpp
@@ -457,3 +457,50 @@ TEST_F(FPDFEditPageEmbedderTest, GetBoundsForRotatedImage) {
UnloadPage(page);
}
+
+TEST_F(FPDFEditPageEmbedderTest, VerifyDashArraySaved) {
+ constexpr float kDashArray[] = {2.5, 3.6};
+ constexpr float kDashPhase = 1.2;
+
+ CreateEmptyDocument();
+ {
+ ScopedFPDFPage page(FPDFPage_New(document(), 0, 612, 792));
+
+ FPDF_PAGEOBJECT path = FPDFPageObj_CreateNewPath(400, 100);
+ EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(path, 2));
+ EXPECT_TRUE(FPDFPageObj_SetStrokeColor(path, 255, 0, 0, 255));
+ EXPECT_TRUE(FPDFPath_SetDrawMode(path, FPDF_FILLMODE_NONE, 1));
+ EXPECT_TRUE(FPDFPath_LineTo(path, 200, 200));
+ EXPECT_TRUE(FPDFPageObj_SetDashArray(path, kDashArray,
+ std::size(kDashArray), kDashPhase));
+ FPDFPage_InsertObject(page.get(), path);
+
+ EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
+ path = FPDFPage_GetObject(page.get(), 0);
+ ASSERT_TRUE(path);
+ ASSERT_EQ(2, FPDFPageObj_GetDashCount(path));
+
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ }
+
+ ASSERT_TRUE(OpenSavedDocument());
+ FPDF_PAGE page = LoadSavedPage(0);
+ ASSERT_TRUE(page);
+
+ FPDF_PAGEOBJECT path = FPDFPage_GetObject(page, 0);
+ ASSERT_TRUE(path);
+
+ float dash_array[] = {0, 0};
+ ASSERT_EQ(static_cast<int>(std::size(dash_array)),
+ FPDFPageObj_GetDashCount(path));
+ ASSERT_TRUE(
+ FPDFPageObj_GetDashArray(path, dash_array, std::size(dash_array)));
+ ASSERT_EQ(kDashArray[0], dash_array[0]);
+ ASSERT_EQ(kDashArray[1], dash_array[1]);
+ float dash_phase = 0;
+ ASSERT_TRUE(FPDFPageObj_GetDashPhase(path, &dash_phase));
+ ASSERT_EQ(kDashPhase, dash_phase);
+
+ CloseSavedPage(page);
+ CloseSavedDocument();
+}
diff --git a/fpdfsdk/fpdf_editpath.cpp b/fpdfsdk/fpdf_editpath.cpp
index 4d481f832..c0b8db357 100644
--- a/fpdfsdk/fpdf_editpath.cpp
+++ b/fpdfsdk/fpdf_editpath.cpp
@@ -12,7 +12,7 @@
#include "core/fxcrt/fx_system.h"
#include "core/fxcrt/stl_util.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
// These checks are here because core/ and public/ cannot depend on each other.
static_assert(static_cast<int>(CFX_GraphStateData::LineCap::kButt) ==
diff --git a/fpdfsdk/fpdf_edittext.cpp b/fpdfsdk/fpdf_edittext.cpp
index 467a8f39c..55ac4f7fe 100644
--- a/fpdfsdk/fpdf_edittext.cpp
+++ b/fpdfsdk/fpdf_edittext.cpp
@@ -31,8 +31,10 @@
#include "core/fxcrt/fx_string_wrappers.h"
#include "core/fxcrt/span_util.h"
#include "core/fxcrt/stl_util.h"
+#include "core/fxcrt/utf16.h"
#include "core/fxge/cfx_defaultrenderdevice.h"
#include "core/fxge/cfx_fontmgr.h"
+#include "core/fxge/dib/cfx_dibitmap.h"
#include "core/fxge/fx_font.h"
#include "core/fxge/text_char_pos.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
@@ -166,8 +168,9 @@ void AddCharcode(fxcrt::ostringstream* pBuffer, uint32_t number) {
// 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(fxcrt::ostringstream* pBuffer, uint32_t unicode) {
- if (unicode >= 0xD800 && unicode <= 0xDFFF)
+ if (pdfium::IsHighSurrogate(unicode) || pdfium::IsLowSurrogate(unicode)) {
unicode = 0;
+ }
char ans[8];
*pBuffer << "<";
@@ -369,16 +372,18 @@ RetainPtr<CPDF_Font> LoadCompositeFont(CPDF_Document* pDoc,
uint32_t dwGlyphIndex;
uint32_t dwCurrentChar = static_cast<uint32_t>(
FT_Get_First_Char(pFont->GetFaceRec(), &dwGlyphIndex));
- static constexpr uint32_t kMaxUnicode = 0x10FFFF;
// If it doesn't have a single char, just fail
- if (dwGlyphIndex == 0 || dwCurrentChar > kMaxUnicode)
+ if (dwGlyphIndex == 0 ||
+ dwCurrentChar > pdfium::kMaximumSupplementaryCodePoint) {
return nullptr;
+ }
std::multimap<uint32_t, uint32_t> to_unicode;
std::map<uint32_t, uint32_t> widths;
while (true) {
- if (dwCurrentChar > kMaxUnicode)
+ if (dwCurrentChar > pdfium::kMaximumSupplementaryCodePoint) {
break;
+ }
if (!pdfium::Contains(widths, dwGlyphIndex))
widths[dwGlyphIndex] = pFont->GetGlyphWidth(dwGlyphIndex);
diff --git a/fpdfsdk/fpdf_flatten.cpp b/fpdfsdk/fpdf_flatten.cpp
index 4eb8ebe5a..c62a4baf0 100644
--- a/fpdfsdk/fpdf_flatten.cpp
+++ b/fpdfsdk/fpdf_flatten.cpp
@@ -149,9 +149,6 @@ float GetMinMaxValue(const std::vector<CFX_FloatRect>& array,
for (size_t i = 0; i < nRects; i++)
pArray[i] = array[i].bottom;
break;
- default:
- NOTREACHED_NORETURN();
- return 0.0f;
}
float fRet = pArray[0];
diff --git a/fpdfsdk/fpdf_flatten_embeddertest.cpp b/fpdfsdk/fpdf_flatten_embeddertest.cpp
index 235ab889f..f3305b525 100644
--- a/fpdfsdk/fpdf_flatten_embeddertest.cpp
+++ b/fpdfsdk/fpdf_flatten_embeddertest.cpp
@@ -42,7 +42,7 @@ TEST_F(FPDFFlattenEmbedderTest, FlatPrint) {
TEST_F(FPDFFlattenEmbedderTest, BUG_861842) {
const char* checkbox_checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "252fd5f2299cc16e5a07565df7c30565";
+ return "95fdaa000e81c80892b8d370f77be970";
#if BUILDFLAG(IS_APPLE)
return "6aafcb2d98da222964bcdbf5aa1f4f1f";
#else
@@ -70,7 +70,7 @@ TEST_F(FPDFFlattenEmbedderTest, BUG_861842) {
TEST_F(FPDFFlattenEmbedderTest, BUG_889099) {
const char* page_checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "73678f308625e22f31940e9f732b68bf";
+ return "de7119d99f42deab2f4215017bdb16af";
#if BUILDFLAG(IS_APPLE)
return "049ed3f1e21fc72f929af3410c64bc8f";
#else
@@ -78,11 +78,14 @@ TEST_F(FPDFFlattenEmbedderTest, BUG_889099) {
#endif
}();
const char* flattened_page_checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "7978c7b3d643a5f0ac0f03ce759c55fe";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "41debc60cf2a8f74c710ec6082d77b18";
-#endif
+ return "41debc60cf2a8f74c710ec6082d77b18";
+#else
return "0832157462ea70fbbf053e14b1d6457f";
+#endif
}();
ASSERT_TRUE(OpenDocument("bug_889099.pdf"));
diff --git a/fpdfsdk/fpdf_formfill.cpp b/fpdfsdk/fpdf_formfill.cpp
index 8c1a083e5..ee72562b2 100644
--- a/fpdfsdk/fpdf_formfill.cpp
+++ b/fpdfsdk/fpdf_formfill.cpp
@@ -21,6 +21,7 @@
#include "core/fpdfdoc/cpdf_formfield.h"
#include "core/fpdfdoc/cpdf_interactiveform.h"
#include "core/fxge/cfx_defaultrenderdevice.h"
+#include "core/fxge/dib/cfx_dibitmap.h"
#include "fpdfsdk/cpdfsdk_annot.h"
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
@@ -31,7 +32,13 @@
#ifdef PDF_ENABLE_XFA
#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
+#endif // PDF_ENABLE_XFA
+
+#if defined(_SKIA_SUPPORT_)
+class SkCanvas;
+#endif // defined(_SKIA_SUPPORT_)
+#ifdef PDF_ENABLE_XFA
static_assert(static_cast<int>(AlertButton::kDefault) ==
JSPLATFORM_ALERT_BUTTON_DEFAULT,
"Default alert button types must match");
@@ -171,7 +178,7 @@ CPDFSDK_PageView* FormHandleToPageView(FPDF_FORMHANDLE hHandle,
void FFLCommon(FPDF_FORMHANDLE hHandle,
FPDF_BITMAP bitmap,
- FPDF_RECORDER recorder,
+ FPDF_SKIA_CANVAS canvas,
FPDF_PAGE fpdf_page,
int start_x,
int start_y,
@@ -194,8 +201,9 @@ void FFLCommon(FPDF_FORMHANDLE hHandle,
auto pDevice = std::make_unique<CFX_DefaultRenderDevice>();
#if defined(_SKIA_SUPPORT_)
- if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- pDevice->AttachRecorder(static_cast<SkPictureRecorder*>(recorder));
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer() && canvas) {
+ pDevice->AttachCanvas(reinterpret_cast<SkCanvas*>(canvas));
+ }
#endif
RetainPtr<CFX_DIBitmap> holder(CFXDIBitmapFromFPDFBitmap(bitmap));
@@ -682,16 +690,16 @@ FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLDraw(FPDF_FORMHANDLE hHandle,
}
#if defined(_SKIA_SUPPORT_)
-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,
+FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLDrawSkia(FPDF_FORMHANDLE hHandle,
+ FPDF_SKIA_CANVAS canvas,
+ FPDF_PAGE page,
+ int start_x,
+ int start_y,
+ int size_x,
+ int size_y,
+ int rotate,
+ int flags) {
+ FFLCommon(hHandle, nullptr, canvas, page, start_x, start_y, size_x, size_y,
rotate, flags);
}
#endif
diff --git a/fpdfsdk/fpdf_formfill_embeddertest.cpp b/fpdfsdk/fpdf_formfill_embeddertest.cpp
index ea4af5743..3f3f51ebe 100644
--- a/fpdfsdk/fpdf_formfill_embeddertest.cpp
+++ b/fpdfsdk/fpdf_formfill_embeddertest.cpp
@@ -1321,7 +1321,7 @@ TEST_F(FPDFFormFillEmbedderTest, BUG_765384) {
TEST_F(FPDFFormFillEmbedderTest, FormText) {
const char* focused_text_form_with_abc_checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "07a179a9dfb8f5462746262984109a99";
+ return "b9fb2245a98ac48146da84237a37f8cc";
#if BUILDFLAG(IS_APPLE)
return "9fb14198d75ca0a107060c60ca21b0c7";
#else
@@ -1330,7 +1330,7 @@ TEST_F(FPDFFormFillEmbedderTest, FormText) {
}();
const char* unfocused_text_form_with_abc_checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "a21b74cc620db8a9891ebd69e1aeda98";
+ return "5f3205f0189d9dde54665f970838f614";
#if BUILDFLAG(IS_APPLE)
return "3c3209357e0c057a0620afa7d83eb784";
#else
@@ -1432,7 +1432,7 @@ TEST_F(FPDFFormFillEmbedderTest, Bug1302455RenderOnly) {
TEST_F(FPDFFormFillEmbedderTest, Bug1302455EditFirstForm) {
const char* checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "29a06da3e47f67535e266b090a5ac82d";
+ return "143c2bb79fcaecf24f5aa104dce27beb";
#if BUILDFLAG(IS_APPLE)
return "bf5423874f188427d2500a2bc4abebbe";
#else
@@ -1465,7 +1465,7 @@ TEST_F(FPDFFormFillEmbedderTest, Bug1302455EditFirstForm) {
TEST_F(FPDFFormFillEmbedderTest, Bug1302455EditSecondForm) {
const char* checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "19f8574d6378ee36e349376d88b7a2c4";
+ return "e36726414acb616dc203e8851b510e2c";
#if BUILDFLAG(IS_APPLE)
return "8a0fd8772dba6e1e952e49d159cc64b5";
#else
@@ -1498,7 +1498,7 @@ TEST_F(FPDFFormFillEmbedderTest, Bug1302455EditSecondForm) {
TEST_F(FPDFFormFillEmbedderTest, Bug1302455EditBothForms) {
const char* checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "edbc9b0e190118a9039fffc11e494081";
+ return "f82a807c056e22aa55d3d7228eedfe6f";
#if BUILDFLAG(IS_APPLE)
return "1f422ee1c520ad74b1a993b64bd4dc4a";
#else
@@ -1537,11 +1537,14 @@ TEST_F(FPDFFormFillEmbedderTest, Bug1302455EditBothForms) {
TEST_F(FPDFFormFillEmbedderTest, RemoveFormFieldHighlight) {
const char* no_highlight_checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "3bfddb2529085021ad283b7e65f71525";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "5c82aa43e3b478aa1e4c94bb9ef1f11f";
-#endif
+ return "5c82aa43e3b478aa1e4c94bb9ef1f11f";
+#else
return "a6268304f7eedfa9ee98fac3caaf2efb";
+#endif
}();
ASSERT_TRUE(OpenDocument("text_form.pdf"));
@@ -3365,7 +3368,7 @@ class FPDFFormFillActionUriTest : public EmbedderTest {
}
void SetFocusOnNthAnnot(size_t n) {
- DCHECK_NE(n, 0);
+ DCHECK_NE(n, 0u);
// Setting focus on first annot.
FORM_OnMouseMove(form_handle(), page(), /*modifier=*/0, 100, 680);
FORM_OnLButtonDown(form_handle(), page(), /*modifier=*/0, 100, 680);
diff --git a/fpdfsdk/fpdf_ppo.cpp b/fpdfsdk/fpdf_ppo.cpp
index f1fde2290..9efb52324 100644
--- a/fpdfsdk/fpdf_ppo.cpp
+++ b/fpdfsdk/fpdf_ppo.cpp
@@ -38,7 +38,7 @@
#include "fpdfsdk/cpdfsdk_helpers.h"
#include "public/cpp/fpdf_scopers.h"
#include "third_party/base/check.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
struct XObjectContext {
UnownedPtr<CPDF_Document> dest_doc;
diff --git a/fpdfsdk/fpdf_progressive.cpp b/fpdfsdk/fpdf_progressive.cpp
index af2cc4747..83b579724 100644
--- a/fpdfsdk/fpdf_progressive.cpp
+++ b/fpdfsdk/fpdf_progressive.cpp
@@ -13,6 +13,7 @@
#include "core/fpdfapi/render/cpdf_pagerendercontext.h"
#include "core/fpdfapi/render/cpdf_progressiverenderer.h"
#include "core/fxge/cfx_defaultrenderdevice.h"
+#include "core/fxge/dib/cfx_dibitmap.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
#include "fpdfsdk/cpdfsdk_pauseadapter.h"
#include "fpdfsdk/cpdfsdk_renderpage.h"
@@ -55,18 +56,17 @@ FPDF_RenderPageBitmapWithColorScheme_Start(FPDF_BITMAP bitmap,
if (!pPage)
return FPDF_RENDER_FAILED;
- auto pOwnedContext = std::make_unique<CPDF_PageRenderContext>();
- CPDF_PageRenderContext* pContext = pOwnedContext.get();
- pPage->SetRenderContext(std::move(pOwnedContext));
+ auto owned_context = std::make_unique<CPDF_PageRenderContext>();
+ CPDF_PageRenderContext* context = owned_context.get();
+ pPage->SetRenderContext(std::move(owned_context));
RetainPtr<CFX_DIBitmap> pBitmap(CFXDIBitmapFromFPDFBitmap(bitmap));
- auto pOwnedDevice = std::make_unique<CFX_DefaultRenderDevice>();
- CFX_DefaultRenderDevice* pDevice = pOwnedDevice.get();
- pContext->m_pDevice = std::move(pOwnedDevice);
- pDevice->AttachWithRgbByteOrder(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER));
+ auto device = std::make_unique<CFX_DefaultRenderDevice>();
+ device->AttachWithRgbByteOrder(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER));
+ context->m_pDevice = std::move(device);
CPDFSDK_PauseAdapter pause_adapter(pause);
- CPDFSDK_RenderPageWithContext(pContext, pPage, start_x, start_y, size_x,
+ CPDFSDK_RenderPageWithContext(context, pPage, start_x, start_y, size_x,
size_y, rotate, flags, color_scheme,
/*need_to_restore=*/false, &pause_adapter);
@@ -76,10 +76,11 @@ FPDF_RenderPageBitmapWithColorScheme_Start(FPDF_BITMAP bitmap,
}
#endif // defined(_SKIA_SUPPORT_)
- if (!pContext->m_pRenderer)
+ if (!context->m_pRenderer) {
return FPDF_RENDER_FAILED;
+ }
- return ToFPDFStatus(pContext->m_pRenderer->GetStatus());
+ return ToFPDFStatus(context->m_pRenderer->GetStatus());
}
FPDF_EXPORT int FPDF_CALLCONV FPDF_RenderPageBitmap_Start(FPDF_BITMAP bitmap,
diff --git a/fpdfsdk/fpdf_structtree.cpp b/fpdfsdk/fpdf_structtree.cpp
index 76a30beda..4817f4797 100644
--- a/fpdfsdk/fpdf_structtree.cpp
+++ b/fpdfsdk/fpdf_structtree.cpp
@@ -135,6 +135,10 @@ FPDF_StructElement_GetAttributeCount(FPDF_STRUCTELEMENT struct_element) {
if (!elem)
return -1;
RetainPtr<const CPDF_Object> attr_obj = elem->GetA();
+ if (!attr_obj) {
+ return -1;
+ }
+ attr_obj = attr_obj->GetDirect();
if (!attr_obj)
return -1;
if (attr_obj->IsArray())
@@ -154,6 +158,10 @@ FPDF_StructElement_GetAttributeAtIndex(FPDF_STRUCTELEMENT struct_element,
if (!attr_obj)
return nullptr;
+ attr_obj = attr_obj->GetDirect();
+ if (!attr_obj) {
+ return nullptr;
+ }
if (attr_obj->IsDictionary()) {
return index == 0 ? FPDFStructElementAttrFromCPDFDictionary(
attr_obj->AsDictionary())
@@ -288,8 +296,9 @@ FPDF_StructElement_Attr_GetName(FPDF_STRUCTELEMENT_ATTR struct_attribute,
void* buffer,
unsigned long buflen,
unsigned long* out_buflen) {
- if (!out_buflen || !buffer)
+ if (!out_buflen) {
return false;
+ }
const CPDF_Dictionary* dict =
CPDFDictionaryFromFPDFStructElementAttr(struct_attribute);
@@ -352,7 +361,7 @@ FPDF_StructElement_Attr_GetNumberValue(FPDF_STRUCTELEMENT_ATTR struct_attribute,
if (!dict)
return false;
- RetainPtr<const CPDF_Object> obj = dict->GetObjectFor(name);
+ RetainPtr<const CPDF_Object> obj = dict->GetDirectObjectFor(name);
if (!obj || !obj->IsNumber())
return false;
diff --git a/fpdfsdk/fpdf_structtree_embeddertest.cpp b/fpdfsdk/fpdf_structtree_embeddertest.cpp
index 472a3a986..2704887ef 100644
--- a/fpdfsdk/fpdf_structtree_embeddertest.cpp
+++ b/fpdfsdk/fpdf_structtree_embeddertest.cpp
@@ -595,6 +595,11 @@ TEST_F(FPDFStructTreeEmbedderTest, GetAttributes) {
ASSERT_EQ(2, FPDF_StructElement_Attr_GetCount(attr));
ASSERT_FALSE(
FPDF_StructElement_Attr_GetName(attr, 1, nullptr, 0U, nullptr));
+ unsigned long buffer_len_needed = ULONG_MAX;
+ // Pass buffer = nullptr to obtain the size of the buffer needed,
+ ASSERT_TRUE(FPDF_StructElement_Attr_GetName(attr, 1, nullptr, 0,
+ &buffer_len_needed));
+ EXPECT_EQ(2U, buffer_len_needed);
char buffer[8] = {};
unsigned long out_len = ULONG_MAX;
// Deliberately pass in a small buffer size to make sure `buffer` remains
@@ -643,11 +648,12 @@ TEST_F(FPDFStructTreeEmbedderTest, GetAttributes) {
FPDF_STRUCTELEMENT td = FPDF_StructElement_GetChildAtIndex(tr, 1);
ASSERT_TRUE(td);
{
+ // Test counting and obtaining attributes via reference
ASSERT_EQ(1, FPDF_StructElement_GetAttributeCount(td));
FPDF_STRUCTELEMENT_ATTR attr =
FPDF_StructElement_GetAttributeAtIndex(td, 0);
ASSERT_TRUE(attr);
- ASSERT_EQ(3, FPDF_StructElement_Attr_GetCount(attr));
+ ASSERT_EQ(4, FPDF_StructElement_Attr_GetCount(attr));
// Test string and blob type
{
char buffer[16] = {};
@@ -691,6 +697,23 @@ TEST_F(FPDFStructTreeEmbedderTest, GetAttributes) {
FPDF_StructElement_Attr_GetBooleanValue(attr, buffer, &val));
EXPECT_TRUE(val);
}
+
+ // Test reference to number
+ {
+ char buffer[16] = {};
+ unsigned long out_len = ULONG_MAX;
+ ASSERT_TRUE(FPDF_StructElement_Attr_GetName(
+ attr, 3, buffer, sizeof(buffer), &out_len));
+ EXPECT_EQ(8U, out_len);
+ EXPECT_STREQ("RowSpan", buffer);
+
+ EXPECT_EQ(FPDF_OBJECT_REFERENCE,
+ FPDF_StructElement_Attr_GetType(attr, buffer));
+ float val;
+ ASSERT_TRUE(
+ FPDF_StructElement_Attr_GetNumberValue(attr, buffer, &val));
+ EXPECT_FLOAT_EQ(3, val);
+ }
}
}
}
@@ -831,3 +854,18 @@ TEST_F(FPDFStructTreeEmbedderTest, Bug1296920) {
UnloadPage(page);
}
+
+TEST_F(FPDFStructTreeEmbedderTest, Bug1443100) {
+ ASSERT_TRUE(OpenDocument("tagged_table_bad_parent.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+
+ {
+ // Calling these APIs should not trigger a dangling pointer.
+ ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page));
+ ASSERT_TRUE(struct_tree);
+ ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree.get()));
+ }
+
+ UnloadPage(page);
+}
diff --git a/fpdfsdk/fpdf_transformpage.cpp b/fpdfsdk/fpdf_transformpage.cpp
index 9814da663..c9ea3334d 100644
--- a/fpdfsdk/fpdf_transformpage.cpp
+++ b/fpdfsdk/fpdf_transformpage.cpp
@@ -26,8 +26,8 @@
#include "core/fxge/cfx_fillrenderoptions.h"
#include "core/fxge/cfx_path.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
+#include "third_party/base/containers/span.h"
#include "third_party/base/numerics/safe_conversions.h"
-#include "third_party/base/span.h"
namespace {
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp
index d65579d32..f93561cee 100644
--- a/fpdfsdk/fpdf_view.cpp
+++ b/fpdfsdk/fpdf_view.cpp
@@ -40,6 +40,7 @@
#include "core/fxge/cfx_defaultrenderdevice.h"
#include "core/fxge/cfx_gemodule.h"
#include "core/fxge/cfx_renderdevice.h"
+#include "core/fxge/dib/cfx_dibitmap.h"
#include "fpdfsdk/cpdfsdk_customaccess.h"
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
@@ -48,14 +49,9 @@
#include "fxjs/ijs_runtime.h"
#include "public/fpdf_formfill.h"
#include "third_party/base/check_op.h"
+#include "third_party/base/containers/span.h"
+#include "third_party/base/memory/ptr_util.h"
#include "third_party/base/numerics/safe_conversions.h"
-#include "third_party/base/ptr_util.h"
-#include "third_party/base/span.h"
-
-#if defined(_SKIA_SUPPORT_)
-#include "third_party/skia/include/core/SkPictureRecorder.h" // nogncheck
-#include "third_party/skia/include/core/SkRect.h" // nogncheck
-#endif // defined(_SKIA_SUPPORT_)
#ifdef PDF_ENABLE_V8
#include "fxjs/cfx_v8_array_buffer_allocator.h"
@@ -72,6 +68,10 @@
#include "core/fpdfapi/render/cpdf_windowsrenderdevice.h"
#include "public/fpdf_edit.h"
+#if defined(_SKIA_SUPPORT_)
+class SkCanvas;
+#endif // defined(_SKIA_SUPPORT_)
+
// These checks are here because core/ and public/ cannot depend on each other.
static_assert(static_cast<int>(WindowsPrintMode::kEmf) == FPDF_PRINTMODE_EMF,
"WindowsPrintMode::kEmf value mismatch");
@@ -546,10 +546,10 @@ FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPage(HDC dc,
if (!pPage)
return;
- auto pOwnedContext = std::make_unique<CPDF_PageRenderContext>();
- CPDF_PageRenderContext* pContext = pOwnedContext.get();
+ auto owned_context = std::make_unique<CPDF_PageRenderContext>();
+ CPDF_PageRenderContext* context = owned_context.get();
CPDF_Page::RenderContextClearer clearer(pPage);
- pPage->SetRenderContext(std::move(pOwnedContext));
+ pPage->SetRenderContext(std::move(owned_context));
// 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
@@ -564,9 +564,9 @@ FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPage(HDC dc,
const bool bHasMask = pPage->HasImageMask() && !bNewBitmap;
auto* render_data = CPDF_DocRenderData::FromDocument(pPage->GetDocument());
if (!bNewBitmap && !bHasMask) {
- pContext->m_pDevice = std::make_unique<CPDF_WindowsRenderDevice>(
+ context->m_pDevice = std::make_unique<CPDF_WindowsRenderDevice>(
dc, render_data->GetPSFontTracker());
- CPDFSDK_RenderPageWithContext(pContext, pPage, start_x, start_y, size_x,
+ CPDFSDK_RenderPageWithContext(context, pPage, start_x, start_y, size_x,
size_y, rotate, flags,
/*color_scheme=*/nullptr,
/*need_to_restore=*/true, /*pause=*/nullptr);
@@ -575,18 +575,18 @@ FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPage(HDC dc,
RetainPtr<CFX_DIBitmap> pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
// Create will probably work fine even if it fails here: we will just attach
- // a zero-sized bitmap to |pDevice|.
+ // a zero-sized bitmap to `device`.
pBitmap->Create(size_x, size_y, FXDIB_Format::kArgb);
pBitmap->Clear(0x00ffffff);
- CFX_DefaultRenderDevice* pDevice = new CFX_DefaultRenderDevice;
- pContext->m_pDevice = pdfium::WrapUnique(pDevice);
- pDevice->Attach(pBitmap);
+ auto device = std::make_unique<CFX_DefaultRenderDevice>();
+ device->Attach(pBitmap);
+ context->m_pDevice = std::move(device);
if (bHasMask) {
- pContext->m_pOptions = std::make_unique<CPDF_RenderOptions>();
- pContext->m_pOptions->GetOptions().bBreakForMasks = true;
+ context->m_pOptions = std::make_unique<CPDF_RenderOptions>();
+ context->m_pOptions->GetOptions().bBreakForMasks = true;
}
- CPDFSDK_RenderPageWithContext(pContext, pPage, start_x, start_y, size_x,
+ CPDFSDK_RenderPageWithContext(context, pPage, start_x, start_y, size_x,
size_y, rotate, flags, /*color_scheme=*/nullptr,
/*need_to_restore=*/true,
/*pause=*/nullptr);
@@ -597,8 +597,8 @@ FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPage(HDC dc,
if (win_dc.GetDeviceType() == DeviceType::kPrinter) {
auto pDst = pdfium::MakeRetain<CFX_DIBitmap>();
if (pDst->Create(size_x, size_y, FXDIB_Format::kRgb32)) {
- fxcrt::spanset(pDst->GetBuffer().first(pBitmap->GetPitch() * size_y),
- -1);
+ fxcrt::spanset(
+ pDst->GetWritableBuffer().first(pBitmap->GetPitch() * size_y), -1);
pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0,
BlendMode::kNormal, nullptr, false);
win_dc.StretchDIBits(pDst, 0, 0, size_x, size_y);
@@ -618,21 +618,21 @@ FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPage(HDC dc,
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);
+ context->m_pRenderer->Continue(nullptr);
}
// Begin rendering to the printer. Add flag to indicate the renderer should
// pause after each image mask.
pPage->ClearRenderContext();
- pOwnedContext = std::make_unique<CPDF_PageRenderContext>();
- pContext = pOwnedContext.get();
- pPage->SetRenderContext(std::move(pOwnedContext));
- pContext->m_pDevice = std::make_unique<CPDF_WindowsRenderDevice>(
+ owned_context = std::make_unique<CPDF_PageRenderContext>();
+ context = owned_context.get();
+ pPage->SetRenderContext(std::move(owned_context));
+ context->m_pDevice = std::make_unique<CPDF_WindowsRenderDevice>(
dc, render_data->GetPSFontTracker());
- pContext->m_pOptions = std::make_unique<CPDF_RenderOptions>();
- pContext->m_pOptions->GetOptions().bBreakForMasks = true;
+ context->m_pOptions = std::make_unique<CPDF_RenderOptions>();
+ context->m_pOptions->GetOptions().bBreakForMasks = true;
- CPDFSDK_RenderPageWithContext(pContext, pPage, start_x, start_y, size_x,
+ CPDFSDK_RenderPageWithContext(context, pPage, start_x, start_y, size_x,
size_y, rotate, flags, /*color_scheme=*/nullptr,
/*need_to_restore=*/true,
/*pause=*/nullptr);
@@ -641,10 +641,10 @@ FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPage(HDC dc,
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]);
+ RenderBitmap(context->m_pDevice.get(), bitmaps[i], bitmap_areas[i]);
}
// Render the next portion of page.
- pContext->m_pRenderer->Continue(nullptr);
+ context->m_pRenderer->Continue(nullptr);
}
}
#endif // BUILDFLAG(IS_WIN)
@@ -664,18 +664,17 @@ FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
if (!pPage)
return;
- auto pOwnedContext = std::make_unique<CPDF_PageRenderContext>();
- CPDF_PageRenderContext* pContext = pOwnedContext.get();
+ auto owned_context = std::make_unique<CPDF_PageRenderContext>();
+ CPDF_PageRenderContext* context = owned_context.get();
CPDF_Page::RenderContextClearer clearer(pPage);
- pPage->SetRenderContext(std::move(pOwnedContext));
-
- auto pOwnedDevice = std::make_unique<CFX_DefaultRenderDevice>();
- CFX_DefaultRenderDevice* pDevice = pOwnedDevice.get();
- pContext->m_pDevice = std::move(pOwnedDevice);
+ pPage->SetRenderContext(std::move(owned_context));
RetainPtr<CFX_DIBitmap> pBitmap(CFXDIBitmapFromFPDFBitmap(bitmap));
- pDevice->AttachWithRgbByteOrder(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER));
- CPDFSDK_RenderPageWithContext(pContext, pPage, start_x, start_y, size_x,
+ auto device = std::make_unique<CFX_DefaultRenderDevice>();
+ device->AttachWithRgbByteOrder(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER));
+ context->m_pDevice = std::move(device);
+
+ CPDFSDK_RenderPageWithContext(context, pPage, start_x, start_y, size_x,
size_y, rotate, flags, /*color_scheme=*/nullptr,
/*need_to_restore=*/true,
/*pause=*/nullptr);
@@ -700,18 +699,16 @@ FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap,
if (!pPage)
return;
- auto pOwnedContext = std::make_unique<CPDF_PageRenderContext>();
- CPDF_PageRenderContext* pContext = pOwnedContext.get();
+ auto owned_context = std::make_unique<CPDF_PageRenderContext>();
+ CPDF_PageRenderContext* context = owned_context.get();
CPDF_Page::RenderContextClearer clearer(pPage);
- pPage->SetRenderContext(std::move(pOwnedContext));
-
- auto pOwnedDevice = std::make_unique<CFX_DefaultRenderDevice>();
- CFX_DefaultRenderDevice* pDevice = pOwnedDevice.get();
- pContext->m_pDevice = std::move(pOwnedDevice);
+ pPage->SetRenderContext(std::move(owned_context));
RetainPtr<CFX_DIBitmap> pBitmap(CFXDIBitmapFromFPDFBitmap(bitmap));
- pDevice->AttachWithRgbByteOrder(std::move(pBitmap),
- !!(flags & FPDF_REVERSE_BYTE_ORDER));
+ auto device = std::make_unique<CFX_DefaultRenderDevice>();
+ device->AttachWithRgbByteOrder(std::move(pBitmap),
+ !!(flags & FPDF_REVERSE_BYTE_ORDER));
+ context->m_pDevice = std::move(device);
CFX_FloatRect clipping_rect;
if (clipping)
@@ -722,41 +719,36 @@ FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap,
CFX_Matrix transform_matrix = pPage->GetDisplayMatrix(rect, 0);
if (matrix)
transform_matrix *= CFXMatrixFromFSMatrix(*matrix);
- CPDFSDK_RenderPage(pContext, pPage, transform_matrix, clip_rect, flags,
+ CPDFSDK_RenderPage(context, pPage, transform_matrix, clip_rect, flags,
/*color_scheme=*/nullptr);
}
#if defined(_SKIA_SUPPORT_)
-FPDF_EXPORT FPDF_RECORDER FPDF_CALLCONV FPDF_RenderPageSkp(FPDF_PAGE page,
- int size_x,
- int size_y) {
- auto skDevice = std::make_unique<CFX_DefaultRenderDevice>();
- std::unique_ptr<SkPictureRecorder> recorder =
- skDevice->CreateRecorder(SkRect::MakeWH(size_x, size_y));
+FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPageSkia(FPDF_SKIA_CANVAS canvas,
+ FPDF_PAGE page,
+ int size_x,
+ int size_y) {
+ if (!canvas) {
+ return;
+ }
- CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
- if (!pPage) {
- // The equivalent bitmap APIs don't signal failure in this case, but defer
- // the real work to a later call to `FPDF_FFLDraw()`. This is the case for
- // XFA pages, for example.
- //
- // The caller still needs the `SkPictureRecorder` in order to call
- // `FPDF_FFLRecord()` later.
- return recorder.release();
+ CPDF_Page* cpdf_page = CPDFPageFromFPDFPage(page);
+ if (!cpdf_page) {
+ return;
}
- auto pOwnedContext = std::make_unique<CPDF_PageRenderContext>();
- pOwnedContext->m_pDevice = std::move(skDevice);
+ auto owned_context = std::make_unique<CPDF_PageRenderContext>();
+ CPDF_PageRenderContext* context = owned_context.get();
+ CPDF_Page::RenderContextClearer clearer(cpdf_page);
+ cpdf_page->SetRenderContext(std::move(owned_context));
- CPDF_Page::RenderContextClearer clearer(pPage);
- CPDF_PageRenderContext* pContext = pOwnedContext.get();
- pPage->SetRenderContext(std::move(pOwnedContext));
+ auto device = std::make_unique<CFX_DefaultRenderDevice>();
+ device->AttachCanvas(reinterpret_cast<SkCanvas*>(canvas));
+ context->m_pDevice = std::move(device);
- CPDFSDK_RenderPageWithContext(pContext, pPage, 0, 0, size_x, size_y, 0, 0,
+ CPDFSDK_RenderPageWithContext(context, cpdf_page, 0, 0, size_x, size_y, 0, 0,
/*color_scheme=*/nullptr,
/*need_to_restore=*/true, /*pause=*/nullptr);
-
- return recorder.release();
}
#endif // defined(_SKIA_SUPPORT_)
@@ -919,7 +911,7 @@ FPDF_EXPORT void FPDF_CALLCONV FPDFBitmap_FillRect(FPDF_BITMAP bitmap,
}
FPDF_EXPORT void* FPDF_CALLCONV FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) {
- return bitmap ? CFXDIBitmapFromFPDFBitmap(bitmap)->GetBuffer().data()
+ return bitmap ? CFXDIBitmapFromFPDFBitmap(bitmap)->GetWritableBuffer().data()
: nullptr;
}
diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c
index b66fe6221..5907a4e3d 100644
--- a/fpdfsdk/fpdf_view_c_api_test.c
+++ b/fpdfsdk/fpdf_view_c_api_test.c
@@ -312,7 +312,7 @@ int CheckPDFiumCApi() {
CHK(FPDFPage_HasFormFieldAtPoint);
CHK(FPDF_FFLDraw);
#if defined(_SKIA_SUPPORT_)
- CHK(FPDF_FFLRecord);
+ CHK(FPDF_FFLDrawSkia);
#endif
CHK(FPDF_GetFormType);
CHK(FPDF_LoadXFA);
@@ -518,7 +518,7 @@ int CheckPDFiumCApi() {
CHK(FPDF_RenderPageBitmap);
CHK(FPDF_RenderPageBitmapWithMatrix);
#if defined(_SKIA_SUPPORT_)
- CHK(FPDF_RenderPageSkp);
+ CHK(FPDF_RenderPageSkia);
#endif
#if defined(_WIN32)
CHK(FPDF_SetPrintMode);
diff --git a/fpdfsdk/fpdf_view_embeddertest.cpp b/fpdfsdk/fpdf_view_embeddertest.cpp
index 469e9bdc7..06b337e1a 100644
--- a/fpdfsdk/fpdf_view_embeddertest.cpp
+++ b/fpdfsdk/fpdf_view_embeddertest.cpp
@@ -133,7 +133,7 @@ ScopedFPDFBitmap SkImageToPdfiumBitmap(const SkImage& image) {
ScopedFPDFBitmap SkPictureToPdfiumBitmap(sk_sp<SkPicture> picture,
const SkISize& size) {
sk_sp<SkSurface> surface =
- SkSurface::MakeRasterN32Premul(size.width(), size.height());
+ SkSurfaces::Raster(SkImageInfo::MakeN32Premul(size));
if (!surface) {
ADD_FAILURE() << "Could not create SkSurface";
return nullptr;
@@ -232,14 +232,17 @@ class FPDFViewEmbedderTest : public EmbedderTest {
int width = static_cast<int>(FPDF_GetPageWidth(page));
int height = static_cast<int>(FPDF_GetPageHeight(page));
- FPDF_RECORDER opaque_recorder = FPDF_RenderPageSkp(page, width, height);
- ASSERT_TRUE(opaque_recorder);
+ sk_sp<SkPicture> picture;
+ {
+ auto recorder = std::make_unique<SkPictureRecorder>();
+ recorder->beginRecording(width, height);
- SkPictureRecorder* recorder =
- reinterpret_cast<SkPictureRecorder*>(opaque_recorder);
- sk_sp<SkPicture> picture = recorder->finishRecordingAsPicture();
- delete recorder;
- ASSERT_TRUE(picture);
+ FPDF_RenderPageSkia(
+ reinterpret_cast<FPDF_SKIA_CANVAS>(recorder->getRecordingCanvas()),
+ page, width, height);
+ picture = recorder->finishRecordingAsPicture();
+ ASSERT_TRUE(picture);
+ }
ScopedFPDFBitmap bitmap = SkPictureToPdfiumBitmap(
std::move(picture), SkISize::Make(width, height));
@@ -1454,11 +1457,14 @@ TEST_F(FPDFViewEmbedderTest, RenderBug664284WithNoNativeText) {
// macOS rendering result doesn't.
const char* original_checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "29cb8045c21cfa2c920fdf43de70efd8";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "0e339d606aafb63077f49e238dc27cb0";
-#endif
+ return "0e339d606aafb63077f49e238dc27cb0";
+#else
return "288502887ffc63291f35a0573b944375";
+#endif
}();
static const char kNoNativeTextChecksum[] =
"288502887ffc63291f35a0573b944375";
@@ -1473,6 +1479,27 @@ TEST_F(FPDFViewEmbedderTest, RenderBug664284WithNoNativeText) {
UnloadPage(page);
}
+TEST_F(FPDFViewEmbedderTest, RenderAnnotationWithPrintingFlag) {
+ const char* annotation_checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "eaece6b8041c0cb9b33398e5b6d5ddda";
+ }
+ return "c108ba6e0a9743652f12e4bc223f9b32";
+ }();
+ static const char kPrintingChecksum[] = "3e235b9f88f652f2b97b1fc393924849";
+ ASSERT_TRUE(OpenDocument("bug_1658.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+
+ // A yellow highlight is rendered with `FPDF_ANNOT` flag.
+ TestRenderPageBitmapWithFlags(page, FPDF_ANNOT, annotation_checksum);
+
+ // After adding `FPDF_PRINTING` flag, the yellow highlight is not rendered.
+ TestRenderPageBitmapWithFlags(page, FPDF_PRINTING | FPDF_ANNOT,
+ kPrintingChecksum);
+ UnloadPage(page);
+}
+
// TODO(crbug.com/pdfium/1955): Remove this test once pixel tests can pass with
// `reverse-byte-order` option.
TEST_F(FPDFViewEmbedderTest, RenderBlueAndRedImagesWithReverByteOrderFlag) {
@@ -1628,7 +1655,7 @@ TEST_F(FPDFViewEmbedderTest, RenderHelloWorldWithFlags) {
const char* lcd_text_checksum = []() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "c1c548442e0e0f949c5550d89bf8ae3b";
+ return "d1decde2de1c07b5274cc8cb44f92427";
#if BUILDFLAG(IS_APPLE)
return "6eef7237f7591f07616e238422086737";
#else
@@ -1636,11 +1663,14 @@ TEST_F(FPDFViewEmbedderTest, RenderHelloWorldWithFlags) {
#endif // BUILDFLAG(IS_APPLE)
}();
const char* no_smoothtext_checksum = []() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "cd5bbe9407c3fcc85d365172a9a55abd";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "6eef7237f7591f07616e238422086737";
-#endif
+ return "6eef7237f7591f07616e238422086737";
+#else
return "37d0b34e1762fdda4c05ce7ea357b828";
+#endif
}();
TestRenderPageBitmapWithFlags(page, FPDF_LCD_TEXT, lcd_text_checksum);
@@ -2038,7 +2068,15 @@ TEST_F(FPDFViewEmbedderTest, NoSmoothTextItalicOverlappingGlyphs) {
FPDF_PAGE page = LoadPage(0);
ASSERT_TRUE(page);
- TestRenderPageBitmapWithFlags(page, FPDF_RENDER_NO_SMOOTHTEXT,
- "4ef1f65ab1ac76acb97a3540dcb10b4e");
+ const char* checksum = []() {
+#if !BUILDFLAG(IS_APPLE)
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "ceeb93d2bcdb586d62c95b33cadcd873";
+ }
+#endif
+ return "4ef1f65ab1ac76acb97a3540dcb10b4e";
+ }();
+
+ TestRenderPageBitmapWithFlags(page, FPDF_RENDER_NO_SMOOTHTEXT, checksum);
UnloadPage(page);
}
diff --git a/fpdfsdk/pwl/cpwl_caret.cpp b/fpdfsdk/pwl/cpwl_caret.cpp
index fe293886c..47f786484 100644
--- a/fpdfsdk/pwl/cpwl_caret.cpp
+++ b/fpdfsdk/pwl/cpwl_caret.cpp
@@ -76,7 +76,7 @@ void CPWL_Caret::SetCaret(bool bVisible,
return;
m_pTimer.reset();
- CPWL_Wnd::SetVisible(false);
+ (void)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;
diff --git a/fpdfsdk/pwl/cpwl_cblistbox.cpp b/fpdfsdk/pwl/cpwl_cblistbox.cpp
index 492b6ae47..0771b2647 100644
--- a/fpdfsdk/pwl/cpwl_cblistbox.cpp
+++ b/fpdfsdk/pwl/cpwl_cblistbox.cpp
@@ -75,7 +75,6 @@ bool CPWL_CBListBox::OnMovementKeyDown(FWL_VKEYCODE nKeyCode,
break;
default:
NOTREACHED_NORETURN();
- break;
}
return OnNotifySelectionChanged(true, nFlag);
}
diff --git a/fpdfsdk/pwl/cpwl_combo_box.cpp b/fpdfsdk/pwl/cpwl_combo_box.cpp
index c84b7c071..7c122d753 100644
--- a/fpdfsdk/pwl/cpwl_combo_box.cpp
+++ b/fpdfsdk/pwl/cpwl_combo_box.cpp
@@ -202,8 +202,8 @@ void CPWL_ComboBox::CreateListBox(const CreateParams& cp) {
m_pList->Realize();
}
-bool CPWL_ComboBox::RePosChildWnd() {
- ObservedPtr<CPWL_ComboBox> thisObserved(this);
+bool CPWL_ComboBox::RepositionChildWnd() {
+ ObservedPtr<CPWL_ComboBox> this_observed(this);
const CFX_FloatRect rcClient = GetClientRect();
if (m_bPopup) {
const float fOldWindowHeight = m_rcOldWindow.Height();
@@ -227,26 +227,31 @@ bool CPWL_ComboBox::RePosChildWnd() {
if (m_pButton) {
m_pButton->Move(rcButton, true, false);
- if (!thisObserved)
+ if (!this_observed) {
return false;
+ }
}
if (m_pEdit) {
m_pEdit->Move(rcEdit, true, false);
- if (!thisObserved)
+ if (!this_observed) {
return false;
+ }
}
if (m_pList) {
- if (!m_pList->SetVisible(true) || !thisObserved)
+ if (!m_pList->SetVisible(true) || !this_observed) {
return false;
+ }
- if (!m_pList->Move(rcList, true, false) || !thisObserved)
+ if (!m_pList->Move(rcList, true, false) || !this_observed) {
return false;
+ }
m_pList->ScrollToListItem(m_nSelectItem);
- if (!thisObserved)
+ if (!this_observed) {
return false;
+ }
}
return true;
}
@@ -256,8 +261,9 @@ bool CPWL_ComboBox::RePosChildWnd() {
if (m_pButton) {
m_pButton->Move(rcButton, true, false);
- if (!thisObserved)
+ if (!this_observed) {
return false;
+ }
}
CFX_FloatRect rcEdit = rcClient;
@@ -265,14 +271,19 @@ bool CPWL_ComboBox::RePosChildWnd() {
if (m_pEdit) {
m_pEdit->Move(rcEdit, true, false);
- if (!thisObserved)
+ if (!this_observed) {
return false;
+ }
}
if (m_pList) {
- m_pList->SetVisible(false);
- if (!thisObserved)
+ if (!m_pList->SetVisible(false)) {
+ m_pList = nullptr; // Gone, dangling even.
+ return false;
+ }
+ if (!this_observed) {
return false;
+ }
}
return true;
@@ -301,11 +312,12 @@ bool CPWL_ComboBox::SetPopup(bool bPopup) {
return Move(m_rcOldWindow, true, true);
}
- ObservedPtr<CPWL_ComboBox> thisObserved(this);
+ ObservedPtr<CPWL_ComboBox> this_observed(this);
if (GetFillerNotify()->OnPopupPreOpen(GetAttachedData(), {}))
- return !!thisObserved;
- if (!thisObserved)
+ return !!this_observed;
+ if (!this_observed) {
return false;
+ }
float fBorderWidth = m_pList->GetBorderWidth() * 2;
float fPopupMin = 0.0f;
@@ -334,7 +346,7 @@ bool CPWL_ComboBox::SetPopup(bool bPopup) {
return false;
GetFillerNotify()->OnPopupPostOpen(GetAttachedData(), {});
- return !!thisObserved;
+ return !!this_observed;
}
bool CPWL_ComboBox::OnKeyDown(FWL_VKEYCODE nKeyCode,
@@ -344,22 +356,22 @@ bool CPWL_ComboBox::OnKeyDown(FWL_VKEYCODE nKeyCode,
if (!m_pEdit)
return false;
- ObservedPtr<CPWL_Wnd> thisObserved(this);
+ ObservedPtr<CPWL_Wnd> this_observed(this);
m_nSelectItem = -1;
switch (nKeyCode) {
case FWL_VKEY_Up:
if (m_pList->GetCurSel() > 0) {
if (GetFillerNotify()->OnPopupPreOpen(GetAttachedData(), nFlag) ||
- !thisObserved) {
+ !this_observed) {
return false;
}
if (GetFillerNotify()->OnPopupPostOpen(GetAttachedData(), nFlag) ||
- !thisObserved) {
+ !this_observed) {
return false;
}
if (m_pList->IsMovementKey(nKeyCode)) {
- if (m_pList->OnMovementKeyDown(nKeyCode, nFlag) || !thisObserved) {
+ if (m_pList->OnMovementKeyDown(nKeyCode, nFlag) || !this_observed) {
return false;
}
SetSelectText();
@@ -369,15 +381,15 @@ bool CPWL_ComboBox::OnKeyDown(FWL_VKEYCODE nKeyCode,
case FWL_VKEY_Down:
if (m_pList->GetCurSel() < m_pList->GetCount() - 1) {
if (GetFillerNotify()->OnPopupPreOpen(GetAttachedData(), nFlag) ||
- !thisObserved) {
+ !this_observed) {
return false;
}
if (GetFillerNotify()->OnPopupPostOpen(GetAttachedData(), nFlag) ||
- !thisObserved) {
+ !this_observed) {
return false;
}
if (m_pList->IsMovementKey(nKeyCode)) {
- if (m_pList->OnMovementKeyDown(nKeyCode, nFlag) || !thisObserved) {
+ if (m_pList->OnMovementKeyDown(nKeyCode, nFlag) || !this_observed) {
return false;
}
SetSelectText();
@@ -431,13 +443,13 @@ bool CPWL_ComboBox::OnChar(uint16_t nChar, Mask<FWL_EVENTFLAG> nFlag) {
if (HasFlag(PCBS_ALLOWCUSTOMTEXT))
return m_pEdit->OnChar(nChar, nFlag);
- ObservedPtr<CPWL_Wnd> thisObserved(this);
+ ObservedPtr<CPWL_Wnd> this_observed(this);
if (GetFillerNotify()->OnPopupPreOpen(GetAttachedData(), nFlag) ||
- !thisObserved) {
+ !this_observed) {
return false;
}
if (GetFillerNotify()->OnPopupPostOpen(GetAttachedData(), nFlag) ||
- !thisObserved) {
+ !this_observed) {
return false;
}
if (!m_pList->IsChar(nChar, nFlag))
diff --git a/fpdfsdk/pwl/cpwl_combo_box.h b/fpdfsdk/pwl/cpwl_combo_box.h
index 87749fa78..45729aeef 100644
--- a/fpdfsdk/pwl/cpwl_combo_box.h
+++ b/fpdfsdk/pwl/cpwl_combo_box.h
@@ -34,7 +34,7 @@ class CPWL_ComboBox final : public CPWL_Wnd {
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;
+ bool RepositionChildWnd() override;
CFX_FloatRect GetFocusRect() const override;
void SetFocus() override;
void KillFocus() override;
diff --git a/fpdfsdk/pwl/cpwl_edit.cpp b/fpdfsdk/pwl/cpwl_edit.cpp
index e41b339c4..3657b8811 100644
--- a/fpdfsdk/pwl/cpwl_edit.cpp
+++ b/fpdfsdk/pwl/cpwl_edit.cpp
@@ -46,17 +46,18 @@ void CPWL_Edit::SetText(const WideString& csText) {
m_pEditImpl->Paint();
}
-bool CPWL_Edit::RePosChildWnd() {
+bool CPWL_Edit::RepositionChildWnd() {
if (CPWL_ScrollBar* pVSB = GetVScrollBar()) {
CFX_FloatRect rcWindow = m_rcOldWindow;
CFX_FloatRect rcVScroll =
CFX_FloatRect(rcWindow.right, rcWindow.bottom,
rcWindow.right + CPWL_ScrollBar::kWidth, rcWindow.top);
- ObservedPtr<CPWL_Edit> thisObserved(this);
+ ObservedPtr<CPWL_Edit> this_observed(this);
pVSB->Move(rcVScroll, true, false);
- if (!thisObserved)
+ if (!this_observed) {
return false;
+ }
}
if (m_pCaret && !HasFlag(PES_TEXTOVERFLOW)) {
@@ -237,12 +238,15 @@ void CPWL_Edit::OnKillFocus() {
ObservedPtr<CPWL_Edit> observed_ptr(this);
CPWL_ScrollBar* pScroll = GetVScrollBar();
if (pScroll && pScroll->IsVisible()) {
- pScroll->SetVisible(false);
- if (!observed_ptr)
+ if (!pScroll->SetVisible(false)) {
return;
-
- if (!Move(m_rcOldWindow, true, true))
+ }
+ if (!observed_ptr) {
+ return;
+ }
+ if (!Move(m_rcOldWindow, true, true)) {
return;
+ }
}
m_pEditImpl->SelectNone();
@@ -342,7 +346,7 @@ bool CPWL_Edit::OnKeyDown(FWL_VKEYCODE nKeyCode, Mask<FWL_EVENTFLAG> nFlag) {
if (nSelStart == nSelEnd)
nSelEnd = nSelStart + 1;
- ObservedPtr<CPWL_Wnd> thisObserved(this);
+ ObservedPtr<CPWL_Wnd> this_observed(this);
bool bRC;
bool bExit;
@@ -350,8 +354,9 @@ bool CPWL_Edit::OnKeyDown(FWL_VKEYCODE nKeyCode, Mask<FWL_EVENTFLAG> nFlag) {
GetAttachedData(), strChange, strChangeEx, nSelStart, nSelEnd, true,
nFlag);
- if (!thisObserved)
+ if (!this_observed) {
return false;
+ }
if (!bRC)
return false;
@@ -423,15 +428,16 @@ bool CPWL_Edit::OnChar(uint16_t nChar, Mask<FWL_EVENTFLAG> nFlag) {
break;
}
- ObservedPtr<CPWL_Wnd> thisObserved(this);
+ ObservedPtr<CPWL_Wnd> this_observed(this);
WideString strChangeEx;
std::tie(bRC, bExit) = GetFillerNotify()->OnBeforeKeyStroke(
GetAttachedData(), swChange, strChangeEx, nSelStart, nSelEnd, true,
nFlag);
- if (!thisObserved)
+ if (!this_observed) {
return false;
+ }
}
if (!bRC)
@@ -785,10 +791,11 @@ bool CPWL_Edit::SetCaret(bool bVisible,
if (!IsFocused() || m_pEditImpl->IsSelected())
bVisible = false;
- ObservedPtr<CPWL_Edit> thisObserved(this);
+ ObservedPtr<CPWL_Edit> this_observed(this);
m_pCaret->SetCaret(bVisible, ptHead, ptFoot);
- if (!thisObserved)
+ if (!this_observed) {
return false;
+ }
return true;
}
diff --git a/fpdfsdk/pwl/cpwl_edit.h b/fpdfsdk/pwl/cpwl_edit.h
index 696e32ca2..5e2e5fc02 100644
--- a/fpdfsdk/pwl/cpwl_edit.h
+++ b/fpdfsdk/pwl/cpwl_edit.h
@@ -33,7 +33,7 @@ class CPWL_Edit final : public CPWL_Wnd {
~CPWL_Edit() override;
// CPWL_Wnd:
- bool RePosChildWnd() override;
+ bool RepositionChildWnd() override;
CFX_FloatRect GetClientRect() const override;
void DrawThisAppearance(CFX_RenderDevice* pDevice,
const CFX_Matrix& mtUser2Device) override;
diff --git a/fpdfsdk/pwl/cpwl_edit_impl.cpp b/fpdfsdk/pwl/cpwl_edit_impl.cpp
index 50e2c42ea..37ec30607 100644
--- a/fpdfsdk/pwl/cpwl_edit_impl.cpp
+++ b/fpdfsdk/pwl/cpwl_edit_impl.cpp
@@ -1232,9 +1232,12 @@ void CPWL_EditImpl::Refresh() {
if (!m_bNotifyFlag) {
AutoRestorer<bool> restorer(&m_bNotifyFlag);
m_bNotifyFlag = true;
- if (std::vector<CFX_FloatRect>* pRects = m_Refresh.GetRefreshRects()) {
- for (auto& rect : *pRects)
- m_pNotify->InvalidateRect(&rect);
+ std::vector<CFX_FloatRect>* pRects = m_Refresh.GetRefreshRects();
+ for (auto& rect : *pRects) {
+ if (!m_pNotify->InvalidateRect(&rect)) {
+ m_pNotify = nullptr; // Gone, dangling even.
+ break;
+ }
}
}
}
@@ -1302,7 +1305,9 @@ void CPWL_EditImpl::RefreshWordRange(const CPVT_WordRange& wr) {
AutoRestorer<bool> restorer(&m_bNotifyFlag);
m_bNotifyFlag = true;
CFX_FloatRect rcRefresh = VTToEdit(rcWord);
- m_pNotify->InvalidateRect(&rcRefresh);
+ if (!m_pNotify->InvalidateRect(&rcRefresh)) {
+ m_pNotify = nullptr; // Gone, dangling even.
+ }
}
}
} else {
@@ -1316,7 +1321,9 @@ void CPWL_EditImpl::RefreshWordRange(const CPVT_WordRange& wr) {
AutoRestorer<bool> restorer(&m_bNotifyFlag);
m_bNotifyFlag = true;
CFX_FloatRect rcRefresh = VTToEdit(rcLine);
- m_pNotify->InvalidateRect(&rcRefresh);
+ if (!m_pNotify->InvalidateRect(&rcRefresh)) {
+ m_pNotify = nullptr; // Gone, dangling even.
+ }
}
}
diff --git a/fpdfsdk/pwl/cpwl_list_box.cpp b/fpdfsdk/pwl/cpwl_list_box.cpp
index 083e24074..2203ca9d7 100644
--- a/fpdfsdk/pwl/cpwl_list_box.cpp
+++ b/fpdfsdk/pwl/cpwl_list_box.cpp
@@ -194,9 +194,10 @@ void CPWL_ListBox::ScrollWindowVertically(float pos) {
m_pListCtrl->SetScrollPos(CFX_PointF(0, pos));
}
-bool CPWL_ListBox::RePosChildWnd() {
- if (!CPWL_Wnd::RePosChildWnd())
+bool CPWL_ListBox::RepositionChildWnd() {
+ if (!CPWL_Wnd::RepositionChildWnd()) {
return false;
+ }
m_pListCtrl->SetPlateRect(GetListRect());
return true;
@@ -204,7 +205,7 @@ bool CPWL_ListBox::RePosChildWnd() {
bool CPWL_ListBox::OnNotifySelectionChanged(bool bKeyDown,
Mask<FWL_EVENTFLAG> nFlag) {
- ObservedPtr<CPWL_Wnd> thisObserved(this);
+ ObservedPtr<CPWL_Wnd> this_observed(this);
WideString swChange = GetText();
WideString strChangeEx;
@@ -216,8 +217,9 @@ bool CPWL_ListBox::OnNotifySelectionChanged(bool bKeyDown,
GetAttachedData(), swChange, strChangeEx, nSelStart, nSelEnd, bKeyDown,
nFlag);
- if (!thisObserved)
+ if (!this_observed) {
return false;
+ }
return bExit;
}
@@ -270,15 +272,13 @@ void CPWL_ListBox::OnSetScrollInfoY(float fPlateMin,
Info.fContentMax - Info.fContentMin) ||
FXSYS_IsFloatEqual(Info.fPlateWidth,
Info.fContentMax - Info.fContentMin)) {
- if (pScroll->IsVisible()) {
- pScroll->SetVisible(false);
- RePosChildWnd();
- }
- } else {
- if (!pScroll->IsVisible()) {
- pScroll->SetVisible(true);
- RePosChildWnd();
+ if (pScroll->IsVisible() && pScroll->SetVisible(false)) {
+ RepositionChildWnd();
}
+ return;
+ }
+ if (!pScroll->IsVisible() && pScroll->SetVisible(true)) {
+ RepositionChildWnd();
}
}
@@ -286,8 +286,8 @@ void CPWL_ListBox::OnSetScrollPosY(float fy) {
SetScrollPosition(fy);
}
-void CPWL_ListBox::OnInvalidateRect(const CFX_FloatRect& rect) {
- InvalidateRect(&rect);
+bool CPWL_ListBox::OnInvalidateRect(const CFX_FloatRect& rect) {
+ return InvalidateRect(&rect);
}
void CPWL_ListBox::Select(int32_t nItemIndex) {
diff --git a/fpdfsdk/pwl/cpwl_list_box.h b/fpdfsdk/pwl/cpwl_list_box.h
index 49d93637f..85b00771e 100644
--- a/fpdfsdk/pwl/cpwl_list_box.h
+++ b/fpdfsdk/pwl/cpwl_list_box.h
@@ -39,7 +39,7 @@ class CPWL_ListBox : public CPWL_Wnd, public CPWL_ListCtrl::NotifyIface {
void SetScrollInfo(const PWL_SCROLL_INFO& info) override;
void SetScrollPosition(float pos) override;
void ScrollWindowVertically(float pos) override;
- bool RePosChildWnd() override;
+ bool RepositionChildWnd() override;
CFX_FloatRect GetFocusRect() const override;
void SetFontSize(float fFontSize) override;
float GetFontSize() const override;
@@ -52,7 +52,7 @@ class CPWL_ListBox : public CPWL_Wnd, public CPWL_ListCtrl::NotifyIface {
float fSmallStep,
float fBigStep) override;
void OnSetScrollPosY(float fy) override;
- void OnInvalidateRect(const CFX_FloatRect& pRect) override;
+ [[nodiscard]] bool OnInvalidateRect(const CFX_FloatRect& pRect) override;
bool OnNotifySelectionChanged(bool bKeyDown, Mask<FWL_EVENTFLAG> nFlag);
diff --git a/fpdfsdk/pwl/cpwl_list_ctrl.cpp b/fpdfsdk/pwl/cpwl_list_ctrl.cpp
index 046e772ed..d7e3b15e1 100644
--- a/fpdfsdk/pwl/cpwl_list_ctrl.cpp
+++ b/fpdfsdk/pwl/cpwl_list_ctrl.cpp
@@ -356,26 +356,30 @@ void CPWL_ListCtrl::SetCaret(int32_t 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->OnInvalidateRect(rcRefresh);
- m_bNotifyFlag = false;
+ if (!m_pNotify) {
+ return;
+ }
+ if (nItemIndex == -1) {
+ if (!m_bNotifyFlag) {
+ m_bNotifyFlag = true;
+ CFX_FloatRect rcRefresh = m_rcPlate;
+ if (!m_pNotify->OnInvalidateRect(rcRefresh)) {
+ m_pNotify = nullptr; // Gone, dangling even.
}
- } 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->OnInvalidateRect(rcRefresh);
- m_bNotifyFlag = false;
+ 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;
+ if (!m_pNotify->OnInvalidateRect(rcRefresh)) {
+ m_pNotify = nullptr; // Gone, dangling even.
}
+ m_bNotifyFlag = false;
}
}
}
diff --git a/fpdfsdk/pwl/cpwl_list_ctrl.h b/fpdfsdk/pwl/cpwl_list_ctrl.h
index 3f36354ab..c278b81d3 100644
--- a/fpdfsdk/pwl/cpwl_list_ctrl.h
+++ b/fpdfsdk/pwl/cpwl_list_ctrl.h
@@ -31,7 +31,9 @@ class CPWL_ListCtrl {
float fSmallStep,
float fBigStep) = 0;
virtual void OnSetScrollPosY(float fy) = 0;
- virtual void OnInvalidateRect(const CFX_FloatRect& rect) = 0;
+
+ // Returns true if `this` is still allocated.
+ [[nodiscard]] virtual bool OnInvalidateRect(const CFX_FloatRect& rect) = 0;
};
CPWL_ListCtrl();
diff --git a/fpdfsdk/pwl/cpwl_sbbutton.cpp b/fpdfsdk/pwl/cpwl_sbbutton.cpp
index 889ce5e76..28f037ab8 100644
--- a/fpdfsdk/pwl/cpwl_sbbutton.cpp
+++ b/fpdfsdk/pwl/cpwl_sbbutton.cpp
@@ -45,23 +45,23 @@ void CPWL_SBButton::DrawThisAppearance(CFX_RenderDevice* pDevice,
nTransparency, 80, 220);
// draw arrow
if (rectWnd.top - rectWnd.bottom > 6.0f) {
- float fX = rectWnd.left + 1.5f;
- float fY = rectWnd.bottom;
std::vector<CFX_PointF> pts;
- static constexpr float kOffsetsX[] = {2.5f, 2.5f, 4.5f, 6.5f,
- 6.5f, 4.5f, 2.5f};
- static constexpr float kOffsetsY[] = {5.0f, 6.0f, 4.0f, 6.0f,
- 5.0f, 3.0f, 5.0f};
- static constexpr float kOffsetsMinY[] = {4.0f, 3.0f, 5.0f, 3.0f,
- 4.0f, 6.0f, 4.0f};
- static_assert(std::size(kOffsetsX) == std::size(kOffsetsY),
- "Wrong offset count");
- static_assert(std::size(kOffsetsX) == std::size(kOffsetsMinY),
- "Wrong offset count");
- const float* pOffsetsY =
- m_eSBButtonType == Type::kMinButton ? kOffsetsMinY : kOffsetsY;
- for (size_t i = 0; i < std::size(kOffsetsX); ++i)
- pts.push_back(CFX_PointF(fX + kOffsetsX[i], fY + pOffsetsY[i]));
+ CFX_PointF origin(rectWnd.left + 1.5f, rectWnd.bottom);
+ if (m_eSBButtonType == Type::kMinButton) {
+ static constexpr CFX_PointF kOffsetsMin[] = {
+ {2.5f, 4.0f}, {2.5f, 3.0f}, {4.5f, 5.0f}, {6.5f, 3.0f},
+ {6.5f, 4.0f}, {4.5f, 6.0f}, {2.5f, 4.0f}};
+ for (const auto& offset : kOffsetsMin) {
+ pts.push_back(origin + offset);
+ }
+ } else {
+ static constexpr CFX_PointF kOffsets[] = {
+ {2.5f, 5.0f}, {2.5f, 6.0f}, {4.5f, 4.0f}, {6.5f, 6.0f},
+ {6.5f, 5.0f}, {4.5f, 3.0f}, {2.5f, 5.0f}};
+ for (const auto& offset : kOffsets) {
+ pts.push_back(origin + offset);
+ }
+ }
pDevice->DrawFillArea(mtUser2Device, pts,
ArgbEncode(nTransparency, 255, 255, 255));
}
diff --git a/fpdfsdk/pwl/cpwl_scroll_bar.cpp b/fpdfsdk/pwl/cpwl_scroll_bar.cpp
index 00a94189d..67c503c51 100644
--- a/fpdfsdk/pwl/cpwl_scroll_bar.cpp
+++ b/fpdfsdk/pwl/cpwl_scroll_bar.cpp
@@ -125,7 +125,7 @@ void CPWL_ScrollBar::OnDestroy() {
CPWL_Wnd::OnDestroy();
}
-bool CPWL_ScrollBar::RePosChildWnd() {
+bool CPWL_ScrollBar::RepositionChildWnd() {
CFX_FloatRect rcClient = GetClientRect();
CFX_FloatRect rcMinButton;
CFX_FloatRect rcMaxButton;
@@ -149,16 +149,18 @@ bool CPWL_ScrollBar::RePosChildWnd() {
}
}
- ObservedPtr<CPWL_ScrollBar> thisObserved(this);
+ ObservedPtr<CPWL_ScrollBar> this_observed(this);
if (m_pMinButton) {
m_pMinButton->Move(rcMinButton, true, false);
- if (!thisObserved)
+ if (!this_observed) {
return false;
+ }
}
if (m_pMaxButton) {
m_pMaxButton->Move(rcMaxButton, true, false);
- if (!thisObserved)
+ if (!this_observed) {
return false;
+ }
}
return MovePosButton(false);
@@ -313,8 +315,8 @@ void CPWL_ScrollBar::CreateButtons(const CreateParams& cp) {
auto pButton = std::make_unique<CPWL_SBButton>(
scp, CloneAttachedData(), CPWL_SBButton::Type::kPosButton);
m_pPosButton = pButton.get();
- ObservedPtr<CPWL_ScrollBar> thisObserved(this);
- if (m_pPosButton->SetVisible(false) && thisObserved) {
+ ObservedPtr<CPWL_ScrollBar> this_observed(this);
+ if (m_pPosButton->SetVisible(false) && this_observed) {
AddChild(std::move(pButton));
m_pPosButton->Realize();
}
@@ -331,21 +333,22 @@ void CPWL_ScrollBar::SetScrollRange(float fMin,
if (!m_pPosButton)
return;
- ObservedPtr<CPWL_ScrollBar> thisObserved(this);
+ ObservedPtr<CPWL_ScrollBar> this_observed(this);
m_sData.SetScrollRange(fMin, fMax);
m_sData.SetClientWidth(fClientWidth);
if (FXSYS_IsFloatSmaller(m_sData.ScrollRange.GetWidth(), 0.0f)) {
- m_pPosButton->SetVisible(false);
+ (void)m_pPosButton->SetVisible(false);
// Note, |this| may no longer be viable at this point. If more work needs
- // to be done, check thisObserved.
+ // to be done, check this_observed.
return;
}
- if (!m_pPosButton->SetVisible(true) || !thisObserved)
+ if (!m_pPosButton->SetVisible(true) || !this_observed) {
return;
+ }
- MovePosButton(true);
+ (void)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().
}
@@ -354,7 +357,7 @@ void CPWL_ScrollBar::SetScrollPos(float fPos) {
float fOldPos = m_sData.fScrollPos;
m_sData.SetPos(fPos);
if (!FXSYS_IsFloatEqual(m_sData.fScrollPos, fOldPos)) {
- MovePosButton(true);
+ (void)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().
}
@@ -385,10 +388,11 @@ bool CPWL_ScrollBar::MovePosButton(bool bRefresh) {
CFX_FloatRect rcPosButton =
CFX_FloatRect(rcPosArea.left, fBottom, rcPosArea.right, fTop);
- ObservedPtr<CPWL_ScrollBar> thisObserved(this);
+ ObservedPtr<CPWL_ScrollBar> this_observed(this);
m_pPosButton->Move(rcPosButton, true, bRefresh);
- if (!thisObserved)
+ if (!this_observed) {
return false;
+ }
}
return true;
diff --git a/fpdfsdk/pwl/cpwl_scroll_bar.h b/fpdfsdk/pwl/cpwl_scroll_bar.h
index 6cca8fba5..91a7516b9 100644
--- a/fpdfsdk/pwl/cpwl_scroll_bar.h
+++ b/fpdfsdk/pwl/cpwl_scroll_bar.h
@@ -101,7 +101,7 @@ class CPWL_ScrollBar final : public CPWL_Wnd, public CFX_Timer::CallbackIface {
// CPWL_Wnd:
void OnDestroy() override;
- bool RePosChildWnd() override;
+ bool RepositionChildWnd() override;
void DrawThisAppearance(CFX_RenderDevice* pDevice,
const CFX_Matrix& mtUser2Device) override;
bool OnLButtonDown(Mask<FWL_EVENTFLAG> nFlag,
@@ -124,7 +124,7 @@ class CPWL_ScrollBar final : public CPWL_Wnd, public CFX_Timer::CallbackIface {
void SetScrollPos(float fPos);
// Returns |true| iff this instance is still allocated.
- bool MovePosButton(bool bRefresh);
+ [[nodiscard]] bool MovePosButton(bool bRefresh);
void SetScrollStep(float fBigStep, float fSmallStep);
void NotifyScrollWindow();
CFX_FloatRect GetScrollArea() const;
diff --git a/fpdfsdk/pwl/cpwl_wnd.cpp b/fpdfsdk/pwl/cpwl_wnd.cpp
index 755fcbb65..a2dafdb71 100644
--- a/fpdfsdk/pwl/cpwl_wnd.cpp
+++ b/fpdfsdk/pwl/cpwl_wnd.cpp
@@ -46,14 +46,16 @@ CPWL_Wnd::CreateParams::CreateParams(const CreateParams& other) = default;
CPWL_Wnd::CreateParams::~CreateParams() = default;
-class CPWL_MsgControl final : public Observable {
+// For a compound window (a window containing a child window as occurs in a
+// list box, combo box, or even a scroll bar), this class contains information
+// shared amongst the parent and children.
+class CPWL_Wnd::SharedCaptureFocusState final : public Observable {
public:
- explicit CPWL_MsgControl(const CPWL_Wnd* pWnd) : m_pCreatedWnd(pWnd) {}
- ~CPWL_MsgControl() = default;
+ explicit SharedCaptureFocusState(const CPWL_Wnd* pOwnerWnd)
+ : m_pOwnerWnd(pOwnerWnd) {}
+ ~SharedCaptureFocusState() = default;
- bool IsWndCreated(const CPWL_Wnd* pWnd) const {
- return m_pCreatedWnd == pWnd;
- }
+ bool IsOwnedByWnd(const CPWL_Wnd* pWnd) const { return m_pOwnerWnd == pWnd; }
bool IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
return pWnd && pdfium::Contains(m_MousePaths, pWnd);
@@ -67,6 +69,9 @@ class CPWL_MsgControl final : public Observable {
return pWnd && pdfium::Contains(m_KeyboardPaths, pWnd);
}
+ void SetCapture(CPWL_Wnd* pWnd) { m_MousePaths = pWnd->GetAncestors(); }
+ void ReleaseCapture() { m_MousePaths.clear(); }
+
void SetFocus(CPWL_Wnd* pWnd) {
m_KeyboardPaths = pWnd->GetAncestors();
m_pMainKeyboardWnd = pWnd;
@@ -75,8 +80,8 @@ class CPWL_MsgControl final : public Observable {
pWnd->OnSetFocus();
}
- void KillFocus() {
- ObservedPtr<CPWL_MsgControl> observed_ptr(this);
+ void ReleaseFocus() {
+ ObservedPtr<SharedCaptureFocusState> observed_ptr(this);
if (!m_KeyboardPaths.empty()) {
CPWL_Wnd* pWnd = m_KeyboardPaths.front();
if (pWnd)
@@ -89,15 +94,29 @@ class CPWL_MsgControl final : public Observable {
m_KeyboardPaths.clear();
}
- void SetCapture(CPWL_Wnd* pWnd) { m_MousePaths = pWnd->GetAncestors(); }
-
- void ReleaseCapture() { m_MousePaths.clear(); }
+ void RemoveWnd(CPWL_Wnd* pWnd) {
+ if (pWnd == m_pOwnerWnd) {
+ m_pOwnerWnd = nullptr;
+ }
+ if (pWnd == m_pMainKeyboardWnd) {
+ m_pMainKeyboardWnd = nullptr;
+ }
+ auto mouse_it = std::find(m_MousePaths.begin(), m_MousePaths.end(), pWnd);
+ if (mouse_it != m_MousePaths.end()) {
+ m_MousePaths.erase(mouse_it);
+ }
+ auto keyboard_it =
+ std::find(m_KeyboardPaths.begin(), m_KeyboardPaths.end(), pWnd);
+ if (keyboard_it != m_KeyboardPaths.end()) {
+ m_KeyboardPaths.erase(keyboard_it);
+ }
+ }
private:
+ UnownedPtr<const CPWL_Wnd> m_pOwnerWnd;
+ UnownedPtr<const CPWL_Wnd> m_pMainKeyboardWnd;
std::vector<UnownedPtr<CPWL_Wnd>> m_MousePaths;
std::vector<UnownedPtr<CPWL_Wnd>> m_KeyboardPaths;
- UnownedPtr<const CPWL_Wnd> m_pCreatedWnd;
- UnownedPtr<const CPWL_Wnd> m_pMainKeyboardWnd;
};
// static
@@ -148,16 +167,17 @@ void CPWL_Wnd::Realize() {
m_rcClip.Inflate(1.0f, 1.0f);
m_rcClip.Normalize();
}
- CreateMsgControl();
+ CreateSharedCaptureFocusState();
CreateParams ccp = m_CreationParams;
ccp.dwFlags &= 0xFFFF0000L; // remove sub styles
- CreateScrollBar(ccp);
+ CreateVScrollBar(ccp);
CreateChildWnd(ccp);
m_bVisible = HasFlag(PWS_VISIBLE);
OnCreated();
- if (!RePosChildWnd())
+ if (!RepositionChildWnd()) {
return;
+ }
m_bCreated = true;
}
@@ -185,7 +205,7 @@ void CPWL_Wnd::Destroy() {
m_pParent->RemoveChild(this);
m_bCreated = false;
}
- DestroyMsgControl();
+ DestroySharedCaptureFocusState();
}
bool CPWL_Wnd::Move(const CFX_FloatRect& rcNew, bool bReset, bool bRefresh) {
@@ -199,8 +219,9 @@ bool CPWL_Wnd::Move(const CFX_FloatRect& rcNew, bool bReset, bool bRefresh) {
if (bReset) {
if (rcOld.left != rcNew.left || rcOld.right != rcNew.right ||
rcOld.top != rcNew.top || rcOld.bottom != rcNew.bottom) {
- if (!RePosChildWnd())
+ if (!RepositionChildWnd()) {
return false;
+ }
}
}
if (bRefresh && !InvalidateRectMove(rcOld, rcNew))
@@ -258,7 +279,7 @@ bool CPWL_Wnd::InvalidateRect(const CFX_FloatRect* pRect) {
if (!IsValid())
return true;
- ObservedPtr<CPWL_Wnd> thisObserved(this);
+ ObservedPtr<CPWL_Wnd> this_observed(this);
CFX_FloatRect rcRefresh = pRect ? *pRect : GetWindowRect();
if (!HasFlag(PWS_NOREFRESHCLIP)) {
CFX_FloatRect rcClip = GetClipRect();
@@ -270,7 +291,7 @@ bool CPWL_Wnd::InvalidateRect(const CFX_FloatRect* pRect) {
rcWin.Inflate(1, 1);
rcWin.Normalize();
GetFillerNotify()->InvalidateRect(m_pAttachedData.get(), rcWin);
- return !!thisObserved;
+ return !!this_observed;
}
bool CPWL_Wnd::OnKeyDown(FWL_VKEYCODE nKeyCode, Mask<FWL_EVENTFLAG> nFlag) {
@@ -478,10 +499,6 @@ CPWL_ScrollBar* CPWL_Wnd::GetVScrollBar() const {
return HasFlag(PWS_VSCROLL) ? m_pVScrollBar : nullptr;
}
-void CPWL_Wnd::CreateScrollBar(const CreateParams& cp) {
- CreateVScrollBar(cp);
-}
-
void CPWL_Wnd::CreateVScrollBar(const CreateParams& cp) {
if (m_pVScrollBar || !HasFlag(PWS_VSCROLL))
return;
@@ -499,30 +516,34 @@ void CPWL_Wnd::CreateVScrollBar(const CreateParams& cp) {
}
void CPWL_Wnd::SetCapture() {
- if (CPWL_MsgControl* pMsgCtrl = GetMsgControl())
- pMsgCtrl->SetCapture(this);
+ if (SharedCaptureFocusState* pSharedState = GetSharedCaptureFocusState()) {
+ pSharedState->SetCapture(this);
+ }
}
void CPWL_Wnd::ReleaseCapture() {
for (const auto& pChild : m_Children)
pChild->ReleaseCapture();
- if (CPWL_MsgControl* pMsgCtrl = GetMsgControl())
- pMsgCtrl->ReleaseCapture();
+ if (SharedCaptureFocusState* pSharedState = GetSharedCaptureFocusState()) {
+ pSharedState->ReleaseCapture();
+ }
}
void CPWL_Wnd::SetFocus() {
- if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
- if (!pMsgCtrl->IsMainCaptureKeyboard(this))
- pMsgCtrl->KillFocus();
- pMsgCtrl->SetFocus(this);
+ if (SharedCaptureFocusState* pSharedState = GetSharedCaptureFocusState()) {
+ if (!pSharedState->IsMainCaptureKeyboard(this)) {
+ pSharedState->ReleaseFocus();
+ }
+ pSharedState->SetFocus(this);
}
}
void CPWL_Wnd::KillFocus() {
- if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
- if (pMsgCtrl->IsWndCaptureKeyboard(this))
- pMsgCtrl->KillFocus();
+ if (SharedCaptureFocusState* pSharedState = GetSharedCaptureFocusState()) {
+ if (pSharedState->IsWndCaptureKeyboard(this)) {
+ pSharedState->ReleaseFocus();
+ }
}
}
@@ -555,17 +576,21 @@ bool CPWL_Wnd::SetVisible(bool bVisible) {
if (!IsValid())
return true;
- ObservedPtr<CPWL_Wnd> thisObserved(this);
+ ObservedPtr<CPWL_Wnd> this_observed(this);
for (const auto& pChild : m_Children) {
- pChild->SetVisible(bVisible);
- if (!thisObserved)
+ if (!pChild->SetVisible(bVisible)) {
+ return false;
+ }
+ if (!this_observed) {
return false;
+ }
}
if (bVisible != m_bVisible) {
m_bVisible = bVisible;
- if (!RePosChildWnd())
+ if (!RepositionChildWnd()) {
return false;
+ }
if (!InvalidateRect(nullptr))
return false;
@@ -586,7 +611,7 @@ bool CPWL_Wnd::IsReadOnly() const {
return HasFlag(PWS_READONLY);
}
-bool CPWL_Wnd::RePosChildWnd() {
+bool CPWL_Wnd::RepositionChildWnd() {
CPWL_ScrollBar* pVSB = GetVScrollBar();
if (!pVSB)
return true;
@@ -601,10 +626,11 @@ bool CPWL_Wnd::RePosChildWnd() {
CFX_FloatRect(rcContent.right - CPWL_ScrollBar::kWidth, rcContent.bottom,
rcContent.right - 1.0f, rcContent.top);
- ObservedPtr<CPWL_Wnd> thisObserved(this);
+ ObservedPtr<CPWL_Wnd> this_observed(this);
pVSB->Move(rcVScroll, true, false);
- if (!thisObserved)
+ if (!this_observed) {
return false;
+ }
return true;
}
@@ -616,19 +642,29 @@ void CPWL_Wnd::SetCursor() {
GetFillerNotify()->SetCursor(GetCreationParams()->eCursorType);
}
-void CPWL_Wnd::CreateMsgControl() {
- if (!m_CreationParams.pMsgControl)
- m_CreationParams.pMsgControl = new CPWL_MsgControl(this);
+void CPWL_Wnd::CreateSharedCaptureFocusState() {
+ if (!m_CreationParams.pSharedCaptureFocusState) {
+ m_CreationParams.pSharedCaptureFocusState =
+ new SharedCaptureFocusState(this);
+ }
}
-void CPWL_Wnd::DestroyMsgControl() {
- CPWL_MsgControl* pMsgControl = GetMsgControl();
- if (pMsgControl && pMsgControl->IsWndCreated(this))
- delete pMsgControl;
+void CPWL_Wnd::DestroySharedCaptureFocusState() {
+ SharedCaptureFocusState* pSharedCaptureFocusState =
+ GetSharedCaptureFocusState();
+ if (!pSharedCaptureFocusState) {
+ return;
+ }
+ const bool owned = pSharedCaptureFocusState->IsOwnedByWnd(this);
+ pSharedCaptureFocusState->RemoveWnd(this);
+ if (owned) {
+ delete pSharedCaptureFocusState;
+ }
}
-CPWL_MsgControl* CPWL_Wnd::GetMsgControl() const {
- return m_CreationParams.pMsgControl;
+CPWL_Wnd::SharedCaptureFocusState* CPWL_Wnd::GetSharedCaptureFocusState()
+ const {
+ return m_CreationParams.pSharedCaptureFocusState;
}
bool CPWL_Wnd::IsCaptureMouse() const {
@@ -636,17 +672,17 @@ bool CPWL_Wnd::IsCaptureMouse() const {
}
bool CPWL_Wnd::IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
- CPWL_MsgControl* pCtrl = GetMsgControl();
+ SharedCaptureFocusState* pCtrl = GetSharedCaptureFocusState();
return pCtrl && pCtrl->IsWndCaptureMouse(pWnd);
}
bool CPWL_Wnd::IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const {
- CPWL_MsgControl* pCtrl = GetMsgControl();
+ SharedCaptureFocusState* pCtrl = GetSharedCaptureFocusState();
return pCtrl && pCtrl->IsWndCaptureKeyboard(pWnd);
}
bool CPWL_Wnd::IsFocused() const {
- CPWL_MsgControl* pCtrl = GetMsgControl();
+ SharedCaptureFocusState* pCtrl = GetSharedCaptureFocusState();
return pCtrl && pCtrl->IsMainCaptureKeyboard(this);
}
diff --git a/fpdfsdk/pwl/cpwl_wnd.h b/fpdfsdk/pwl/cpwl_wnd.h
index b10b59a5e..f7aea8d71 100644
--- a/fpdfsdk/pwl/cpwl_wnd.h
+++ b/fpdfsdk/pwl/cpwl_wnd.h
@@ -14,6 +14,7 @@
#include "core/fxcrt/mask.h"
#include "core/fxcrt/observed_ptr.h"
#include "core/fxcrt/unowned_ptr.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
#include "core/fxcrt/widestring.h"
#include "core/fxge/cfx_color.h"
#include "core/fxge/cfx_renderdevice.h"
@@ -21,7 +22,6 @@
#include "public/fpdf_fwlevent.h"
class CPWL_Edit;
-class CPWL_MsgControl;
class CPWL_ScrollBar;
class IPVT_FontMap;
struct PWL_SCROLL_INFO;
@@ -79,6 +79,8 @@ class CPWL_Wnd : public Observable {
static const CFX_Color kDefaultBlackColor;
static const CFX_Color kDefaultWhiteColor;
+ class SharedCaptureFocusState;
+
class ProviderIface : public Observable {
public:
virtual ~ProviderIface() = default;
@@ -118,7 +120,9 @@ class CPWL_Wnd : public Observable {
CPWL_Dash sDash;
// Ignore, used internally only:
- CPWL_MsgControl* pMsgControl = nullptr;
+ // TODO(tsepez): fix murky ownership, bare delete.
+ UNOWNED_PTR_EXCLUSION SharedCaptureFocusState* pSharedCaptureFocusState =
+ nullptr;
IPWL_FillerNotify::CursorStyle eCursorType =
IPWL_FillerNotify::CursorStyle::kArrow;
};
@@ -136,7 +140,7 @@ class CPWL_Wnd : public Observable {
virtual ~CPWL_Wnd();
// Returns |true| iff this instance is still allocated.
- virtual bool InvalidateRect(const CFX_FloatRect* pRect);
+ [[nodiscard]] virtual bool InvalidateRect(const CFX_FloatRect* pRect);
virtual bool OnKeyDown(FWL_VKEYCODE nKeyCode, Mask<FWL_EVENTFLAG> nFlag);
virtual bool OnChar(uint16_t nChar, Mask<FWL_EVENTFLAG> nFlag);
@@ -163,7 +167,7 @@ class CPWL_Wnd : public Observable {
virtual void SetCursor();
// Returns |true| iff this instance is still allocated.
- virtual bool SetVisible(bool bVisible);
+ [[nodiscard]] virtual bool SetVisible(bool bVisible);
virtual void SetFontSize(float fFontSize);
virtual float GetFontSize() const;
@@ -222,7 +226,7 @@ class CPWL_Wnd : public Observable {
virtual void CreateChildWnd(const CreateParams& cp);
// Returns |true| iff this instance is still allocated.
- virtual bool RePosChildWnd();
+ [[nodiscard]] virtual bool RepositionChildWnd();
virtual void DrawThisAppearance(CFX_RenderDevice* pDevice,
const CFX_Matrix& mtUser2Device);
@@ -246,8 +250,8 @@ class CPWL_Wnd : public Observable {
CPWL_ScrollBar* GetVScrollBar() const;
// Returns |true| iff this instance is still allocated.
- bool InvalidateRectMove(const CFX_FloatRect& rcOld,
- const CFX_FloatRect& rcNew);
+ [[nodiscard]] bool InvalidateRectMove(const CFX_FloatRect& rcOld,
+ const CFX_FloatRect& rcNew);
void SetCapture();
void ReleaseCapture();
@@ -275,13 +279,12 @@ class CPWL_Wnd : public Observable {
CFX_FloatRect PWLtoWnd(const CFX_FloatRect& rect) const;
- void CreateScrollBar(const CreateParams& cp);
void CreateVScrollBar(const CreateParams& cp);
void AdjustStyle();
- void CreateMsgControl();
- void DestroyMsgControl();
- CPWL_MsgControl* GetMsgControl() const;
+ void CreateSharedCaptureFocusState();
+ void DestroySharedCaptureFocusState();
+ SharedCaptureFocusState* GetSharedCaptureFocusState() const;
CreateParams m_CreationParams;
std::unique_ptr<IPWL_FillerNotify::PerWindowData> m_pAttachedData;
diff --git a/fxbarcode/BC_TwoDimWriter.h b/fxbarcode/BC_TwoDimWriter.h
index 3f9e4a7db..cab1f45cb 100644
--- a/fxbarcode/BC_TwoDimWriter.h
+++ b/fxbarcode/BC_TwoDimWriter.h
@@ -11,7 +11,7 @@
#include "core/fxcrt/fx_coordinates.h"
#include "fxbarcode/BC_Writer.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CBC_CommonBitMatrix;
class CFX_RenderDevice;
diff --git a/fxbarcode/cfx_barcode.cpp b/fxbarcode/cfx_barcode.cpp
index f7cd5f60d..5b2c1346c 100644
--- a/fxbarcode/cfx_barcode.cpp
+++ b/fxbarcode/cfx_barcode.cpp
@@ -18,8 +18,8 @@
#include "fxbarcode/cbc_pdf417i.h"
#include "fxbarcode/cbc_qrcode.h"
#include "fxbarcode/cbc_upca.h"
+#include "third_party/base/memory/ptr_util.h"
#include "third_party/base/notreached.h"
-#include "third_party/base/ptr_util.h"
namespace {
@@ -50,8 +50,7 @@ std::unique_ptr<CBC_CodeBase> CreateBarCodeEngineObject(BC_TYPE type) {
case BC_TYPE::kUnknown:
return nullptr;
}
- NOTREACHED();
- return nullptr;
+ NOTREACHED_NORETURN();
}
} // namespace
diff --git a/fxbarcode/common/BC_CommonByteMatrix.h b/fxbarcode/common/BC_CommonByteMatrix.h
index 6ce611998..fa97f6904 100644
--- a/fxbarcode/common/BC_CommonByteMatrix.h
+++ b/fxbarcode/common/BC_CommonByteMatrix.h
@@ -10,7 +10,7 @@
#include <stdint.h>
#include "core/fxcrt/data_vector.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CBC_CommonByteMatrix final {
public:
diff --git a/fxbarcode/datamatrix/BC_SymbolInfo.cpp b/fxbarcode/datamatrix/BC_SymbolInfo.cpp
index 05efd5654..59d40d023 100644
--- a/fxbarcode/datamatrix/BC_SymbolInfo.cpp
+++ b/fxbarcode/datamatrix/BC_SymbolInfo.cpp
@@ -106,8 +106,7 @@ int32_t CBC_SymbolInfo::GetHorizontalDataRegions() const {
case 36:
return 6;
default:
- NOTREACHED();
- return 0;
+ NOTREACHED_NORETURN();
}
}
@@ -124,8 +123,7 @@ int32_t CBC_SymbolInfo::GetVerticalDataRegions() const {
case 36:
return 6;
default:
- NOTREACHED();
- return 0;
+ NOTREACHED_NORETURN();
}
}
diff --git a/fxbarcode/oned/BC_OneDimWriter.h b/fxbarcode/oned/BC_OneDimWriter.h
index 49957b5c2..3abcce488 100644
--- a/fxbarcode/oned/BC_OneDimWriter.h
+++ b/fxbarcode/oned/BC_OneDimWriter.h
@@ -18,7 +18,7 @@
#include "core/fxge/cfx_textrenderoptions.h"
#include "fxbarcode/BC_Library.h"
#include "fxbarcode/BC_Writer.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_Font;
class CFX_Matrix;
diff --git a/fxbarcode/pdf417/BC_PDF417BarcodeRow.h b/fxbarcode/pdf417/BC_PDF417BarcodeRow.h
index 160275eea..fc40701f3 100644
--- a/fxbarcode/pdf417/BC_PDF417BarcodeRow.h
+++ b/fxbarcode/pdf417/BC_PDF417BarcodeRow.h
@@ -10,7 +10,7 @@
#include <stdint.h>
#include "core/fxcrt/fixed_zeroed_data_vector.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CBC_BarcodeRow final {
public:
diff --git a/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h b/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h
index 16b80daa4..6e8f034ee 100644
--- a/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h
+++ b/fxbarcode/pdf417/BC_PDF417HighLevelEncoder.h
@@ -10,7 +10,7 @@
#include "core/fxcrt/widestring.h"
#include "fxbarcode/pdf417/BC_PDF417.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CBC_PDF417HighLevelEncoder {
public:
diff --git a/fxbarcode/qrcode/BC_QRCoderBitVector.h b/fxbarcode/qrcode/BC_QRCoderBitVector.h
index 1bfa24bb6..51bbe7c37 100644
--- a/fxbarcode/qrcode/BC_QRCoderBitVector.h
+++ b/fxbarcode/qrcode/BC_QRCoderBitVector.h
@@ -11,7 +11,7 @@
#include <stdint.h>
#include "core/fxcrt/data_vector.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CBC_QRCoderBitVector {
public:
diff --git a/fxbarcode/qrcode/BC_QRCoderMaskUtil.cpp b/fxbarcode/qrcode/BC_QRCoderMaskUtil.cpp
index f518c8b01..10fac61ca 100644
--- a/fxbarcode/qrcode/BC_QRCoderMaskUtil.cpp
+++ b/fxbarcode/qrcode/BC_QRCoderMaskUtil.cpp
@@ -196,8 +196,7 @@ bool CBC_QRCoderMaskUtil::GetDataMaskBit(int32_t maskPattern,
intermediate = (((temp % 3) + ((y + x) & 0x1)) & 0x1);
break;
default:
- NOTREACHED();
- return false;
+ NOTREACHED_NORETURN();
}
return intermediate == 0;
}
diff --git a/fxjs/cfx_globaldata.cpp b/fxjs/cfx_globaldata.cpp
index 59b43c1d6..6d6efd535 100644
--- a/fxjs/cfx_globaldata.cpp
+++ b/fxjs/cfx_globaldata.cpp
@@ -75,7 +75,6 @@ bool MakeByteString(const ByteString& name,
}
// Arrays don't get persisted per JS spec page 484.
case CFX_Value::DataType::kObject:
- default:
break;
}
return false;
@@ -293,10 +292,12 @@ bool CFX_GlobalData::LoadGlobalPersistentVariablesFromBuffer(
return false;
for (int32_t i = 0, sz = dwCount; i < sz; i++) {
- if (p > buffer.end())
+ if (p + sizeof(uint32_t) >= buffer.end()) {
break;
+ }
- uint32_t dwNameLen = *((uint32_t*)p);
+ uint32_t dwNameLen = 0;
+ memcpy(&dwNameLen, p, sizeof(uint32_t));
p += sizeof(uint32_t);
if (p + dwNameLen > buffer.end())
break;
@@ -304,21 +305,25 @@ bool CFX_GlobalData::LoadGlobalPersistentVariablesFromBuffer(
ByteString sEntry = ByteString(p, dwNameLen);
p += sizeof(char) * dwNameLen;
- CFX_Value::DataType wDataType =
- static_cast<CFX_Value::DataType>(*((uint16_t*)p));
+ uint16_t wDataType = 0;
+ memcpy(&wDataType, p, sizeof(uint16_t));
p += sizeof(uint16_t);
- switch (wDataType) {
+ CFX_Value::DataType eDataType = static_cast<CFX_Value::DataType>(wDataType);
+
+ switch (eDataType) {
case CFX_Value::DataType::kNumber: {
double dData = 0;
switch (wVersion) {
case 1: {
- uint32_t dwData = *((uint32_t*)p);
+ uint32_t dwData = 0;
+ memcpy(&dwData, p, sizeof(uint32_t));
p += sizeof(uint32_t);
dData = dwData;
} break;
case 2: {
- dData = *((double*)p);
+ dData = 0;
+ memcpy(&dData, p, sizeof(double));
p += sizeof(double);
} break;
}
@@ -326,13 +331,15 @@ bool CFX_GlobalData::LoadGlobalPersistentVariablesFromBuffer(
SetGlobalVariablePersistent(sEntry, true);
} break;
case CFX_Value::DataType::kBoolean: {
- uint16_t wData = *((uint16_t*)p);
+ uint16_t wData = 0;
+ memcpy(&wData, p, sizeof(uint16_t));
p += sizeof(uint16_t);
SetGlobalVariableBoolean(sEntry, (bool)(wData == 1));
SetGlobalVariablePersistent(sEntry, true);
} break;
case CFX_Value::DataType::kString: {
- uint32_t dwLength = *((uint32_t*)p);
+ uint32_t dwLength = 0;
+ memcpy(&dwLength, p, sizeof(uint32_t));
p += sizeof(uint32_t);
if (p + dwLength > buffer.end())
break;
@@ -346,8 +353,7 @@ bool CFX_GlobalData::LoadGlobalPersistentVariablesFromBuffer(
SetGlobalVariablePersistent(sEntry, true);
} break;
case CFX_Value::DataType::kObject:
- default:
- // Arrays aren't allowed in these buffers, nor are unrecoginzed tags.
+ // Arrays aren't allowed in these buffers, nor are unrecognized tags.
return false;
}
}
diff --git a/fxjs/cfx_globaldata.h b/fxjs/cfx_globaldata.h
index 6b9426593..ac940582f 100644
--- a/fxjs/cfx_globaldata.h
+++ b/fxjs/cfx_globaldata.h
@@ -14,7 +14,7 @@
#include "core/fxcrt/unowned_ptr.h"
#include "fxjs/cfx_keyvalue.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFX_GlobalData {
public:
diff --git a/fxjs/cjs_field.cpp b/fxjs/cjs_field.cpp
index 53b3449a1..c9127dd0f 100644
--- a/fxjs/cjs_field.cpp
+++ b/fxjs/cjs_field.cpp
@@ -235,7 +235,7 @@ void SetBorderStyle(CPDFSDK_FormFillEnvironment* pFormFillEnv,
const ByteString& bsString) {
DCHECK(pFormFillEnv);
- BorderStyle nBorderStyle = BorderStyle::kSolid;
+ BorderStyle nBorderStyle;
if (bsString == "solid")
nBorderStyle = BorderStyle::kSolid;
else if (bsString == "beveled")
@@ -2022,8 +2022,10 @@ CJS_Result CJS_Field::get_type(CJS_Runtime* pRuntime) {
return CJS_Result::Success(pRuntime->NewString("text"));
case FormFieldType::kSignature:
return CJS_Result::Success(pRuntime->NewString("signature"));
+#ifdef PDF_ENABLE_XFA
default:
return CJS_Result::Success(pRuntime->NewString("unknown"));
+#endif
}
}
@@ -2633,7 +2635,5 @@ void CJS_Field::DoDelay(CPDFSDK_FormFillEnvironment* pFormFillEnv,
SetFieldValue(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
pData->widestringarray);
break;
- default:
- NOTREACHED();
}
}
diff --git a/fxjs/cjs_global.cpp b/fxjs/cjs_global.cpp
index 101dee2cb..5582682f5 100644
--- a/fxjs/cjs_global.cpp
+++ b/fxjs/cjs_global.cpp
@@ -201,10 +201,7 @@ CJS_Result CJS_Global::GetProperty(CJS_Runtime* pRuntime,
v8::Local<v8::Object>::New(pRuntime->GetIsolate(), pData->pData));
case CFX_Value::DataType::kNull:
return CJS_Result::Success(pRuntime->NewNull());
- default:
- break;
}
- return CJS_Result::Failure(JSMessage::kObjectTypeError);
}
CJS_Result CJS_Global::SetProperty(CJS_Runtime* pRuntime,
@@ -491,8 +488,6 @@ CJS_Result CJS_Global::SetGlobalVariables(const ByteString& propname,
break;
case CFX_Value::DataType::kNull:
break;
- default:
- return CJS_Result::Failure(JSMessage::kObjectTypeError);
}
return CJS_Result::Success();
}
@@ -523,8 +518,6 @@ CJS_Result CJS_Global::SetGlobalVariables(const ByteString& propname,
pNewData->nType = CFX_Value::DataType::kNull;
pNewData->bPersistent = bDefaultPersistent;
break;
- default:
- return CJS_Result::Failure(JSMessage::kObjectTypeError);
}
m_MapGlobal[propname] = std::move(pNewData);
return CJS_Result::Success();
diff --git a/fxjs/cjs_object.h b/fxjs/cjs_object.h
index c53568eee..4c567f294 100644
--- a/fxjs/cjs_object.h
+++ b/fxjs/cjs_object.h
@@ -9,7 +9,7 @@
#include "core/fxcrt/unowned_ptr.h"
#include "fxjs/cjs_runtime.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class CFXJS_Engine;
diff --git a/fxjs/fxv8.h b/fxjs/fxv8.h
index 5ebd7f5cc..62c9bb342 100644
--- a/fxjs/fxv8.h
+++ b/fxjs/fxv8.h
@@ -12,7 +12,7 @@
#include <vector>
#include "core/fxcrt/fx_string.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#include "v8/include/v8-forward.h"
// The fxv8 functions soften up the interface to the V8 API. In particular,
diff --git a/fxjs/js_resources.cpp b/fxjs/js_resources.cpp
index c13361034..5c054fd87 100644
--- a/fxjs/js_resources.cpp
+++ b/fxjs/js_resources.cpp
@@ -6,8 +6,6 @@
#include "fxjs/js_resources.h"
-#include "third_party/base/notreached.h"
-
WideString JSGetStringFromID(JSMessage msg) {
const char* msg_string = "";
switch (msg) {
@@ -92,9 +90,6 @@ WideString JSGetStringFromID(JSMessage msg) {
case JSMessage::kWouldBeCyclic:
msg_string = "Operation would create a cycle.";
break;
- default:
- NOTREACHED();
- break;
}
return WideString::FromASCII(msg_string);
}
diff --git a/fxjs/xfa/cfxjse_class.cpp b/fxjs/xfa/cfxjse_class.cpp
index 26b4666be..c600bd7f4 100644
--- a/fxjs/xfa/cfxjse_class.cpp
+++ b/fxjs/xfa/cfxjse_class.cpp
@@ -103,7 +103,7 @@ void DynPropGetterAdapter_MethodCallback(
}
v8::Local<v8::String> hPropName =
- hCallBackInfo->GetInternalField(1).As<v8::String>();
+ hCallBackInfo->GetInternalField(1).As<v8::Value>().As<v8::String>();
if (hPropName.IsEmpty())
return;
diff --git a/fxjs/xfa/cfxjse_context.cpp b/fxjs/xfa/cfxjse_context.cpp
index 970cb3d7a..337b443ee 100644
--- a/fxjs/xfa/cfxjse_context.cpp
+++ b/fxjs/xfa/cfxjse_context.cpp
@@ -17,7 +17,7 @@
#include "fxjs/xfa/cjx_object.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
-#include "third_party/base/ptr_util.h"
+#include "third_party/base/memory/ptr_util.h"
#include "v8/include/v8-exception.h"
#include "v8/include/v8-function.h"
#include "v8/include/v8-message.h"
diff --git a/fxjs/xfa/cfxjse_engine.cpp b/fxjs/xfa/cfxjse_engine.cpp
index 601ffb42d..ecb8c96da 100644
--- a/fxjs/xfa/cfxjse_engine.cpp
+++ b/fxjs/xfa/cfxjse_engine.cpp
@@ -547,7 +547,8 @@ CJS_Result CFXJSE_Engine::NormalMethodCall(
for (int i = 0; i < info.Length(); i++)
parameters.push_back(info[i]);
- return pObject->JSObject()->RunMethod(functionName, parameters);
+ return pObject->JSObject()->RunMethod(pScriptContext, functionName,
+ parameters);
}
bool CFXJSE_Engine::IsStrictScopeInJavaScript() {
diff --git a/fxjs/xfa/cfxjse_formcalc_context.cpp b/fxjs/xfa/cfxjse_formcalc_context.cpp
index 4fc19d7d8..a99c13512 100644
--- a/fxjs/xfa/cfxjse_formcalc_context.cpp
+++ b/fxjs/xfa/cfxjse_formcalc_context.cpp
@@ -18,6 +18,7 @@
#include <vector>
#include "core/fxcrt/cfx_datetime.h"
+#include "core/fxcrt/code_point_view.h"
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/fx_random.h"
@@ -31,7 +32,6 @@
#include "fxjs/xfa/cjx_object.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/base/check_op.h"
-#include "third_party/base/cxx17_backports.h"
#include "third_party/base/numerics/safe_conversions.h"
#include "v8/include/v8-container.h"
#include "v8/include/v8-function-callback.h"
@@ -510,316 +510,6 @@ ByteString GUIDString(bool bSeparator) {
return bsGUID;
}
-bool IsIsoDateFormat(pdfium::span<const char> pData,
- int32_t* pStyle,
- int32_t* pYear,
- int32_t* pMonth,
- int32_t* pDay) {
- int32_t& iStyle = *pStyle;
- int32_t& iYear = *pYear;
- int32_t& iMonth = *pMonth;
- int32_t& iDay = *pDay;
-
- iYear = 0;
- iMonth = 1;
- iDay = 1;
-
- if (pData.size() < 4)
- return false;
-
- char szYear[5];
- szYear[4] = '\0';
- for (int32_t i = 0; i < 4; ++i) {
- if (!isdigit(pData[i]))
- return false;
-
- szYear[i] = pData[i];
- }
- iYear = FXSYS_atoi(szYear);
- iStyle = 0;
- if (pData.size() == 4)
- return true;
-
- iStyle = pData[4] == '-' ? 1 : 0;
-
- size_t iPosOff = iStyle == 0 ? 4 : 5;
- if (!isdigit(pData[iPosOff]) || !isdigit(pData[iPosOff + 1]))
- return false;
-
- char szBuffer[3] = {};
- szBuffer[0] = pData[iPosOff];
- szBuffer[1] = pData[iPosOff + 1];
- iMonth = FXSYS_atoi(szBuffer);
- if (iMonth > 12 || iMonth < 1)
- return false;
-
- if (iStyle == 0) {
- iPosOff += 2;
- if (pData.size() == 6)
- return true;
- } else {
- iPosOff += 3;
- if (pData.size() == 7)
- return true;
- }
- if (!isdigit(pData[iPosOff]) || !isdigit(pData[iPosOff + 1]))
- return false;
-
- szBuffer[0] = pData[iPosOff];
- szBuffer[1] = pData[iPosOff + 1];
- iDay = FXSYS_atoi(szBuffer);
- if (iPosOff + 2 < pData.size())
- return false;
-
- if (iMonth == 2) {
- bool bIsLeap = (!(iYear % 4) && (iYear % 100)) || !(iYear % 400);
- return iDay <= (bIsLeap ? 29 : 28);
- }
-
- if (iMonth < 8)
- return iDay <= (iMonth % 2 == 0 ? 30 : 31);
- return iDay <= (iMonth % 2 == 0 ? 31 : 30);
-}
-
-bool IsIsoTimeFormat(pdfium::span<const char> pData,
- int32_t* pHour,
- int32_t* pMinute,
- int32_t* pSecond,
- int32_t* pMilliSecond,
- int32_t* pZoneHour,
- int32_t* pZoneMinute) {
- int32_t& iHour = *pHour;
- int32_t& iMinute = *pMinute;
- int32_t& iSecond = *pSecond;
- int32_t& iMilliSecond = *pMilliSecond;
- int32_t& iZoneHour = *pZoneHour;
- int32_t& iZoneMinute = *pZoneMinute;
-
- iHour = 0;
- iMinute = 0;
- iSecond = 0;
- iMilliSecond = 0;
- iZoneHour = 0;
- iZoneMinute = 0;
-
- if (pData.empty())
- return false;
-
- size_t iZone = 0;
- size_t i = 0;
- while (i < pData.size()) {
- if (!isdigit(pData[i]) && pData[i] != ':') {
- iZone = i;
- break;
- }
- ++i;
- }
- if (i == pData.size())
- iZone = pData.size();
-
- char szBuffer[3] = {};
- size_t iPos = 0;
- size_t iIndex = 0;
- while (iIndex < iZone) {
- if (!isdigit(pData[iIndex]))
- return false;
-
- szBuffer[0] = pData[iIndex];
- if (!isdigit(pData[iIndex + 1]))
- return false;
-
- szBuffer[1] = pData[iIndex + 1];
- if (FXSYS_atoi(szBuffer) > 60)
- return false;
-
- if (pData[2] == ':') {
- if (iPos == 0) {
- iHour = FXSYS_atoi(szBuffer);
- ++iPos;
- } else if (iPos == 1) {
- iMinute = FXSYS_atoi(szBuffer);
- ++iPos;
- } else {
- iSecond = FXSYS_atoi(szBuffer);
- }
- iIndex += 3;
- } else {
- if (iPos == 0) {
- iHour = FXSYS_atoi(szBuffer);
- ++iPos;
- } else if (iPos == 1) {
- iMinute = FXSYS_atoi(szBuffer);
- ++iPos;
- } else if (iPos == 2) {
- iSecond = FXSYS_atoi(szBuffer);
- ++iPos;
- }
- iIndex += 2;
- }
- }
-
- if (iIndex < pData.size() && pData[iIndex] == '.') {
- constexpr int kSubSecondLength = 3;
- if (iIndex + kSubSecondLength >= pData.size())
- return false;
-
- ++iIndex;
- char szMilliSeconds[kSubSecondLength + 1];
- for (int j = 0; j < kSubSecondLength; ++j) {
- char c = pData[iIndex + j];
- if (!isdigit(c))
- return false;
- szMilliSeconds[j] = c;
- }
- szMilliSeconds[kSubSecondLength] = '\0';
-
- iMilliSecond = FXSYS_atoi(szMilliSeconds);
- if (iMilliSecond > 100) {
- iMilliSecond = 0;
- return false;
- }
- iIndex += kSubSecondLength;
- }
-
- if (iIndex < pData.size() && FXSYS_towlower(pData[iIndex]) == 'z')
- return true;
-
- int32_t iSign = 1;
- if (iIndex < pData.size()) {
- if (pData[iIndex] == '+') {
- ++iIndex;
- } else if (pData[iIndex] == '-') {
- iSign = -1;
- ++iIndex;
- }
- }
- iPos = 0;
- while (iIndex < pData.size()) {
- if (!isdigit(pData[iIndex]))
- return false;
-
- szBuffer[0] = pData[iIndex];
- if (!isdigit(pData[iIndex + 1]))
- return false;
-
- szBuffer[1] = pData[iIndex + 1];
- if (FXSYS_atoi(szBuffer) > 60)
- return false;
-
- if (pData[2] == ':') {
- if (iPos == 0) {
- iZoneHour = FXSYS_atoi(szBuffer);
- } else if (iPos == 1) {
- iZoneMinute = FXSYS_atoi(szBuffer);
- }
- iIndex += 3;
- } else {
- if (!iPos) {
- iZoneHour = FXSYS_atoi(szBuffer);
- ++iPos;
- } else if (iPos == 1) {
- iZoneMinute = FXSYS_atoi(szBuffer);
- ++iPos;
- }
- iIndex += 2;
- }
- }
- if (iIndex < pData.size())
- return false;
-
- iZoneHour *= iSign;
- return true;
-}
-
-bool IsIsoDateTimeFormat(pdfium::span<const char> pData,
- int32_t* pYear,
- int32_t* pMonth,
- int32_t* pDay,
- int32_t* pHour,
- int32_t* pMinute,
- int32_t* pSecond,
- int32_t* pMilliSecond,
- int32_t* pZoneHour,
- int32_t* pZoneMinute) {
- *pYear = 0;
- *pMonth = 0;
- *pDay = 0;
- *pHour = 0;
- *pMinute = 0;
- *pSecond = 0;
-
- size_t iIndex = 0;
- while (iIndex < pData.size()) {
- if (pData[iIndex] == 'T' || pData[iIndex] == 't')
- break;
- ++iIndex;
- }
- if (iIndex == pData.size() || (iIndex != 8 && iIndex != 10))
- return false;
-
- pdfium::span<const char> pDateSpan = pData.subspan(0, iIndex);
- pdfium::span<const char> pTimeSpan = pData.subspan(iIndex + 1);
-
- int32_t iStyle = -1;
- return IsIsoDateFormat(pDateSpan, &iStyle, pYear, pMonth, pDay) &&
- IsIsoTimeFormat(pTimeSpan, pHour, pMinute, pSecond, pMilliSecond,
- pZoneHour, pZoneMinute);
-}
-
-int32_t DateString2Num(ByteStringView bsDate) {
- int32_t iLength = bsDate.GetLength();
- int32_t iYear = 0;
- int32_t iMonth = 0;
- int32_t iDay = 0;
- if (iLength <= 10) {
- int32_t iStyle = -1;
- if (!IsIsoDateFormat(bsDate.span(), &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(bsDate.span(), &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;
- ++i;
- }
- return static_cast<int32_t>(dDays);
-}
-
void GetLocalTimeZone(int32_t* pHour, int32_t* pMin, int32_t* pSec) {
time_t now;
FXSYS_time(&now);
@@ -967,18 +657,20 @@ WideString DecodeXML(const WideString& wsXML) {
}
WideString EncodeURL(const ByteString& bsURL) {
- static const wchar_t kStrUnsafe[] = {' ', '<', '>', '"', '#', '%', '{', '}',
- '|', '\\', '^', '~', '[', ']', '`'};
- static const wchar_t kStrReserved[] = {';', '/', '?', ':', '@', '=', '&'};
- static const wchar_t kStrSpecial[] = {'$', '-', '+', '!', '*',
- '\'', '(', ')', ','};
+ static constexpr char32_t kStrUnsafe[] = {' ', '<', '>', '"', '#',
+ '%', '{', '}', '|', '\\',
+ '^', '~', '[', ']', '`'};
+ static constexpr char32_t kStrReserved[] = {';', '/', '?', ':',
+ '@', '=', '&'};
+ static constexpr char32_t kStrSpecial[] = {'$', '-', '+', '!', '*',
+ '\'', '(', ')', ','};
WideString wsURL = WideString::FromUTF8(bsURL.AsStringView());
WideTextBuffer wsResultBuf;
wchar_t szEncode[4];
szEncode[0] = '%';
szEncode[3] = 0;
- for (wchar_t ch : wsURL) {
+ for (char32_t ch : pdfium::CodePointView(wsURL.AsStringView())) {
size_t i = 0;
size_t iCount = std::size(kStrUnsafe);
while (i < iCount) {
@@ -1070,7 +762,7 @@ WideString EncodeHTML(const ByteString& bsHTML) {
szEncode[1] = '#';
szEncode[2] = 'x';
WideTextBuffer wsResultBuf;
- for (uint32_t ch : wsHTML) {
+ for (char32_t ch : pdfium::CodePointView(wsHTML.AsStringView())) {
WideString htmlReserve;
if (HTMLCode2STR(ch, &htmlReserve)) {
wsResultBuf.AppendChar(L'&');
@@ -1109,7 +801,7 @@ WideString EncodeXML(const ByteString& bsXML) {
szEncode[0] = '&';
szEncode[1] = '#';
szEncode[2] = 'x';
- for (uint32_t ch : wsXML) {
+ for (char32_t ch : pdfium::CodePointView(wsXML.AsStringView())) {
switch (ch) {
case '"':
wsResultBuf.AppendChar('&');
@@ -1885,7 +1577,7 @@ void CFXJSE_FormCalcContext::Round(
return;
}
double dPrecision = maybe_precision.value();
- uPrecision = static_cast<uint8_t>(pdfium::clamp(dPrecision, 0.0, 12.0));
+ uPrecision = static_cast<uint8_t>(std::clamp(dPrecision, 0.0, 12.0));
}
CFGAS_Decimal decimalValue(static_cast<float>(dValue), uPrecision);
@@ -4321,10 +4013,10 @@ void CFXJSE_FormCalcContext::Stuff(
ByteString bsSource = ValueToUTF8String(info.GetIsolate(), sourceValue);
int32_t iLength = pdfium::base::checked_cast<int32_t>(bsSource.GetLength());
if (iLength) {
- iStart = pdfium::clamp(
+ iStart = std::clamp(
static_cast<int32_t>(ValueToFloat(info.GetIsolate(), startValue)), 1,
iLength);
- iDelete = pdfium::clamp(
+ iDelete = std::clamp(
static_cast<int32_t>(ValueToFloat(info.GetIsolate(), deleteValue)), 0,
iLength - iStart + 1);
}
@@ -5440,6 +5132,279 @@ void CFXJSE_FormCalcContext::DotAccessorCommon(
info.GetReturnValue().Set(fxv8::NewArrayHelper(pIsolate, values));
}
+// static
+bool CFXJSE_FormCalcContext::IsIsoDateFormat(ByteStringView bsData,
+ int32_t* pYear,
+ int32_t* pMonth,
+ int32_t* pDay) {
+ pdfium::span<const char> pData = bsData.span();
+
+ int32_t& iYear = *pYear;
+ int32_t& iMonth = *pMonth;
+ int32_t& iDay = *pDay;
+
+ iYear = 0;
+ iMonth = 1;
+ iDay = 1;
+
+ if (pData.size() < 4) {
+ return false;
+ }
+
+ char szYear[5];
+ szYear[4] = '\0';
+ for (int32_t i = 0; i < 4; ++i) {
+ if (!isdigit(pData[i])) {
+ return false;
+ }
+
+ szYear[i] = pData[i];
+ }
+ iYear = FXSYS_atoi(szYear);
+ if (pData.size() == 4) {
+ return true;
+ }
+
+ int32_t iStyle = pData[4] == '-' ? 1 : 0;
+ size_t iPosOff = iStyle == 0 ? 4 : 5;
+ if (!isdigit(pData[iPosOff]) || !isdigit(pData[iPosOff + 1])) {
+ return false;
+ }
+
+ char szBuffer[3] = {};
+ szBuffer[0] = pData[iPosOff];
+ szBuffer[1] = pData[iPosOff + 1];
+ iMonth = FXSYS_atoi(szBuffer);
+ if (iMonth > 12 || iMonth < 1) {
+ return false;
+ }
+
+ if (iStyle == 0) {
+ iPosOff += 2;
+ if (pData.size() == 6) {
+ return true;
+ }
+ } else {
+ iPosOff += 3;
+ if (pData.size() == 7) {
+ return true;
+ }
+ }
+ if (!isdigit(pData[iPosOff]) || !isdigit(pData[iPosOff + 1])) {
+ return false;
+ }
+
+ szBuffer[0] = pData[iPosOff];
+ szBuffer[1] = pData[iPosOff + 1];
+ iDay = FXSYS_atoi(szBuffer);
+ if (iPosOff + 2 < pData.size()) {
+ return false;
+ }
+
+ if (iMonth == 2) {
+ bool bIsLeap = (!(iYear % 4) && (iYear % 100)) || !(iYear % 400);
+ return iDay <= (bIsLeap ? 29 : 28);
+ }
+
+ if (iMonth < 8) {
+ return iDay <= (iMonth % 2 == 0 ? 30 : 31);
+ }
+ return iDay <= (iMonth % 2 == 0 ? 31 : 30);
+}
+
+// static
+bool CFXJSE_FormCalcContext::IsIsoTimeFormat(ByteStringView bsData) {
+ enum State { kHour, kMinute, kSecond, kZoneHour, kZoneMinute, kFinished };
+
+ pdfium::span<const char> pData = bsData.span();
+ if (pData.empty()) {
+ return false;
+ }
+
+ size_t iZone = 0;
+ size_t i = 0;
+ while (i < pData.size()) {
+ if (!isdigit(pData[i]) && pData[i] != ':') {
+ iZone = i;
+ break;
+ }
+ ++i;
+ }
+ if (i == pData.size()) {
+ iZone = pData.size();
+ }
+
+ char szBuffer[3] = {}; // Last char always stays NUL for termination.
+ State state = kHour;
+ size_t iIndex = 0;
+ while (iIndex + 1 < iZone) {
+ szBuffer[0] = pData[iIndex];
+ szBuffer[1] = pData[iIndex + 1];
+ if (!isdigit(szBuffer[0]) || !isdigit(szBuffer[1])) {
+ return false;
+ }
+ int32_t value = FXSYS_atoi(szBuffer);
+ if (state == kHour) {
+ if (value >= 24) {
+ return false;
+ }
+ state = kMinute;
+ } else if (state == kMinute) {
+ if (value >= 60) {
+ return false;
+ }
+ state = kSecond;
+ } else if (state == kSecond) {
+ // Allow leap second.
+ if (value > 60) {
+ return false;
+ }
+ state = kFinished;
+ } else {
+ return false;
+ }
+ iIndex += 2;
+ if (iIndex < iZone && pData[iIndex] == ':') {
+ ++iIndex;
+ }
+ }
+
+ if (iIndex < pData.size() && pData[iIndex] == '.') {
+ constexpr int kSubSecondLength = 3;
+ if (iIndex + kSubSecondLength >= pData.size()) {
+ return false;
+ }
+
+ ++iIndex;
+ char szMilliSeconds[kSubSecondLength + 1] = {};
+ for (int j = 0; j < kSubSecondLength; ++j) {
+ char c = pData[iIndex + j];
+ if (!isdigit(c)) {
+ return false;
+ }
+ szMilliSeconds[j] = c;
+ }
+ if (FXSYS_atoi(szMilliSeconds) >= 1000) {
+ return false;
+ }
+ iIndex += kSubSecondLength;
+ }
+
+ if (iIndex < pData.size() && FXSYS_towlower(pData[iIndex]) == 'z') {
+ return true;
+ }
+
+ if (iIndex < pData.size()) {
+ if (pData[iIndex] == '+') {
+ ++iIndex;
+ } else if (pData[iIndex] == '-') {
+ ++iIndex;
+ }
+ }
+ state = kZoneHour;
+ while (iIndex + 1 < pData.size()) {
+ szBuffer[0] = pData[iIndex];
+ szBuffer[1] = pData[iIndex + 1];
+ if (!isdigit(szBuffer[0]) || !isdigit(szBuffer[1])) {
+ return false;
+ }
+ int32_t value = FXSYS_atoi(szBuffer);
+ if (state == kZoneHour) {
+ if (value >= 24) {
+ return false;
+ }
+ state = kZoneMinute;
+ } else if (state == kZoneMinute) {
+ if (value >= 60) {
+ return false;
+ }
+ state = kFinished;
+ } else {
+ return false;
+ }
+ iIndex += 2;
+ if (iIndex < pData.size() && pData[iIndex] == ':') {
+ ++iIndex;
+ }
+ }
+
+ // Success if all input was processed.
+ return iIndex == pData.size();
+}
+
+bool CFXJSE_FormCalcContext::IsIsoDateTimeFormat(ByteStringView bsData,
+ int32_t* pYear,
+ int32_t* pMonth,
+ int32_t* pDay) {
+ *pYear = 0;
+ *pMonth = 0;
+ *pDay = 0;
+
+ size_t iIndex = 0;
+ while (iIndex < bsData.GetLength()) {
+ if (bsData[iIndex] == 'T' || bsData[iIndex] == 't') {
+ break;
+ }
+ ++iIndex;
+ }
+ if (iIndex == bsData.GetLength() || (iIndex != 8 && iIndex != 10)) {
+ return false;
+ }
+
+ ByteStringView date_part = bsData.First(iIndex);
+ ByteStringView time_part = bsData.Substr(iIndex + 1);
+ return IsIsoDateFormat(date_part, pYear, pMonth, pDay) &&
+ IsIsoTimeFormat(time_part);
+}
+
+// static
+int32_t CFXJSE_FormCalcContext::DateString2Num(ByteStringView bsDate) {
+ int32_t iYear = 0;
+ int32_t iMonth = 0;
+ int32_t iDay = 0;
+ if (bsDate.GetLength() <= 10) {
+ if (!IsIsoDateFormat(bsDate, &iYear, &iMonth, &iDay)) {
+ return 0;
+ }
+ } else {
+ if (!IsIsoDateTimeFormat(bsDate, &iYear, &iMonth, &iDay)) {
+ 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;
+ ++i;
+ }
+ return static_cast<int32_t>(dDays);
+}
+
bool CFXJSE_FormCalcContext::ApplyToExpansion(
std::function<void(v8::Isolate*, v8::Local<v8::Value>)> fn,
const v8::FunctionCallbackInfo<v8::Value>& info,
diff --git a/fxjs/xfa/cfxjse_formcalc_context.h b/fxjs/xfa/cfxjse_formcalc_context.h
index 3c7d2715c..a0bf84fe7 100644
--- a/fxjs/xfa/cfxjse_formcalc_context.h
+++ b/fxjs/xfa/cfxjse_formcalc_context.h
@@ -11,6 +11,7 @@
#include <functional>
+#include "core/fxcrt/bytestring.h"
#include "core/fxcrt/widetext_buffer.h"
#include "fxjs/xfa/fxjse.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -266,10 +267,6 @@ class CFXJSE_FormCalcContext final : public CFXJSE_HostObject {
static void concat_fm_object(CFXJSE_HostObject* pThis,
const v8::FunctionCallbackInfo<v8::Value>& info);
- static ByteString GenerateSomExpression(ByteStringView bsName,
- int32_t iIndexFlags,
- int32_t iIndexValue,
- bool bIsStar);
static absl::optional<WideTextBuffer> Translate(cppgc::Heap* pHeap,
WideStringView wsFormcalc);
@@ -278,10 +275,33 @@ class CFXJSE_FormCalcContext final : public CFXJSE_HostObject {
CXFA_Document* GetDocument() const { return m_pDocument.Get(); }
private:
+ friend class FormCalcContextTest_GenerateSomExpression_Test;
+ friend class FormCalcContextTest_IsIsoDateFormat_Test;
+ friend class FormCalcContextTest_IsIsoTimeFormat_Test;
+
+ static ByteString GenerateSomExpression(ByteStringView bsName,
+ int32_t iIndexFlags,
+ int32_t iIndexValue,
+ bool bIsStar);
+
static void DotAccessorCommon(CFXJSE_HostObject* pThis,
const v8::FunctionCallbackInfo<v8::Value>& info,
bool bDotAccessor);
+ static bool IsIsoDateTimeFormat(ByteStringView bsData,
+ int32_t* pYear,
+ int32_t* pMonth,
+ int32_t* pDay);
+
+ static bool IsIsoDateFormat(ByteStringView bsData,
+ int32_t* pYear,
+ int32_t* pMonth,
+ int32_t* pDay);
+
+ static bool IsIsoTimeFormat(ByteStringView bsData);
+
+ static int32_t DateString2Num(ByteStringView bsDate);
+
bool ApplyToExpansion(
std::function<void(v8::Isolate*, v8::Local<v8::Value>)> fn,
const v8::FunctionCallbackInfo<v8::Value>& info,
diff --git a/fxjs/xfa/cfxjse_formcalc_context_embeddertest.cpp b/fxjs/xfa/cfxjse_formcalc_context_embeddertest.cpp
index 1478bf920..db03f03c6 100644
--- a/fxjs/xfa/cfxjse_formcalc_context_embeddertest.cpp
+++ b/fxjs/xfa/cfxjse_formcalc_context_embeddertest.cpp
@@ -11,7 +11,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/scoped_set_tz.h"
#include "testing/xfa_js_embedder_test.h"
-#include "third_party/base/cxx17_backports.h"
#include "xfa/fxfa/cxfa_eventparam.h"
class CFXJSE_FormCalcContextEmbedderTest : public XFAJSEmbedderTest {
@@ -717,13 +716,9 @@ TEST_F(CFXJSE_FormCalcContextEmbedderTest, Encode) {
ExecuteExpectString("Encode(\"\\u0022\\u00f5\\ufed0\", \"html\")",
"&quot;&otilde;&#xfed0;");
-#if !BUILDFLAG(IS_WIN)
- // Windows wchar_t isn't wide enough to handle these anyways.
- // TODO(tsepez): fix surrogate encodings.
ExecuteExpectString("Encode(\"\\uD83D\\uDCA9\", \"url\")", "%01%f4%a9");
ExecuteExpectString("Encode(\"\\uD83D\\uDCA9\", \"xml\")", "");
ExecuteExpectString("Encode(\"\\uD83D\\uDCA9\", \"html\")", "");
-#endif // !BUILDFLAG(IS_WIN)
}
TEST_F(CFXJSE_FormCalcContextEmbedderTest, DISABLED_Format) {
diff --git a/fxjs/xfa/cfxjse_formcalc_context_unittest.cpp b/fxjs/xfa/cfxjse_formcalc_context_unittest.cpp
index 2500e3f25..ee9437e9b 100644
--- a/fxjs/xfa/cfxjse_formcalc_context_unittest.cpp
+++ b/fxjs/xfa/cfxjse_formcalc_context_unittest.cpp
@@ -72,3 +72,72 @@ TEST(FormCalcContextTest, GenerateSomExpression) {
"mars", 3, -2147483648, /*bIsStar=*/false);
EXPECT_EQ(result, "mars[0]");
}
+
+TEST(FormCalcContextTest, IsIsoDateFormat) {
+ int32_t year = 0;
+ int32_t month = 0;
+ int32_t day = 0;
+
+ EXPECT_FALSE(
+ CFXJSE_FormCalcContext::IsIsoDateFormat("", &year, &month, &day));
+ EXPECT_TRUE(CFXJSE_FormCalcContext::IsIsoDateFormat("2023-06-24", &year,
+ &month, &day));
+ EXPECT_EQ(2023, year);
+ EXPECT_EQ(6, month);
+ EXPECT_EQ(24, day);
+}
+
+TEST(FormCalcContextTest, IsIsoTimeFormat) {
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat(""));
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat(":"));
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("::"));
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat(":::"));
+
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("2"));
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("2:"));
+
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("203"));
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("20:3"));
+
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("20304"));
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("20:30:4"));
+
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("2030405"));
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("20:30:40:5"));
+
+ EXPECT_TRUE(CFXJSE_FormCalcContext::IsIsoTimeFormat("20"));
+
+ EXPECT_TRUE(CFXJSE_FormCalcContext::IsIsoTimeFormat("2030"));
+ EXPECT_TRUE(CFXJSE_FormCalcContext::IsIsoTimeFormat("20:30"));
+
+ EXPECT_TRUE(CFXJSE_FormCalcContext::IsIsoTimeFormat("203040"));
+ EXPECT_TRUE(CFXJSE_FormCalcContext::IsIsoTimeFormat("20:30:40"));
+
+ EXPECT_TRUE(CFXJSE_FormCalcContext::IsIsoTimeFormat("203040.001"));
+ EXPECT_TRUE(CFXJSE_FormCalcContext::IsIsoTimeFormat("20:30:40.001"));
+
+ EXPECT_TRUE(CFXJSE_FormCalcContext::IsIsoTimeFormat("203040z"));
+ EXPECT_TRUE(CFXJSE_FormCalcContext::IsIsoTimeFormat("20:30:40z"));
+
+ EXPECT_TRUE(CFXJSE_FormCalcContext::IsIsoTimeFormat("203040+07:30"));
+ EXPECT_TRUE(CFXJSE_FormCalcContext::IsIsoTimeFormat("20:30:40+07:30"));
+
+ EXPECT_TRUE(CFXJSE_FormCalcContext::IsIsoTimeFormat("203040-07:30"));
+ EXPECT_TRUE(CFXJSE_FormCalcContext::IsIsoTimeFormat("20:30:40-07:30"));
+
+ // Range errors.
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("243040-07:30"));
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("24:30:40-07:30"));
+
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("206040-07:30"));
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("20:60:40-07:30"));
+
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("203061-07:30"));
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("20:30:61-07:30"));
+
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("203040-24:30"));
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("20:30:40-24:30"));
+
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("203040-07:60"));
+ EXPECT_FALSE(CFXJSE_FormCalcContext::IsIsoTimeFormat("20:30:40-07:60"));
+}
diff --git a/fxjs/xfa/cjx_eventpseudomodel.cpp b/fxjs/xfa/cjx_eventpseudomodel.cpp
index 72309dc4f..66dbb0779 100644
--- a/fxjs/xfa/cjx_eventpseudomodel.cpp
+++ b/fxjs/xfa/cjx_eventpseudomodel.cpp
@@ -126,8 +126,8 @@ void CJX_EventPseudoModel::newText(v8::Isolate* pIsolate,
if (bSetting)
return;
- CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
- CXFA_EventParam* pEventParam = pScriptContext->GetEventParam();
+ CXFA_EventParam* pEventParam =
+ GetDocument()->GetScriptContext()->GetEventParam();
if (!pEventParam)
return;
@@ -201,8 +201,7 @@ void CJX_EventPseudoModel::target(v8::Isolate* pIsolate,
CJS_Result CJX_EventPseudoModel::emit(
CFXJSE_Engine* runtime,
const std::vector<v8::Local<v8::Value>>& params) {
- CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
- CXFA_EventParam* pEventParam = pScriptContext->GetEventParam();
+ CXFA_EventParam* pEventParam = runtime->GetEventParam();
if (!pEventParam)
return CJS_Result::Success();
@@ -210,15 +209,14 @@ CJS_Result CJX_EventPseudoModel::emit(
if (!pNotify)
return CJS_Result::Success();
- pNotify->HandleWidgetEvent(pScriptContext->GetEventTarget(), pEventParam);
+ pNotify->HandleWidgetEvent(runtime->GetEventTarget(), pEventParam);
return CJS_Result::Success();
}
CJS_Result CJX_EventPseudoModel::reset(
CFXJSE_Engine* runtime,
const std::vector<v8::Local<v8::Value>>& params) {
- CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
- CXFA_EventParam* pEventParam = pScriptContext->GetEventParam();
+ CXFA_EventParam* pEventParam = runtime->GetEventParam();
if (pEventParam)
*pEventParam = CXFA_EventParam();
@@ -309,7 +307,6 @@ void CJX_EventPseudoModel::Property(v8::Isolate* pIsolate,
bSetting);
break;
case XFA_Event::Target:
- default:
break;
}
}
diff --git a/fxjs/xfa/cjx_exclgroup.cpp b/fxjs/xfa/cjx_exclgroup.cpp
index 11e6982e2..641f0f2b7 100644
--- a/fxjs/xfa/cjx_exclgroup.cpp
+++ b/fxjs/xfa/cjx_exclgroup.cpp
@@ -109,9 +109,7 @@ CJS_Result CJX_ExclGroup::selectedMember(
if (!pReturnNode)
return CJS_Result::Success(runtime->NewNull());
- return CJS_Result::Success(
- GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(
- pReturnNode));
+ return CJS_Result::Success(runtime->GetOrCreateJSBindingFromMap(pReturnNode));
}
void CJX_ExclGroup::defaultValue(v8::Isolate* pIsolate,
diff --git a/fxjs/xfa/cjx_form.cpp b/fxjs/xfa/cjx_form.cpp
index 4dab966f6..ec68b709a 100644
--- a/fxjs/xfa/cjx_form.cpp
+++ b/fxjs/xfa/cjx_form.cpp
@@ -82,8 +82,7 @@ CJS_Result CJX_Form::execInitialize(
CJS_Result CJX_Form::recalculate(
CFXJSE_Engine* runtime,
const std::vector<v8::Local<v8::Value>>& params) {
- CXFA_EventParam* pEventParam =
- GetDocument()->GetScriptContext()->GetEventParam();
+ CXFA_EventParam* pEventParam = runtime->GetEventParam();
if (pEventParam && (pEventParam->m_eType == XFA_EVENT_Calculate ||
pEventParam->m_eType == XFA_EVENT_InitCalculate)) {
return CJS_Result::Success();
diff --git a/fxjs/xfa/cjx_hostpseudomodel.cpp b/fxjs/xfa/cjx_hostpseudomodel.cpp
index 597db3025..f79a0cd9d 100644
--- a/fxjs/xfa/cjx_hostpseudomodel.cpp
+++ b/fxjs/xfa/cjx_hostpseudomodel.cpp
@@ -259,8 +259,9 @@ void CJX_HostPseudoModel::name(v8::Isolate* pIsolate,
CJS_Result CJX_HostPseudoModel::gotoURL(
CFXJSE_Engine* runtime,
const std::vector<v8::Local<v8::Value>>& params) {
- if (!GetDocument()->GetScriptContext()->IsRunAtClient())
+ if (!runtime->IsRunAtClient()) {
return CJS_Result::Success();
+ }
if (params.size() != 1)
return CJS_Result::Failure(JSMessage::kParamError);
@@ -276,8 +277,9 @@ CJS_Result CJX_HostPseudoModel::gotoURL(
CJS_Result CJX_HostPseudoModel::openList(
CFXJSE_Engine* runtime,
const std::vector<v8::Local<v8::Value>>& params) {
- if (!GetDocument()->GetScriptContext()->IsRunAtClient())
+ if (!runtime->IsRunAtClient()) {
return CJS_Result::Success();
+ }
if (params.size() != 1)
return CJS_Result::Failure(JSMessage::kParamError);
@@ -290,8 +292,7 @@ CJS_Result CJX_HostPseudoModel::openList(
if (params[0]->IsObject()) {
pNode = ToNode(runtime->ToXFAObject(params[0]));
} else if (params[0]->IsString()) {
- CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
- CXFA_Object* pObject = pScriptContext->GetThisObject();
+ CXFA_Object* pObject = runtime->GetThisObject();
if (!pObject)
return CJS_Result::Success();
@@ -299,7 +300,7 @@ CJS_Result CJX_HostPseudoModel::openList(
XFA_ResolveFlag::kParent,
XFA_ResolveFlag::kSiblings};
absl::optional<CFXJSE_Engine::ResolveResult> maybeResult =
- pScriptContext->ResolveObjects(
+ runtime->ResolveObjects(
pObject, runtime->ToWideString(params[0]).AsStringView(), kFlags);
if (!maybeResult.has_value() ||
!maybeResult.value().objects.front()->IsNode()) {
@@ -376,8 +377,7 @@ CJS_Result CJX_HostPseudoModel::resetData(
const size_t nExpLength = expression.GetLength();
while (nStart < nExpLength) {
nStart = FilterName(expression.AsStringView(), nStart, wsName);
- CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
- CXFA_Object* pObject = pScriptContext->GetThisObject();
+ CXFA_Object* pObject = runtime->GetThisObject();
if (!pObject)
return CJS_Result::Success();
@@ -385,7 +385,7 @@ CJS_Result CJX_HostPseudoModel::resetData(
XFA_ResolveFlag::kParent,
XFA_ResolveFlag::kSiblings};
absl::optional<CFXJSE_Engine::ResolveResult> maybeResult =
- pScriptContext->ResolveObjects(pObject, wsName.AsStringView(), kFlags);
+ runtime->ResolveObjects(pObject, wsName.AsStringView(), kFlags);
if (!maybeResult.has_value() ||
!maybeResult.value().objects.front()->IsNode())
continue;
@@ -402,8 +402,9 @@ CJS_Result CJX_HostPseudoModel::resetData(
CJS_Result CJX_HostPseudoModel::beep(
CFXJSE_Engine* runtime,
const std::vector<v8::Local<v8::Value>>& params) {
- if (!GetDocument()->GetScriptContext()->IsRunAtClient())
+ if (!runtime->IsRunAtClient()) {
return CJS_Result::Success();
+ }
if (params.size() > 1)
return CJS_Result::Failure(JSMessage::kParamError);
@@ -423,8 +424,9 @@ CJS_Result CJX_HostPseudoModel::beep(
CJS_Result CJX_HostPseudoModel::setFocus(
CFXJSE_Engine* runtime,
const std::vector<v8::Local<v8::Value>>& params) {
- if (!GetDocument()->GetScriptContext()->IsRunAtClient())
+ if (!runtime->IsRunAtClient()) {
return CJS_Result::Success();
+ }
if (params.size() != 1)
return CJS_Result::Failure(JSMessage::kParamError);
@@ -438,8 +440,7 @@ CJS_Result CJX_HostPseudoModel::setFocus(
if (params[0]->IsObject()) {
pNode = ToNode(runtime->ToXFAObject(params[0]));
} else if (params[0]->IsString()) {
- CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
- CXFA_Object* pObject = pScriptContext->GetThisObject();
+ CXFA_Object* pObject = runtime->GetThisObject();
if (!pObject)
return CJS_Result::Success();
@@ -447,7 +448,7 @@ CJS_Result CJX_HostPseudoModel::setFocus(
XFA_ResolveFlag::kParent,
XFA_ResolveFlag::kSiblings};
absl::optional<CFXJSE_Engine::ResolveResult> maybeResult =
- pScriptContext->ResolveObjects(
+ runtime->ResolveObjects(
pObject, runtime->ToWideString(params[0]).AsStringView(), kFlags);
if (!maybeResult.has_value() ||
!maybeResult.value().objects.front()->IsNode()) {
@@ -471,17 +472,15 @@ CJS_Result CJX_HostPseudoModel::getFocus(
if (!pNode)
return CJS_Result::Success();
- v8::Local<v8::Value> value =
- GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(pNode);
-
- return CJS_Result::Success(value);
+ return CJS_Result::Success(runtime->GetOrCreateJSBindingFromMap(pNode));
}
CJS_Result CJX_HostPseudoModel::messageBox(
CFXJSE_Engine* runtime,
const std::vector<v8::Local<v8::Value>>& params) {
- if (!GetDocument()->GetScriptContext()->IsRunAtClient())
+ if (!runtime->IsRunAtClient()) {
return CJS_Result::Success();
+ }
if (params.empty() || params.size() > 4)
return CJS_Result::Failure(JSMessage::kParamError);
@@ -526,8 +525,9 @@ CJS_Result CJX_HostPseudoModel::documentCountInBatch(
CJS_Result CJX_HostPseudoModel::print(
CFXJSE_Engine* runtime,
const std::vector<v8::Local<v8::Value>>& params) {
- if (!GetDocument()->GetScriptContext()->IsRunAtClient())
+ if (!runtime->IsRunAtClient()) {
return CJS_Result::Success();
+ }
if (params.size() != 8)
return CJS_Result::Failure(JSMessage::kParamError);
diff --git a/fxjs/xfa/cjx_instancemanager.cpp b/fxjs/xfa/cjx_instancemanager.cpp
index 18faf93b8..f5b4d61d1 100644
--- a/fxjs/xfa/cjx_instancemanager.cpp
+++ b/fxjs/xfa/cjx_instancemanager.cpp
@@ -250,8 +250,7 @@ CJS_Result CJX_InstanceManager::addInstance(
}
return CJS_Result::Success(
- GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(
- pNewInstance));
+ runtime->GetOrCreateJSBindingFromMap(pNewInstance));
}
CJS_Result CJX_InstanceManager::insertInstance(
@@ -291,8 +290,7 @@ CJS_Result CJX_InstanceManager::insertInstance(
}
return CJS_Result::Success(
- GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(
- pNewInstance));
+ runtime->GetOrCreateJSBindingFromMap(pNewInstance));
}
void CJX_InstanceManager::max(v8::Isolate* pIsolate,
diff --git a/fxjs/xfa/cjx_model.cpp b/fxjs/xfa/cjx_model.cpp
index 21a767d75..e94954e6f 100644
--- a/fxjs/xfa/cjx_model.cpp
+++ b/fxjs/xfa/cjx_model.cpp
@@ -65,11 +65,7 @@ CJS_Result CJX_Model::createNode(
if (pNewNode->GetPacketType() == XFA_PacketType::Datasets)
pNewNode->CreateXMLMappingNode();
}
-
- v8::Local<v8::Value> value =
- GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(pNewNode);
-
- return CJS_Result::Success(value);
+ return CJS_Result::Success(runtime->GetOrCreateJSBindingFromMap(pNewNode));
}
CJS_Result CJX_Model::isCompatibleNS(
diff --git a/fxjs/xfa/cjx_node.cpp b/fxjs/xfa/cjx_node.cpp
index 0685107a2..9db88ba36 100644
--- a/fxjs/xfa/cjx_node.cpp
+++ b/fxjs/xfa/cjx_node.cpp
@@ -137,9 +137,7 @@ CJS_Result CJX_Node::clone(CFXJSE_Engine* runtime,
return CJS_Result::Failure(JSMessage::kParamError);
CXFA_Node* pCloneNode = GetXFANode()->Clone(runtime->ToBoolean(params[0]));
- return CJS_Result::Success(
- GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(
- pCloneNode));
+ return CJS_Result::Success(runtime->GetOrCreateJSBindingFromMap(pCloneNode));
}
CJS_Result CJX_Node::getAttribute(
@@ -169,8 +167,7 @@ CJS_Result CJX_Node::getElement(
if (!pNode)
return CJS_Result::Success(runtime->NewNull());
- return CJS_Result::Success(
- GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(pNode));
+ return CJS_Result::Success(runtime->GetOrCreateJSBindingFromMap(pNode));
}
CJS_Result CJX_Node::isPropertySpecified(
diff --git a/fxjs/xfa/cjx_object.cpp b/fxjs/xfa/cjx_object.cpp
index 9d6cdf9bb..7542e8a30 100644
--- a/fxjs/xfa/cjx_object.cpp
+++ b/fxjs/xfa/cjx_object.cpp
@@ -159,14 +159,14 @@ bool CJX_Object::HasMethod(const WideString& func) const {
}
CJS_Result CJX_Object::RunMethod(
+ CFXJSE_Engine* pScriptContext,
const WideString& func,
const std::vector<v8::Local<v8::Value>>& params) {
auto it = method_specs_.find(func.ToUTF8());
if (it == method_specs_.end())
return CJS_Result::Failure(JSMessage::kUnknownMethod);
- return it->second(this, GetXFAObject()->GetDocument()->GetScriptContext(),
- params);
+ return it->second(this, pScriptContext, params);
}
void CJX_Object::ThrowTooManyOccurrencesException(v8::Isolate* pIsolate,
@@ -241,8 +241,6 @@ void CJX_Object::SetAttributeByEnum(XFA_Attribute eAttr,
case XFA_AttributeType::Measure:
SetMeasure(eAttr, CXFA_Measurement(wsValue.AsStringView()), bNotify);
break;
- default:
- break;
}
}
@@ -301,8 +299,6 @@ absl::optional<WideString> CJX_Object::TryAttribute(XFA_Attribute eAttr,
return absl::nullopt;
return value->ToString();
}
- default:
- break;
}
return absl::nullopt;
}
@@ -464,13 +460,15 @@ void CJX_Object::SetCDataImpl(XFA_Attribute eAttr,
return;
}
+ CFX_XMLElement* elem = ToXMLElement(xfaObj->GetXMLMappingNode());
+ if (!elem) {
+ return;
+ }
+
WideString wsAttrName = WideString::FromASCII(XFA_AttributeToName(eAttr));
if (eAttr == XFA_Attribute::ContentType)
wsAttrName = L"xfa:" + wsAttrName;
-
- CFX_XMLElement* elem = ToXMLElement(xfaObj->GetXMLMappingNode());
elem->SetAttribute(wsAttrName, wsValue);
- return;
}
void CJX_Object::SetAttributeValue(const WideString& wsValue,
diff --git a/fxjs/xfa/cjx_object.h b/fxjs/xfa/cjx_object.h
index caa1a5e5b..51a2a1325 100644
--- a/fxjs/xfa/cjx_object.h
+++ b/fxjs/xfa/cjx_object.h
@@ -16,7 +16,7 @@
#include "fxjs/xfa/fxjse.h"
#include "fxjs/xfa/jse_define.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#include "v8/include/cppgc/garbage-collected.h"
#include "v8/include/cppgc/member.h"
#include "v8/include/v8-forward.h"
@@ -119,7 +119,8 @@ class CJX_Object : public cppgc::GarbageCollected<CJX_Object>,
CXFA_LayoutItem* GetLayoutItem() const { return layout_item_; }
bool HasMethod(const WideString& func) const;
- CJS_Result RunMethod(const WideString& func,
+ CJS_Result RunMethod(CFXJSE_Engine* pScriptContext,
+ const WideString& func,
const std::vector<v8::Local<v8::Value>>& params);
bool HasAttribute(XFA_Attribute eAttr) const;
diff --git a/fxjs/xfa/cjx_tree.cpp b/fxjs/xfa/cjx_tree.cpp
index ec562cedd..daabd09e9 100644
--- a/fxjs/xfa/cjx_tree.cpp
+++ b/fxjs/xfa/cjx_tree.cpp
@@ -43,13 +43,12 @@ CJS_Result CJX_Tree::resolveNode(
return CJS_Result::Failure(JSMessage::kParamError);
WideString wsExpression = runtime->ToWideString(params[0]);
- CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
CXFA_Object* pRefNode = GetXFAObject();
if (pRefNode->GetElementType() == XFA_Element::Xfa)
- pRefNode = pScriptContext->GetThisObject();
+ pRefNode = runtime->GetThisObject();
absl::optional<CFXJSE_Engine::ResolveResult> maybeResult =
- pScriptContext->ResolveObjects(
+ runtime->ResolveObjects(
ToNode(pRefNode), wsExpression.AsStringView(),
Mask<XFA_ResolveFlag>{
XFA_ResolveFlag::kChildren, XFA_ResolveFlag::kAttributes,
@@ -59,9 +58,8 @@ CJS_Result CJX_Tree::resolveNode(
return CJS_Result::Success(runtime->NewNull());
if (maybeResult.value().type == CFXJSE_Engine::ResolveResult::Type::kNodes) {
- return CJS_Result::Success(
- GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(
- maybeResult.value().objects.front().Get()));
+ return CJS_Result::Success(runtime->GetOrCreateJSBindingFromMap(
+ maybeResult.value().objects.front().Get()));
}
if (!maybeResult.value().script_attribute.callback ||
@@ -86,14 +84,13 @@ CJS_Result CJX_Tree::resolveNodes(
CXFA_Object* refNode = GetXFAObject();
if (refNode->GetElementType() == XFA_Element::Xfa)
- refNode = GetDocument()->GetScriptContext()->GetThisObject();
+ refNode = runtime->GetThisObject();
- CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
const Mask<XFA_ResolveFlag> kFlags = {
XFA_ResolveFlag::kChildren, XFA_ResolveFlag::kAttributes,
XFA_ResolveFlag::kProperties, XFA_ResolveFlag::kParent,
XFA_ResolveFlag::kSiblings};
- return CJS_Result::Success(ResolveNodeList(pScriptContext->GetIsolate(),
+ return CJS_Result::Success(ResolveNodeList(runtime->GetIsolate(),
runtime->ToWideString(params[0]),
kFlags, ToNode(refNode)));
}
diff --git a/fxjs/xfa/cjx_treelist.cpp b/fxjs/xfa/cjx_treelist.cpp
index e2e4a21a2..a72134954 100644
--- a/fxjs/xfa/cjx_treelist.cpp
+++ b/fxjs/xfa/cjx_treelist.cpp
@@ -44,6 +44,5 @@ CJS_Result CJX_TreeList::namedItem(
if (!pNode)
return CJS_Result::Success();
- return CJS_Result::Success(
- GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(pNode));
+ return CJS_Result::Success(runtime->GetOrCreateJSBindingFromMap(pNode));
}
diff --git a/fxjs/xfa/fxjse.h b/fxjs/xfa/fxjse.h
index b020ce685..04d746b53 100644
--- a/fxjs/xfa/fxjse.h
+++ b/fxjs/xfa/fxjse.h
@@ -10,6 +10,7 @@
#include <stdint.h>
#include "core/fxcrt/fx_string.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
#include "v8/include/v8-forward.h"
namespace pdfium {
@@ -78,7 +79,7 @@ struct FXJSE_FUNCTION_DESCRIPTOR {
struct FXJSE_CLASS_DESCRIPTOR {
const char* tag; // `pdfium::fxjse::kClassTag` always.
const char* name;
- const FXJSE_FUNCTION_DESCRIPTOR* methods;
+ UNOWNED_PTR_EXCLUSION const FXJSE_FUNCTION_DESCRIPTOR* methods;
int32_t methNum;
FXJSE_PropTypeGetter dynPropTypeGetter;
FXJSE_PropGetter dynPropGetter;
diff --git a/pdfium.gni b/pdfium.gni
index 9c6ae8d64..ffa740a9c 100644
--- a/pdfium.gni
+++ b/pdfium.gni
@@ -41,7 +41,11 @@ declare_args() {
# standalone PDFium, and not when PDFium is embedded in our projects.
pdf_use_cxx20 = (is_win && is_component_build) || is_fuchsia
- # Build PDFium with PartitionAlloc as the memory allocator.
+ # Build PDFium against PartitionAlloc. When false, PDFium must build without
+ # requiring any PartitionAlloc headers or code to be present. When true,
+ # PDFium will use PartitionAlloc partitions to separate strings, scalars,
+ # etc. from other allocations. However, the use of PartitionAlloc for new or
+ # malloc is controlled by args in build_overrides/partition_alloc.gni.
pdf_use_partition_alloc = pdf_use_partition_alloc_override
# Build PDFium to use Skia (experimental) for all PDFium graphics.
@@ -49,7 +53,8 @@ declare_args() {
# renderer is selectable at runtime.
pdf_use_skia = pdf_use_skia_override
- # Build PDFium standalone
+ # Build PDFium standalone. Now only controls whether the test binaries
+ # are built. Most logic is conditioned by build_with_chromium.
pdf_is_standalone = false
# Build a complete static library
diff --git a/public/DEPS b/public/DEPS
index d0005cacd..74caee4f8 100644
--- a/public/DEPS
+++ b/public/DEPS
@@ -1,8 +1,2 @@
-include_rules = [
- # public/ needs to be standalone. Explicitly disallow everything.
- '-core',
- '-fpdfsdk',
- '-testing',
- '-third_party',
- '-v8',
-]
+# public/ needs to be standalone; don't inherit any include rules.
+noparent = True
diff --git a/public/fpdf_formfill.h b/public/fpdf_formfill.h
index 2bcf7f7c1..a0769b7b9 100644
--- a/public/fpdf_formfill.h
+++ b/public/fpdf_formfill.h
@@ -8,7 +8,7 @@
#define PUBLIC_FPDF_FORMFILL_H_
// clang-format off
-// NOLINTNEXTLINE(build/include)
+// NOLINTNEXTLINE(build/include_directory)
#include "fpdfview.h"
// These values are return values for a public API, so should not be changed
@@ -1913,15 +1913,15 @@ FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLDraw(FPDF_FORMHANDLE hHandle,
int flags);
#if defined(_SKIA_SUPPORT_)
-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);
+FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLDrawSkia(FPDF_FORMHANDLE hHandle,
+ FPDF_SKIA_CANVAS canvas,
+ FPDF_PAGE page,
+ int start_x,
+ int start_y,
+ int size_x,
+ int size_y,
+ int rotate,
+ int flags);
#endif
/*
diff --git a/public/fpdfview.h b/public/fpdfview.h
index 206bfe2d5..0c901a753 100644
--- a/public/fpdfview.h
+++ b/public/fpdfview.h
@@ -4,6 +4,14 @@
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+// This is the main header file for embedders of PDFium. It provides APIs to
+// initialize the library, load documents, and render pages, amongst other
+// things.
+//
+// NOTE: None of the PDFium APIs are thread-safe. They expect to be called
+// from a single thread. Barring that, embedders are required to ensure (via
+// a mutex or similar) that only a single PDFium call can be made at a time.
+//
// NOTE: External docs refer to this file as "fpdfview.h", so do not rename
// despite lack of consistency with other public files.
@@ -71,9 +79,9 @@ typedef struct fpdf_pageobject_t__* FPDF_PAGEOBJECT; // (text, path, etc.)
typedef struct fpdf_pageobjectmark_t__* FPDF_PAGEOBJECTMARK;
typedef const struct fpdf_pagerange_t__* FPDF_PAGERANGE;
typedef const struct fpdf_pathsegment_t* FPDF_PATHSEGMENT;
-typedef void* FPDF_RECORDER; // Passed into Skia as a SkPictureRecorder.
typedef struct fpdf_schhandle_t__* FPDF_SCHHANDLE;
typedef const struct fpdf_signature_t__* FPDF_SIGNATURE;
+typedef void* FPDF_SKIA_CANVAS; // Passed into Skia as an SkCanvas.
typedef struct fpdf_structelement_t__* FPDF_STRUCTELEMENT;
typedef const struct fpdf_structelement_attr_t__* FPDF_STRUCTELEMENT_ATTR;
typedef struct fpdf_structtree_t__* FPDF_STRUCTTREE;
@@ -98,12 +106,14 @@ typedef enum _FPDF_DUPLEXTYPE_ {
// String types
typedef unsigned short FPDF_WCHAR;
-// FPDFSDK may use three types of strings: byte string, wide string (UTF-16LE
-// encoded), and platform dependent string
+// The public PDFium API uses three types of strings: byte string, wide string
+// (UTF-16LE encoded), and platform dependent string.
+
+// Public PDFium API type for byte strings.
typedef const char* FPDF_BYTESTRING;
-// FPDFSDK always uses UTF-16LE encoded wide strings, each character uses 2
-// bytes (except surrogation), with the low byte first.
+// The public PDFium API always uses UTF-16LE encoded wide strings, each
+// character uses 2 bytes (except surrogation), with the low byte first.
typedef const FPDF_WCHAR* FPDF_WIDESTRING;
// Structure for persisting a string beyond the duration of a callback.
@@ -222,18 +232,6 @@ typedef int FPDF_OBJECT_TYPE;
extern "C" {
#endif
-// Function: FPDF_InitLibrary
-// Initialize the FPDFSDK library
-// Parameters:
-// None
-// Return value:
-// None.
-// Comments:
-// Convenience function to call FPDF_InitLibraryWithConfig() for
-// backwards compatibility purposes. This will be deprecated in the
-// future.
-FPDF_EXPORT void FPDF_CALLCONV FPDF_InitLibrary();
-
// PDF renderer types - Experimental.
// Selection of 2D graphics library to use for rendering to FPDF_BITMAPs.
typedef enum {
@@ -280,11 +278,10 @@ typedef struct FPDF_LIBRARY_CONFIG_ {
// corresponding render library is not included in the build will similarly
// fail with an immediate crash.
FPDF_RENDERER_TYPE m_RendererType;
-
} FPDF_LIBRARY_CONFIG;
// Function: FPDF_InitLibraryWithConfig
-// Initialize the FPDFSDK library
+// Initialize the PDFium library and allocate global resources for it.
// Parameters:
// config - configuration information as above.
// Return value:
@@ -295,17 +292,33 @@ typedef struct FPDF_LIBRARY_CONFIG_ {
FPDF_EXPORT void FPDF_CALLCONV
FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG* config);
-// Function: FPDF_DestroyLibary
-// Release all resources allocated by the FPDFSDK library.
+// Function: FPDF_InitLibrary
+// Initialize the PDFium library (alternative form).
+// Parameters:
+// None
+// Return value:
+// None.
+// Comments:
+// Convenience function to call FPDF_InitLibraryWithConfig() with a
+// default configuration for backwards compatibility purposes. New
+// code should call FPDF_InitLibraryWithConfig() instead. This will
+// be deprecated in the future.
+FPDF_EXPORT void FPDF_CALLCONV FPDF_InitLibrary();
+
+// Function: FPDF_DestroyLibrary
+// Release global resources allocated to the PDFium library by
+// FPDF_InitLibrary() or FPDF_InitLibraryWithConfig().
// Parameters:
// None.
// Return value:
// None.
// Comments:
-// You can call this function to release all memory blocks allocated by
-// the library.
-// After this function is called, you should not call any PDF
+// After this function is called, you must not call any PDF
// processing functions.
+//
+// Calling this function does not automatically close other
+// objects. It is recommended to close other objects before
+// closing the library with this function.
FPDF_EXPORT void FPDF_CALLCONV FPDF_DestroyLibrary();
// Policy for accessing the local machine time.
@@ -435,7 +448,7 @@ typedef struct {
// Position is specified by byte offset from the beginning of the file.
// The pointer to the buffer is never NULL and the size is never 0.
// The position and size will never go out of range of the file length.
- // It may be possible for FPDFSDK to call this function multiple times for
+ // It may be possible for PDFium to call this function multiple times for
// the same position.
// Return value: should be non-zero if successful, zero for error.
int (*m_GetBlock)(void* param,
@@ -912,18 +925,19 @@ FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap,
#if defined(_SKIA_SUPPORT_)
// Experimental API.
-// Function: FPDF_RenderPageSkp
-// Render contents of a page to a Skia SkPictureRecorder.
+// Function: FPDF_RenderPageSkia
+// Render contents of a page to a Skia SkCanvas.
// Parameters:
+// canvas - SkCanvas to render to.
// page - Handle to the page.
// size_x - Horizontal size (in pixels) for displaying the page.
// size_y - Vertical size (in pixels) for displaying the page.
// Return value:
-// The SkPictureRecorder that holds the rendering of the page, or NULL
-// on failure. Caller takes ownership of the returned result.
-FPDF_EXPORT FPDF_RECORDER FPDF_CALLCONV FPDF_RenderPageSkp(FPDF_PAGE page,
- int size_x,
- int size_y);
+// None.
+FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPageSkia(FPDF_SKIA_CANVAS canvas,
+ FPDF_PAGE page,
+ int size_x,
+ int size_y);
#endif
// Function: FPDF_ClosePage
diff --git a/samples/BUILD.gn b/samples/BUILD.gn
index ccf7ff85d..981750ba9 100644
--- a/samples/BUILD.gn
+++ b/samples/BUILD.gn
@@ -21,7 +21,9 @@ config("pdfium_samples_config") {
if (is_asan) {
defines += [ "PDF_ENABLE_ASAN" ]
}
-
+ if (pdf_use_partition_alloc) {
+ defines += [ "PDF_USE_PARTITION_ALLOC" ]
+ }
if (enable_callgrind) {
defines += [ "ENABLE_CALLGRIND" ]
}
@@ -33,13 +35,15 @@ config("pdfium_samples_config") {
executable("pdfium_test") {
testonly = true
sources = [
+ "helpers/dump.cc",
+ "helpers/dump.h",
+ "helpers/event.cc",
+ "helpers/event.h",
+ "helpers/page_renderer.cc",
+ "helpers/page_renderer.h",
+ "helpers/write.cc",
+ "helpers/write.h",
"pdfium_test.cc",
- "pdfium_test_dump_helper.cc",
- "pdfium_test_dump_helper.h",
- "pdfium_test_event_helper.cc",
- "pdfium_test_event_helper.h",
- "pdfium_test_write_helper.cc",
- "pdfium_test_write_helper.h",
]
# Note: One should write programs that depend on ../:pdfium. Whereas this
@@ -55,6 +59,13 @@ executable("pdfium_test") {
]
configs += [ ":pdfium_samples_config" ]
+ if (is_win) {
+ sources += [
+ "helpers/win32/com_factory.cc",
+ "helpers/win32/com_factory.h",
+ ]
+ }
+
if (pdf_enable_v8) {
deps += [
"//v8:v8_headers",
diff --git a/samples/pdfium_test_dump_helper.cc b/samples/helpers/dump.cc
index 4d45390c7..e2a8469b2 100644
--- a/samples/pdfium_test_dump_helper.cc
+++ b/samples/helpers/dump.cc
@@ -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 "samples/pdfium_test_dump_helper.h"
+#include "samples/helpers/dump.h"
#include <limits.h>
#include <string.h>
@@ -98,15 +98,17 @@ 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);
- if (len > 0)
+ if (len > 0) {
printf("%*s S: %ls\n", indent * 2, "", ConvertToWString(buf, len).c_str());
+ }
int attr_count = FPDF_StructElement_GetAttributeCount(child);
for (int i = 0; i < attr_count; i++) {
FPDF_STRUCTELEMENT_ATTR child_attr =
FPDF_StructElement_GetAttributeAtIndex(child, i);
- if (!child_attr)
+ if (!child_attr) {
continue;
+ }
printf("%*s A[%d]:\n", indent * 2, "", i);
DumpStructureElementAttributes(child_attr, indent * 2 + 2);
}
@@ -127,8 +129,9 @@ void DumpChildStructure(FPDF_STRUCTELEMENT child, int indent) {
memset(buf, 0, sizeof(buf));
len = FPDF_StructElement_GetID(child, buf, kBufSize);
- if (len > 0)
+ if (len > 0) {
printf("%*s ID: %ls\n", indent * 2, "", ConvertToWString(buf, len).c_str());
+ }
memset(buf, 0, sizeof(buf));
len = FPDF_StructElement_GetLang(child, buf, kBufSize);
@@ -138,8 +141,9 @@ void DumpChildStructure(FPDF_STRUCTELEMENT child, int indent) {
}
int mcid = FPDF_StructElement_GetMarkedContentID(child);
- if (mcid != -1)
+ if (mcid != -1) {
printf("%*s MCID: %d\n", indent * 2, "", mcid);
+ }
FPDF_STRUCTELEMENT parent = FPDF_StructElement_GetParent(child);
if (parent) {
@@ -169,8 +173,9 @@ void DumpChildStructure(FPDF_STRUCTELEMENT child, int indent) {
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)
+ if (!sub_child) {
continue;
+ }
DumpChildStructure(sub_child, indent + 1);
}
@@ -211,8 +216,9 @@ void DumpMetaData(FPDF_DOCUMENT doc) {
char meta_buffer[4096];
unsigned long len =
FPDF_GetMetaText(doc, meta_tag, meta_buffer, sizeof(meta_buffer));
- if (!len)
+ if (!len) {
continue;
+ }
auto* meta_string = reinterpret_cast<unsigned short*>(meta_buffer);
printf("%-12s = %ls (%lu bytes)\n", meta_tag,
diff --git a/samples/pdfium_test_dump_helper.h b/samples/helpers/dump.h
index 727731e73..6682b292c 100644
--- a/samples/pdfium_test_dump_helper.h
+++ b/samples/helpers/dump.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef SAMPLES_PDFIUM_TEST_DUMP_HELPER_H_
-#define SAMPLES_PDFIUM_TEST_DUMP_HELPER_H_
+#ifndef SAMPLES_HELPERS_DUMP_H_
+#define SAMPLES_HELPERS_DUMP_H_
#include "public/fpdfview.h"
@@ -12,4 +12,4 @@ void DumpPageInfo(FPDF_PAGE page, int page_idx);
void DumpPageStructure(FPDF_PAGE page, int page_idx);
void DumpMetaData(FPDF_DOCUMENT doc);
-#endif // SAMPLES_PDFIUM_TEST_DUMP_HELPER_H_
+#endif // SAMPLES_HELPERS_DUMP_H_
diff --git a/samples/pdfium_test_event_helper.cc b/samples/helpers/event.cc
index d55057ee8..48491e898 100644
--- a/samples/pdfium_test_event_helper.cc
+++ b/samples/helpers/event.cc
@@ -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 "samples/pdfium_test_event_helper.h"
+#include "samples/helpers/event.h"
#include <stdio.h>
@@ -17,12 +17,15 @@ namespace {
uint32_t GetModifiers(std::string modifiers_string) {
uint32_t modifiers = 0;
- if (modifiers_string.find("shift") != std::string::npos)
+ if (modifiers_string.find("shift") != std::string::npos) {
modifiers |= FWL_EVENTFLAG_ShiftKey;
- if (modifiers_string.find("control") != std::string::npos)
+ }
+ if (modifiers_string.find("control") != std::string::npos) {
modifiers |= FWL_EVENTFLAG_ControlKey;
- if (modifiers_string.find("alt") != std::string::npos)
+ }
+ if (modifiers_string.find("alt") != std::string::npos) {
modifiers |= FWL_EVENTFLAG_AltKey;
+ }
return modifiers;
}
@@ -65,12 +68,13 @@ void SendMouseDownEvent(FPDF_FORMHANDLE form,
int y = atoi(tokens[3].c_str());
uint32_t modifiers = tokens.size() >= 5 ? GetModifiers(tokens[4]) : 0;
- if (tokens[1] == "left")
+ if (tokens[1] == "left") {
FORM_OnLButtonDown(form, page, modifiers, x, y);
- else if (tokens[1] == "right")
+ } else if (tokens[1] == "right") {
FORM_OnRButtonDown(form, page, modifiers, x, y);
- else
+ } else {
fprintf(stderr, "mousedown: bad button name\n");
+ }
}
void SendMouseUpEvent(FPDF_FORMHANDLE form,
@@ -84,12 +88,13 @@ void SendMouseUpEvent(FPDF_FORMHANDLE form,
int x = atoi(tokens[2].c_str());
int y = atoi(tokens[3].c_str());
int modifiers = tokens.size() >= 5 ? GetModifiers(tokens[4]) : 0;
- if (tokens[1] == "left")
+ if (tokens[1] == "left") {
FORM_OnLButtonUp(form, page, modifiers, x, y);
- else if (tokens[1] == "right")
+ } else if (tokens[1] == "right") {
FORM_OnRButtonUp(form, page, modifiers, x, y);
- else
+ } else {
fprintf(stderr, "mouseup: bad button name\n");
+ }
}
void SendMouseDoubleClickEvent(FPDF_FORMHANDLE form,
@@ -161,8 +166,9 @@ void SendPageEvents(FPDF_FORMHANDLE form,
auto lines = StringSplit(events, '\n');
for (const auto& line : lines) {
auto command = StringSplit(line, '#');
- if (command[0].empty())
+ if (command[0].empty()) {
continue;
+ }
auto tokens = StringSplit(command[0], ',');
if (tokens[0] == "charcode") {
SendCharCodeEvent(form, page, tokens);
diff --git a/samples/pdfium_test_event_helper.h b/samples/helpers/event.h
index 2f2825a18..021c075e7 100644
--- a/samples/pdfium_test_event_helper.h
+++ b/samples/helpers/event.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef SAMPLES_PDFIUM_TEST_EVENT_HELPER_H_
-#define SAMPLES_PDFIUM_TEST_EVENT_HELPER_H_
+#ifndef SAMPLES_HELPERS_EVENT_H_
+#define SAMPLES_HELPERS_EVENT_H_
#include <functional>
#include <string>
@@ -16,4 +16,4 @@ void SendPageEvents(FPDF_FORMHANDLE form,
const std::string& events,
const std::function<void()>& idler);
-#endif // SAMPLES_PDFIUM_TEST_EVENT_HELPER_H_
+#endif // SAMPLES_HELPERS_EVENT_H_
diff --git a/samples/helpers/page_renderer.cc b/samples/helpers/page_renderer.cc
new file mode 100644
index 000000000..e7771ef66
--- /dev/null
+++ b/samples/helpers/page_renderer.cc
@@ -0,0 +1,16 @@
+// Copyright 2023 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "samples/helpers/page_renderer.h"
+
+#include "public/fpdfview.h"
+
+PageRenderer::PageRenderer(FPDF_PAGE page, int width, int height, int flags)
+ : page_(page), width_(width), height_(height), flags_(flags) {}
+
+PageRenderer::~PageRenderer() = default;
+
+bool PageRenderer::Continue() {
+ return false;
+}
diff --git a/samples/helpers/page_renderer.h b/samples/helpers/page_renderer.h
new file mode 100644
index 000000000..277bd0fd9
--- /dev/null
+++ b/samples/helpers/page_renderer.h
@@ -0,0 +1,47 @@
+// Copyright 2023 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SAMPLES_HELPERS_PAGE_RENDERER_H_
+#define SAMPLES_HELPERS_PAGE_RENDERER_H_
+
+#include <string>
+
+#include "public/fpdfview.h"
+
+// Renderer for a single page.
+class PageRenderer {
+ public:
+ virtual ~PageRenderer();
+
+ // Returns `true` if the rendered output exists. Must call `Finish()` first.
+ virtual bool HasOutput() const = 0;
+
+ // Starts rendering the page, returning `false` on failure.
+ virtual bool Start() = 0;
+
+ // Continues rendering the page, returning `false` when complete.
+ virtual bool Continue();
+
+ // Finishes rendering the page.
+ virtual void Finish(FPDF_FORMHANDLE form) = 0;
+
+ // Writes rendered output to a file, returning `false` on failure.
+ virtual bool Write(const std::string& name, int page_index, bool md5) = 0;
+
+ protected:
+ PageRenderer(FPDF_PAGE page, int width, int height, int flags);
+
+ FPDF_PAGE page() { return page_; }
+ int width() const { return width_; }
+ int height() const { return height_; }
+ int flags() const { return flags_; }
+
+ private:
+ FPDF_PAGE page_;
+ int width_;
+ int height_;
+ int flags_;
+};
+
+#endif // SAMPLES_HELPERS_PAGE_RENDERER_H_
diff --git a/samples/helpers/win32/com_factory.cc b/samples/helpers/win32/com_factory.cc
new file mode 100644
index 000000000..7c5fe44fc
--- /dev/null
+++ b/samples/helpers/win32/com_factory.cc
@@ -0,0 +1,51 @@
+// Copyright 2023 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "samples/helpers/win32/com_factory.h"
+
+#include <combaseapi.h>
+#include <objbase.h>
+#include <winerror.h>
+#include <xpsobjectmodel.h>
+
+#include "third_party/base/check_op.h"
+
+ComFactory::ComFactory() = default;
+
+ComFactory::~ComFactory() {
+ if (xps_om_object_factory_) {
+ xps_om_object_factory_->Release();
+ }
+
+ if (initialized_) {
+ CoUninitialize();
+ }
+}
+
+bool ComFactory::Initialize() {
+ if (!initialized_) {
+ HRESULT result =
+ CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
+ DCHECK_NE(RPC_E_CHANGED_MODE, result);
+ initialized_ = SUCCEEDED(result);
+ }
+
+ return initialized_;
+}
+
+IXpsOMObjectFactory* ComFactory::GetXpsOMObjectFactory() {
+ if (!xps_om_object_factory_ && Initialize()) {
+ HRESULT result =
+ CoCreateInstance(__uuidof(XpsOMObjectFactory), /*pUnkOuter=*/nullptr,
+ CLSCTX_INPROC_SERVER, __uuidof(IXpsOMObjectFactory),
+ reinterpret_cast<LPVOID*>(&xps_om_object_factory_));
+ if (SUCCEEDED(result)) {
+ DCHECK(xps_om_object_factory_);
+ } else {
+ DCHECK(!xps_om_object_factory_);
+ }
+ }
+
+ return xps_om_object_factory_;
+}
diff --git a/samples/helpers/win32/com_factory.h b/samples/helpers/win32/com_factory.h
new file mode 100644
index 000000000..eabaffec4
--- /dev/null
+++ b/samples/helpers/win32/com_factory.h
@@ -0,0 +1,25 @@
+// Copyright 2023 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SAMPLES_HELPERS_WIN32_COM_FACTORY_H_
+#define SAMPLES_HELPERS_WIN32_COM_FACTORY_H_
+
+struct IXpsOMObjectFactory;
+
+// Factory for COM instances.
+class ComFactory final {
+ public:
+ ComFactory();
+ ~ComFactory();
+
+ IXpsOMObjectFactory* GetXpsOMObjectFactory();
+
+ private:
+ bool Initialize();
+
+ bool initialized_ = false;
+ IXpsOMObjectFactory* xps_om_object_factory_ = nullptr;
+};
+
+#endif // SAMPLES_HELPERS_WIN32_COM_FACTORY_H_
diff --git a/samples/pdfium_test_write_helper.cc b/samples/helpers/write.cc
index 7ac49d702..13223d276 100644
--- a/samples/pdfium_test_write_helper.cc
+++ b/samples/helpers/write.cc
@@ -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 "samples/pdfium_test_write_helper.h"
+#include "samples/helpers/write.h"
#include <limits.h>
@@ -28,114 +28,156 @@
namespace {
bool CheckDimensions(int stride, int width, int height) {
- if (stride < 0 || width < 0 || height < 0)
+ if (stride < 0 || width < 0 || height < 0) {
return false;
- if (height > 0 && stride > INT_MAX / height)
+ }
+ if (height > 0 && stride > INT_MAX / height) {
return false;
+ }
return true;
}
const char* AnnotSubtypeToCString(FPDF_ANNOTATION_SUBTYPE subtype) {
- if (subtype == FPDF_ANNOT_TEXT)
+ if (subtype == FPDF_ANNOT_TEXT) {
return "Text";
- if (subtype == FPDF_ANNOT_LINK)
+ }
+ if (subtype == FPDF_ANNOT_LINK) {
return "Link";
- if (subtype == FPDF_ANNOT_FREETEXT)
+ }
+ if (subtype == FPDF_ANNOT_FREETEXT) {
return "FreeText";
- if (subtype == FPDF_ANNOT_LINE)
+ }
+ if (subtype == FPDF_ANNOT_LINE) {
return "Line";
- if (subtype == FPDF_ANNOT_SQUARE)
+ }
+ if (subtype == FPDF_ANNOT_SQUARE) {
return "Square";
- if (subtype == FPDF_ANNOT_CIRCLE)
+ }
+ if (subtype == FPDF_ANNOT_CIRCLE) {
return "Circle";
- if (subtype == FPDF_ANNOT_POLYGON)
+ }
+ if (subtype == FPDF_ANNOT_POLYGON) {
return "Polygon";
- if (subtype == FPDF_ANNOT_POLYLINE)
+ }
+ if (subtype == FPDF_ANNOT_POLYLINE) {
return "PolyLine";
- if (subtype == FPDF_ANNOT_HIGHLIGHT)
+ }
+ if (subtype == FPDF_ANNOT_HIGHLIGHT) {
return "Highlight";
- if (subtype == FPDF_ANNOT_UNDERLINE)
+ }
+ if (subtype == FPDF_ANNOT_UNDERLINE) {
return "Underline";
- if (subtype == FPDF_ANNOT_SQUIGGLY)
+ }
+ if (subtype == FPDF_ANNOT_SQUIGGLY) {
return "Squiggly";
- if (subtype == FPDF_ANNOT_STRIKEOUT)
+ }
+ if (subtype == FPDF_ANNOT_STRIKEOUT) {
return "StrikeOut";
- if (subtype == FPDF_ANNOT_STAMP)
+ }
+ if (subtype == FPDF_ANNOT_STAMP) {
return "Stamp";
- if (subtype == FPDF_ANNOT_CARET)
+ }
+ if (subtype == FPDF_ANNOT_CARET) {
return "Caret";
- if (subtype == FPDF_ANNOT_INK)
+ }
+ if (subtype == FPDF_ANNOT_INK) {
return "Ink";
- if (subtype == FPDF_ANNOT_POPUP)
+ }
+ if (subtype == FPDF_ANNOT_POPUP) {
return "Popup";
- if (subtype == FPDF_ANNOT_FILEATTACHMENT)
+ }
+ if (subtype == FPDF_ANNOT_FILEATTACHMENT) {
return "FileAttachment";
- if (subtype == FPDF_ANNOT_SOUND)
+ }
+ if (subtype == FPDF_ANNOT_SOUND) {
return "Sound";
- if (subtype == FPDF_ANNOT_MOVIE)
+ }
+ if (subtype == FPDF_ANNOT_MOVIE) {
return "Movie";
- if (subtype == FPDF_ANNOT_WIDGET)
+ }
+ if (subtype == FPDF_ANNOT_WIDGET) {
return "Widget";
- if (subtype == FPDF_ANNOT_SCREEN)
+ }
+ if (subtype == FPDF_ANNOT_SCREEN) {
return "Screen";
- if (subtype == FPDF_ANNOT_PRINTERMARK)
+ }
+ if (subtype == FPDF_ANNOT_PRINTERMARK) {
return "PrinterMark";
- if (subtype == FPDF_ANNOT_TRAPNET)
+ }
+ if (subtype == FPDF_ANNOT_TRAPNET) {
return "TrapNet";
- if (subtype == FPDF_ANNOT_WATERMARK)
+ }
+ if (subtype == FPDF_ANNOT_WATERMARK) {
return "Watermark";
- if (subtype == FPDF_ANNOT_THREED)
+ }
+ if (subtype == FPDF_ANNOT_THREED) {
return "3D";
- if (subtype == FPDF_ANNOT_RICHMEDIA)
+ }
+ if (subtype == FPDF_ANNOT_RICHMEDIA) {
return "RichMedia";
- if (subtype == FPDF_ANNOT_XFAWIDGET)
+ }
+ if (subtype == FPDF_ANNOT_XFAWIDGET) {
return "XFAWidget";
- NOTREACHED();
- return "";
+ }
+ NOTREACHED_NORETURN();
}
void AppendFlagString(const char* flag, std::string* output) {
- if (!output->empty())
+ if (!output->empty()) {
*output += ", ";
+ }
*output += flag;
}
std::string AnnotFlagsToString(int flags) {
std::string str;
- if (flags & FPDF_ANNOT_FLAG_INVISIBLE)
+ if (flags & FPDF_ANNOT_FLAG_INVISIBLE) {
AppendFlagString("Invisible", &str);
- if (flags & FPDF_ANNOT_FLAG_HIDDEN)
+ }
+ if (flags & FPDF_ANNOT_FLAG_HIDDEN) {
AppendFlagString("Hidden", &str);
- if (flags & FPDF_ANNOT_FLAG_PRINT)
+ }
+ if (flags & FPDF_ANNOT_FLAG_PRINT) {
AppendFlagString("Print", &str);
- if (flags & FPDF_ANNOT_FLAG_NOZOOM)
+ }
+ if (flags & FPDF_ANNOT_FLAG_NOZOOM) {
AppendFlagString("NoZoom", &str);
- if (flags & FPDF_ANNOT_FLAG_NOROTATE)
+ }
+ if (flags & FPDF_ANNOT_FLAG_NOROTATE) {
AppendFlagString("NoRotate", &str);
- if (flags & FPDF_ANNOT_FLAG_NOVIEW)
+ }
+ if (flags & FPDF_ANNOT_FLAG_NOVIEW) {
AppendFlagString("NoView", &str);
- if (flags & FPDF_ANNOT_FLAG_READONLY)
+ }
+ if (flags & FPDF_ANNOT_FLAG_READONLY) {
AppendFlagString("ReadOnly", &str);
- if (flags & FPDF_ANNOT_FLAG_LOCKED)
+ }
+ if (flags & FPDF_ANNOT_FLAG_LOCKED) {
AppendFlagString("Locked", &str);
- if (flags & FPDF_ANNOT_FLAG_TOGGLENOVIEW)
+ }
+ if (flags & FPDF_ANNOT_FLAG_TOGGLENOVIEW) {
AppendFlagString("ToggleNoView", &str);
+ }
return str;
}
const char* PageObjectTypeToCString(int type) {
- if (type == FPDF_PAGEOBJ_TEXT)
+ if (type == FPDF_PAGEOBJ_TEXT) {
return "Text";
- if (type == FPDF_PAGEOBJ_PATH)
+ }
+ if (type == FPDF_PAGEOBJ_PATH) {
return "Path";
- if (type == FPDF_PAGEOBJ_IMAGE)
+ }
+ if (type == FPDF_PAGEOBJ_IMAGE) {
return "Image";
- if (type == FPDF_PAGEOBJ_SHADING)
+ }
+ if (type == FPDF_PAGEOBJ_SHADING) {
return "Shading";
- if (type == FPDF_PAGEOBJ_FORM)
+ }
+ if (type == FPDF_PAGEOBJ_FORM) {
return "Form";
- NOTREACHED();
- return "";
+ }
+ NOTREACHED_NORETURN();
}
std::vector<uint8_t> EncodePng(pdfium::span<const uint8_t> input,
@@ -162,7 +204,7 @@ std::vector<uint8_t> EncodePng(pdfium::span<const uint8_t> input,
/*discard_transparency=*/false);
break;
default:
- NOTREACHED();
+ NOTREACHED_NORETURN();
}
return png;
}
@@ -521,8 +563,9 @@ void WritePS(FPDF_PAGE page, const char* pdf_name, int num) {
return;
}
FILE* fp = fopen(filename.c_str(), "wb");
- if (!fp)
+ if (!fp) {
return;
+ }
HDC dc = CreateEnhMetaFileA(nullptr, nullptr, nullptr, nullptr);
@@ -534,8 +577,9 @@ void WritePS(FPDF_PAGE page, const char* pdf_name, int num) {
std::vector<const ENHMETARECORD*> items;
EnumEnhMetaFile(nullptr, emf, &EnhMetaFileProc, &items, nullptr);
for (const ENHMETARECORD* record : items) {
- if (record->iType != EMR_GDICOMMENT)
+ if (record->iType != EMR_GDICOMMENT) {
continue;
+ }
const auto* comment = reinterpret_cast<const EMRGDICOMMENT*>(record);
const char* data = reinterpret_cast<const char*>(comment->Data);
@@ -551,16 +595,43 @@ void WritePS(FPDF_PAGE page, const char* pdf_name, int num) {
#endif // _WIN32
#ifdef PDF_ENABLE_SKIA
-std::string WriteSkp(const char* pdf_name, int num, const SkPicture& picture) {
- std::string filename = GeneratePageOutputFilename(pdf_name, num, "skp");
+std::unique_ptr<SkWStream> WriteToSkWStream(const std::string& pdf_name,
+ int num,
+ const std::string& extension) {
+ std::string discarded_filename;
+ return WriteToSkWStream(pdf_name, num, extension, discarded_filename);
+}
+
+std::unique_ptr<SkWStream> WriteToSkWStream(const std::string& pdf_name,
+ int num,
+ const std::string& extension,
+ std::string& filename) {
+ filename =
+ GeneratePageOutputFilename(pdf_name.c_str(), num, extension.c_str());
if (filename.empty()) {
- return filename;
+ return nullptr;
+ }
+
+ auto stream = std::make_unique<SkFILEWStream>(filename.c_str());
+ if (!stream->isValid()) {
+ return nullptr;
+ }
+
+ return stream;
+}
+
+std::string WriteSkp(const char* pdf_name, int num, const SkPicture& picture) {
+ std::string filename;
+ std::unique_ptr<SkWStream> stream =
+ WriteToSkWStream(pdf_name, num, "skp", filename);
+ if (!stream) {
+ return "";
}
- SkFILEWStream wStream(filename.c_str());
- picture.serialize(&wStream);
+
+ picture.serialize(stream.get());
return filename;
}
-#endif
+#endif // PDF_ENABLE_SKIA
enum class ThumbnailDecodeType { kBitmap, kRawStream, kDecodedStream };
@@ -604,24 +675,27 @@ void WriteBufferToFile(const void* buf,
}
size_t bytes_written = fwrite(buf, 1, buflen, fp);
- if (bytes_written == buflen)
+ if (bytes_written == buflen) {
fprintf(stderr, "Successfully wrote %s %s.\n", filetype, filename);
- else
+ } else {
fprintf(stderr, "Failed to write to %s.\n", filename);
+ }
fclose(fp);
}
std::vector<uint8_t> EncodeBitmapToPng(ScopedFPDFBitmap bitmap) {
std::vector<uint8_t> png_encoding;
int format = FPDFBitmap_GetFormat(bitmap.get());
- if (format == FPDFBitmap_Unknown)
+ if (format == FPDFBitmap_Unknown) {
return png_encoding;
+ }
int width = FPDFBitmap_GetWidth(bitmap.get());
int height = FPDFBitmap_GetHeight(bitmap.get());
int stride = FPDFBitmap_GetStride(bitmap.get());
- if (!CheckDimensions(stride, width, height))
+ if (!CheckDimensions(stride, width, height)) {
return png_encoding;
+ }
auto input = pdfium::make_span(
static_cast<const uint8_t*>(FPDFBitmap_GetBuffer(bitmap.get())),
@@ -642,8 +716,9 @@ void WriteAttachments(FPDF_DOCUMENT doc, const std::string& name) {
std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
unsigned long actual_length_bytes =
FPDFAttachment_GetName(attachment, buf.data(), length_bytes);
- if (actual_length_bytes == length_bytes)
+ if (actual_length_bytes == length_bytes) {
attachment_name = GetPlatformString(buf.data());
+ }
}
if (attachment_name.empty()) {
fprintf(stderr, "Attachment #%d has an empty file name.\n", i + 1);
diff --git a/samples/pdfium_test_write_helper.h b/samples/helpers/write.h
index ffeba1f55..b23760e4c 100644
--- a/samples/pdfium_test_write_helper.h
+++ b/samples/helpers/write.h
@@ -2,16 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef SAMPLES_PDFIUM_TEST_WRITE_HELPER_H_
-#define SAMPLES_PDFIUM_TEST_WRITE_HELPER_H_
+#ifndef SAMPLES_HELPERS_WRITE_H_
+#define SAMPLES_HELPERS_WRITE_H_
+#include <memory>
#include <string>
#include "public/fpdfview.h"
#ifdef PDF_ENABLE_SKIA
class SkPicture;
-#endif
+class SkWStream;
+#endif // PDF_ENABLE_SKIA
std::string WritePpm(const char* pdf_name,
int num,
@@ -40,6 +42,13 @@ void WritePS(FPDF_PAGE page, const char* pdf_name, int num);
#endif // _WIN32
#ifdef PDF_ENABLE_SKIA
+std::unique_ptr<SkWStream> WriteToSkWStream(const std::string& pdf_name,
+ int num,
+ const std::string& extension);
+std::unique_ptr<SkWStream> WriteToSkWStream(const std::string& pdf_name,
+ int num,
+ const std::string& extension,
+ std::string& filename);
std::string WriteSkp(const char* pdf_name, int num, const SkPicture& picture);
#endif // PDF_ENABLE_SKIA
@@ -57,4 +66,4 @@ void WriteRawThumbnailStream(FPDF_PAGE page,
int page_num);
void WriteThumbnail(FPDF_PAGE page, const char* pdf_name, int page_num);
-#endif // SAMPLES_PDFIUM_TEST_WRITE_HELPER_H_
+#endif // SAMPLES_HELPERS_WRITE_H_
diff --git a/samples/pdfium_test.cc b/samples/pdfium_test.cc
index 2693a5627..282c539b2 100644
--- a/samples/pdfium_test.cc
+++ b/samples/pdfium_test.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include <locale.h>
+#include <stddef.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -30,9 +32,10 @@
#include "public/fpdf_structtree.h"
#include "public/fpdf_text.h"
#include "public/fpdfview.h"
-#include "samples/pdfium_test_dump_helper.h"
-#include "samples/pdfium_test_event_helper.h"
-#include "samples/pdfium_test_write_helper.h"
+#include "samples/helpers/dump.h"
+#include "samples/helpers/event.h"
+#include "samples/helpers/page_renderer.h"
+#include "samples/helpers/write.h"
#include "testing/command_line_helpers.h"
#include "testing/font_renamer.h"
#include "testing/fx_string_testhelpers.h"
@@ -41,11 +44,16 @@
#include "testing/utils/hash.h"
#include "testing/utils/path_service.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/base/check_op.h"
#ifdef _WIN32
#include <crtdbg.h>
#include <errhandlingapi.h>
#include <io.h>
+#include <wingdi.h>
+
+#include "samples/helpers/win32/com_factory.h"
+#include "third_party/base/win/scoped_select_object.h"
#else
#include <unistd.h>
#endif // _WIN32
@@ -54,15 +62,25 @@
#include <valgrind/callgrind.h>
#endif // ENABLE_CALLGRIND
+#if defined(PDF_USE_PARTITION_ALLOC)
+#include "testing/allocator_shim_config.h"
+#endif
+
#ifdef PDF_ENABLE_SKIA
#include "third_party/skia/include/core/SkCanvas.h" // nogncheck
#include "third_party/skia/include/core/SkColor.h" // nogncheck
+#include "third_party/skia/include/core/SkDocument.h" // nogncheck
#include "third_party/skia/include/core/SkPicture.h" // nogncheck
#include "third_party/skia/include/core/SkPictureRecorder.h" // nogncheck
#include "third_party/skia/include/core/SkPixmap.h" // nogncheck
#include "third_party/skia/include/core/SkRefCnt.h" // nogncheck
+#include "third_party/skia/include/core/SkStream.h" // nogncheck
#include "third_party/skia/include/core/SkSurface.h" // nogncheck
+#ifdef _WIN32
+#include "third_party/skia/include/docs/SkXPSDocument.h" // nogncheck
+#endif
+
#ifdef BUILD_WITH_CHROMIUM
#include "samples/chromium_support/discardable_memory_allocator.h" // nogncheck
#endif
@@ -95,6 +113,17 @@
namespace {
+enum class RendererType {
+ kDefault,
+ kAgg,
+#ifdef _WIN32
+ kGdi,
+#endif // _WIN32
+#if defined(PDF_ENABLE_SKIA)
+ kSkia,
+#endif // defined(PDF_ENABLE_SKIA)
+};
+
enum class OutputFormat {
kNone,
kPageInfo,
@@ -112,7 +141,10 @@ enum class OutputFormat {
#endif
#ifdef PDF_ENABLE_SKIA
kSkp,
-#endif
+#ifdef _WIN32
+ kXps,
+#endif // _WIN32
+#endif // PDF_ENABLE_SKIA
};
struct Options {
@@ -141,7 +173,7 @@ struct Options {
bool save_thumbnails = false;
bool save_thumbnails_decoded = false;
bool save_thumbnails_raw = false;
- absl::optional<FPDF_RENDERER_TYPE> use_renderer_type;
+ RendererType use_renderer_type = RendererType::kDefault;
#ifdef PDF_ENABLE_V8
bool disable_javascript = false;
std::string js_flags; // Extra flags to pass to v8 init.
@@ -486,23 +518,25 @@ bool ParseCommandLine(const std::vector<std::string>& args,
options->save_thumbnails_decoded = true;
} else if (cur_arg == "--save-thumbs-raw") {
options->save_thumbnails_raw = true;
-#if defined(_SKIA_SUPPORT_)
} else if (ParseSwitchKeyValue(cur_arg, "--use-renderer=", &value)) {
- if (options->use_renderer_type.has_value()) {
+ if (options->use_renderer_type != RendererType::kDefault) {
fprintf(stderr, "Duplicate --use-renderer argument\n");
return false;
}
if (value == "agg") {
- options->use_renderer_type = FPDF_RENDERERTYPE_AGG;
+ options->use_renderer_type = RendererType::kAgg;
+#ifdef _WIN32
+ } else if (value == "gdi") {
+ options->use_renderer_type = RendererType::kGdi;
+#endif // _WIN32
+#if defined(PDF_ENABLE_SKIA)
} else if (value == "skia") {
- options->use_renderer_type = FPDF_RENDERERTYPE_SKIA;
+ options->use_renderer_type = RendererType::kSkia;
+#endif // defined(PDF_ENABLE_SKIA)
} else {
- fprintf(stderr,
- "Invalid --use-renderer argument, value must be one of agg or "
- "skia\n");
+ fprintf(stderr, "Invalid --use-renderer argument\n");
return false;
}
-#endif // defined(_SKIA_SUPPORT_)
#ifdef PDF_ENABLE_V8
} else if (cur_arg == "--disable-javascript") {
options->disable_javascript = true;
@@ -558,6 +592,14 @@ bool ParseCommandLine(const std::vector<std::string>& args,
return false;
}
options->output_format = OutputFormat::kSkp;
+#ifdef _WIN32
+ } else if (cur_arg == "--xps") {
+ if (options->output_format != OutputFormat::kNone) {
+ fprintf(stderr, "Duplicate or conflicting --xps argument\n");
+ return false;
+ }
+ options->output_format = OutputFormat::kXps;
+#endif // _WIN32
#endif // PDF_ENABLE_SKIA
} else if (ParseSwitchKeyValue(cur_arg, "--font-dir=", &value)) {
if (!options->font_directory.empty()) {
@@ -764,71 +806,165 @@ FPDF_BOOL NeedToPauseNow(IFSDK_PAUSE* p) {
return true;
}
-// Renderer for a single page.
-class PageRenderer {
+class Processor final {
public:
- virtual ~PageRenderer() = default;
+ Processor(const Options* options, const std::function<void()>* idler)
+ : options_(options), idler_(idler) {
+ DCHECK(options_);
+ DCHECK(idler_);
+ }
- // Returns `true` if the rendered output exists. Must call `Finish()` first.
- virtual bool HasOutput() const = 0;
+ const Options& options() const { return *options_; }
+ const std::function<void()>& idler() const { return *idler_; }
- // Starts rendering the page, returning `false` on failure.
- virtual bool Start() = 0;
+#ifdef _WIN32
+ ComFactory& com_factory() { return com_factory_; }
+#endif // _WIN32
- // Continues rendering the page, returning `false` when complete.
- virtual bool Continue() { return false; }
+ // Invokes `idler()`.
+ void Idle() const { idler()(); }
- // Finishes rendering the page.
- virtual void Finish(FPDF_FORMHANDLE form) = 0;
+ void ProcessPdf(const std::string& name,
+ const char* buf,
+ size_t len,
+ const std::string& events);
- // Writes rendered output to a file, returning `false` on failure.
- virtual bool Write(const std::string& name, int page_index, bool md5) = 0;
+ private:
+ const Options* options_;
+ const std::function<void()>* idler_;
- protected:
- PageRenderer(FPDF_PAGE page, int width, int height, int flags)
- : page_(page), width_(width), height_(height), flags_(flags) {}
+#ifdef _WIN32
+ ComFactory com_factory_;
+#endif // _WIN32
+};
+
+class PdfProcessor final {
+ public:
+ PdfProcessor(Processor* processor,
+ const std::string* name,
+ const std::string* events,
+ FPDF_DOCUMENT doc,
+ FPDF_FORMHANDLE form,
+ FPDF_FORMFILLINFO_PDFiumTest* form_fill_info)
+ : processor_(processor),
+ name_(name),
+ events_(events),
+ doc_(doc),
+ form_(form),
+ form_fill_info_(form_fill_info) {
+ DCHECK(processor_);
+ DCHECK(name_);
+ DCHECK(events_);
+ DCHECK(doc_);
+ DCHECK(form_);
+ DCHECK(form_fill_info_);
+ }
- FPDF_PAGE page() { return page_; }
- int width() const { return width_; }
- int height() const { return height_; }
- int flags() const { return flags_; }
+ bool ProcessPage(int page_index);
private:
- FPDF_PAGE page_;
- int width_;
- int height_;
- int flags_;
+ // Per processor state.
+ const Options& options() const { return processor_->options(); }
+ const std::function<void()>& idler() const { return processor_->idler(); }
+
+#ifdef _WIN32
+ ComFactory& com_factory() { return processor_->com_factory(); }
+#endif // _WIN32
+
+ // Per PDF state.
+ const std::string& name() const { return *name_; }
+ const std::string& events() const { return *events_; }
+ FPDF_DOCUMENT doc() const { return doc_; }
+ FPDF_FORMHANDLE form() const { return form_; }
+
+ // Invokes `idler()`.
+ void Idle() const { idler()(); }
+
+ FPDF_PAGE GetPage(int page_index) const {
+ return GetPageForIndex(form_fill_info_, doc_, page_index);
+ }
+
+ Processor* processor_;
+ const std::string* name_;
+ const std::string* events_;
+ FPDF_DOCUMENT doc_;
+ FPDF_FORMHANDLE form_;
+ FPDF_FORMFILLINFO_PDFiumTest* form_fill_info_;
};
// Page renderer with bitmap output.
class BitmapPageRenderer : public PageRenderer {
public:
- // Function type that writes a bitmap to an image file. The function returns
- // the name of the image file on success, or an empty name on failure.
+ // Function type that writes rendered output to a file, returning `false` on
+ // failure.
//
- // Intended for use with some of the `pdfium_test_write_helper.h` functions.
- using BitmapWriter = std::string (*)(const char* pdf_name,
- int num,
- void* buffer,
- int stride,
- int width,
- int height);
+ // Intended to wrap functions from `pdfium_test_write_helper.h`.
+ using PageWriter = std::function<bool(BitmapPageRenderer& renderer,
+ const std::string& name,
+ int page_index,
+ bool md5)>;
+
+ // Wraps a `PageWriter` around a function pointer that writes the text page.
+ static PageWriter WrapPageWriter(
+ void (*text_page_writer)(FPDF_TEXTPAGE text_page,
+ const char* pdf_name,
+ int num)) {
+ return [text_page_writer](BitmapPageRenderer& renderer,
+ const std::string& name, int page_index,
+ bool /*md5*/) {
+ ScopedFPDFTextPage text_page(FPDFText_LoadPage(renderer.page()));
+ if (!text_page) {
+ return false;
+ }
- bool HasOutput() const override { return !!bitmap_; }
+ text_page_writer(text_page.get(), name.c_str(), page_index);
+ return true;
+ };
+ }
- bool Start() override {
- bool alpha = FPDFPage_HasTransparency(page());
- bitmap_.reset(FPDFBitmap_Create(/*width=*/width(), /*height=*/height(),
- /*alpha=*/alpha));
- if (!bitmap_)
- return false;
+ // Wraps a `PageWriter` around a function pointer that writes the page.
+ static PageWriter WrapPageWriter(void (*page_writer)(FPDF_PAGE page,
+ const char* pdf_name,
+ int num)) {
+ return [page_writer](BitmapPageRenderer& renderer, const std::string& name,
+ int page_index, bool /*md5*/) {
+ page_writer(renderer.page(), name.c_str(), page_index);
+ return true;
+ };
+ }
- FPDF_DWORD fill_color = alpha ? 0x00000000 : 0xFFFFFFFF;
- FPDFBitmap_FillRect(bitmap(), /*left=*/0, /*top=*/0, /*width=*/width(),
- /*height=*/height(), /*color=*/fill_color);
- return true;
+ // Wraps a `PageWriter` around a function pointer that writes the rasterized
+ // bitmap to an image file.
+ static PageWriter WrapPageWriter(
+ std::string (*bitmap_writer)(const char* pdf_name,
+ int num,
+ void* buffer,
+ int stride,
+ int width,
+ int height)) {
+ return [bitmap_writer](BitmapPageRenderer& renderer,
+ const std::string& name, int page_index, bool md5) {
+ int stride = FPDFBitmap_GetStride(renderer.bitmap());
+ void* buffer = FPDFBitmap_GetBuffer(renderer.bitmap());
+ std::string image_file_name = bitmap_writer(
+ name.c_str(), page_index, buffer, /*stride=*/stride,
+ /*width=*/renderer.width(), /*height=*/renderer.height());
+ if (image_file_name.empty()) {
+ return false;
+ }
+
+ if (md5) {
+ // Write the filename and the MD5 of the buffer to stdout.
+ OutputMD5Hash(image_file_name.c_str(),
+ {static_cast<const uint8_t*>(buffer),
+ static_cast<size_t>(stride) * renderer.height()});
+ }
+ return true;
+ };
}
+ bool HasOutput() const override { return !!bitmap_; }
+
void Finish(FPDF_FORMHANDLE form) override {
FPDF_FFLDraw(form, bitmap(), page(), /*start_x=*/0, /*start_y=*/0,
/*size_x=*/width(), /*size_y=*/height(), /*rotate=*/0,
@@ -837,24 +973,7 @@ class BitmapPageRenderer : public PageRenderer {
}
bool Write(const std::string& name, int page_index, bool md5) override {
- if (!writer_)
- return false;
-
- int stride = FPDFBitmap_GetStride(bitmap());
- void* buffer = FPDFBitmap_GetBuffer(bitmap());
- std::string image_file_name =
- writer_(name.c_str(), /*num=*/page_index, buffer, /*stride=*/stride,
- /*width=*/width(), /*height=*/height());
- if (image_file_name.empty())
- return false;
-
- if (md5) {
- // Write the filename and the MD5 of the buffer to stdout.
- OutputMD5Hash(image_file_name.c_str(),
- {static_cast<const uint8_t*>(buffer),
- static_cast<size_t>(stride) * height()});
- }
- return true;
+ return writer_ && writer_(*this, name, page_index, md5);
}
protected:
@@ -863,17 +982,35 @@ class BitmapPageRenderer : public PageRenderer {
int height,
int flags,
const std::function<void()>& idler,
- BitmapWriter writer)
+ PageWriter writer)
: PageRenderer(page, /*width=*/width, /*height=*/height, /*flags=*/flags),
idler_(idler),
- writer_(writer) {}
+ writer_(std::move(writer)) {}
+
+ bool InitializeBitmap(void* first_scan) {
+ bool alpha = FPDFPage_HasTransparency(page());
+ bitmap_.reset(FPDFBitmap_CreateEx(
+ /*width=*/width(), /*height=*/height(),
+ /*format=*/alpha ? FPDFBitmap_BGRA : FPDFBitmap_BGRx, first_scan,
+ /*stride=*/width() * sizeof(uint32_t)));
+ if (!bitmap()) {
+ return false;
+ }
+
+ FPDF_DWORD fill_color = alpha ? 0x00000000 : 0xFFFFFFFF;
+ FPDFBitmap_FillRect(bitmap(), /*left=*/0, /*top=*/0, /*width=*/width(),
+ /*height=*/height(), /*color=*/fill_color);
+ return true;
+ }
+
+ void ResetBitmap() { bitmap_.reset(); }
void Idle() const { idler_(); }
FPDF_BITMAP bitmap() { return bitmap_.get(); }
private:
const std::function<void()>& idler_;
- BitmapWriter writer_;
+ PageWriter writer_;
ScopedFPDFBitmap bitmap_;
};
@@ -885,17 +1022,18 @@ class OneShotBitmapPageRenderer : public BitmapPageRenderer {
int height,
int flags,
const std::function<void()>& idler,
- BitmapWriter writer)
+ PageWriter writer)
: BitmapPageRenderer(page,
/*width=*/width,
/*height=*/height,
/*flags=*/flags,
idler,
- writer) {}
+ std::move(writer)) {}
bool Start() override {
- if (!BitmapPageRenderer::Start())
+ if (!InitializeBitmap(/*first_scan=*/nullptr)) {
return false;
+ }
// Note, client programs probably want to use this method instead of the
// progressive calls. The progressive calls are if you need to pause the
@@ -915,22 +1053,23 @@ class ProgressiveBitmapPageRenderer : public BitmapPageRenderer {
int height,
int flags,
const std::function<void()>& idler,
- BitmapWriter writer,
+ PageWriter writer,
const FPDF_COLORSCHEME* color_scheme)
: BitmapPageRenderer(page,
/*width=*/width,
/*height=*/height,
/*flags=*/flags,
idler,
- writer),
+ std::move(writer)),
color_scheme_(color_scheme) {
pause_.version = 1;
pause_.NeedToPauseNow = &NeedToPauseNow;
}
bool Start() override {
- if (!BitmapPageRenderer::Start())
+ if (!InitializeBitmap(/*first_scan=*/nullptr)) {
return false;
+ }
if (FPDF_RenderPageBitmapWithColorScheme_Start(
bitmap(), page(), /*start_x=*/0, /*start_y=*/0, /*size_x=*/width(),
@@ -961,28 +1100,159 @@ class ProgressiveBitmapPageRenderer : public BitmapPageRenderer {
bool to_be_continued_ = false;
};
+#ifdef _WIN32
+class ScopedGdiDc final {
+ public:
+ ~ScopedGdiDc() { Reset(nullptr); }
+
+ void Reset(HDC dc) {
+ if (dc_) {
+ [[maybe_unused]] BOOL success = DeleteDC(dc_);
+ DCHECK(success);
+ }
+ dc_ = dc;
+ }
+
+ HDC Get() const { return dc_; }
+
+ private:
+ HDC dc_ = nullptr;
+};
+
+class ScopedGdiObject final {
+ public:
+ ~ScopedGdiObject() { Reset(nullptr); }
+
+ void Reset(HGDIOBJ object) {
+ if (object_) {
+ [[maybe_unused]] BOOL success = DeleteObject(object_);
+ DCHECK(success);
+ }
+ object_ = object;
+ }
+
+ HGDIOBJ Get() const { return object_; }
+
+ private:
+ HGDIOBJ object_ = nullptr;
+};
+
+class GdiDisplayPageRenderer : public BitmapPageRenderer {
+ public:
+ GdiDisplayPageRenderer(FPDF_PAGE page,
+ int width,
+ int height,
+ int flags,
+ const std::function<void()>& idler,
+ PageWriter writer)
+ : BitmapPageRenderer(page,
+ /*width=*/width,
+ /*height=*/height,
+ /*flags=*/flags,
+ idler,
+ std::move(writer)) {}
+
+ ~GdiDisplayPageRenderer() override {
+ // Need to free `bitmap()` first, in case it points at `dib_` memory.
+ ResetBitmap();
+ }
+
+ bool Start() override {
+ // Create an in-memory DC compatible with the display.
+ dc_.Reset(CreateCompatibleDC(/*hdc=*/nullptr));
+ if (!dc_.Get()) {
+ return false;
+ }
+
+ // Create a BGRA DIB and select it into the in-memory DC.
+ BITMAPINFO dib_info;
+ memset(&dib_info, 0, sizeof(BITMAPINFO));
+ dib_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ dib_info.bmiHeader.biWidth = width();
+ dib_info.bmiHeader.biHeight = -height(); // top-down
+ dib_info.bmiHeader.biPlanes = 1;
+ dib_info.bmiHeader.biBitCount = 32;
+ dib_info.bmiHeader.biCompression = BI_RGB;
+
+ VOID* dib_pixels;
+ dib_.Reset(CreateDIBSection(dc_.Get(), &dib_info, DIB_RGB_COLORS,
+ &dib_pixels, /*hSection=*/nullptr,
+ /*offset=*/0));
+ if (!dib_.Get() || !InitializeBitmap(dib_pixels)) {
+ return false;
+ }
+ pdfium::base::win::ScopedSelectObject select_dib(dc_.Get(), dib_.Get());
+
+ // Render into the in-memory DC.
+ FPDF_RenderPage(dc_.Get(), page(), /*start_x=*/0, /*start_y=*/0,
+ /*size_x=*/width(), /*size_y=*/height(), /*rotate=*/0,
+ /*flags=*/flags());
+
+ return !!GdiFlush();
+ }
+
+ void Finish(FPDF_FORMHANDLE /*form*/) override {
+ // Note that `fpdf_formfill.h` does not support GDI.
+
+ // The GDI backend doesn't support alpha and clears the alpha component to
+ // transparent, so clear the alpha component back to opaque.
+ const int stride = FPDFBitmap_GetStride(bitmap());
+ DCHECK_EQ(width() * sizeof(uint32_t), static_cast<size_t>(stride));
+ const int pixel_stride = stride / sizeof(uint32_t);
+
+ uint32_t* scanline =
+ reinterpret_cast<uint32_t*>(FPDFBitmap_GetBuffer(bitmap()));
+ for (int row = 0; row < height(); ++row) {
+ for (int column = 0; column < width(); ++column) {
+ scanline[column] |= 0xFF000000;
+ }
+ scanline += pixel_stride;
+ }
+ }
+
+ private:
+ ScopedGdiDc dc_;
+ ScopedGdiObject dib_;
+};
+#endif // _WIN32
+
#ifdef PDF_ENABLE_SKIA
-class SkPicturePageRenderer : public PageRenderer {
+class SkCanvasPageRenderer : public PageRenderer {
+ public:
+ bool Start() override {
+ FPDF_RenderPageSkia(reinterpret_cast<FPDF_SKIA_CANVAS>(canvas()), page(),
+ width(), height());
+ return true;
+ }
+
+ void Finish(FPDF_FORMHANDLE form) override {
+ FPDF_FFLDrawSkia(form, reinterpret_cast<FPDF_SKIA_CANVAS>(canvas()), page(),
+ /*start_x=*/0, /*start_y=*/0, width(), height(),
+ /*rotate=*/0, flags());
+ }
+
+ protected:
+ SkCanvasPageRenderer(FPDF_PAGE page, int width, int height, int flags)
+ : PageRenderer(page, width, height, flags) {}
+
+ virtual SkCanvas* canvas() = 0;
+};
+
+class SkPicturePageRenderer final : public SkCanvasPageRenderer {
public:
SkPicturePageRenderer(FPDF_PAGE page, int width, int height, int flags)
- : PageRenderer(page,
- /*width=*/width,
- /*height=*/height,
- /*flags=*/flags) {}
+ : SkCanvasPageRenderer(page, width, height, flags) {}
bool HasOutput() const override { return !!picture_; }
bool Start() override {
- recorder_.reset(reinterpret_cast<SkPictureRecorder*>(
- FPDF_RenderPageSkp(page(), /*size_x=*/width(), /*size_y=*/height())));
- return !!recorder_;
+ recorder_ = std::make_unique<SkPictureRecorder>();
+ recorder_->beginRecording(width(), height());
+ return SkCanvasPageRenderer::Start();
}
void Finish(FPDF_FORMHANDLE form) override {
- FPDF_FFLRecord(form, reinterpret_cast<FPDF_RECORDER>(recorder_.get()),
- page(), /*start_x=*/0, /*start_y=*/0, /*size_x=*/width(),
- /*size_y=*/height(), /*rotate=*/0, /*flags=*/0);
-
+ SkCanvasPageRenderer::Finish(form);
picture_ = recorder_->finishRecordingAsPicture();
recorder_.reset();
}
@@ -994,8 +1264,8 @@ class SkPicturePageRenderer : public PageRenderer {
if (md5) {
// Play back the `SkPicture` so we can take a hash of the result.
- sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(
- /*width=*/width(), /*height=*/height());
+ sk_sp<SkSurface> surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(
+ /*width=*/width(), /*height=*/height()));
if (!surface)
return false;
@@ -1015,92 +1285,216 @@ class SkPicturePageRenderer : public PageRenderer {
return true;
}
+ protected:
+ SkCanvas* canvas() override { return recorder_->getRecordingCanvas(); }
+
private:
std::unique_ptr<SkPictureRecorder> recorder_;
sk_sp<SkPicture> picture_;
};
+
+class SkDocumentPageRenderer final : public SkCanvasPageRenderer {
+ public:
+ SkDocumentPageRenderer(std::unique_ptr<SkWStream> stream,
+ sk_sp<SkDocument> document,
+ FPDF_PAGE page,
+ int width,
+ int height,
+ int flags)
+ : SkCanvasPageRenderer(page, width, height, flags),
+ stream_(std::move(stream)),
+ document_(std::move(document)) {
+ DCHECK(stream_);
+ DCHECK(document_);
+ }
+
+ bool HasOutput() const override { return has_output_; }
+
+ bool Start() override {
+ if (!document_) {
+ return false;
+ }
+
+ DCHECK(!canvas_);
+ canvas_ = document_->beginPage(width(), height());
+ if (!canvas_) {
+ return false;
+ }
+
+ return SkCanvasPageRenderer::Start();
+ }
+
+ void Finish(FPDF_FORMHANDLE form) override {
+ SkCanvasPageRenderer::Finish(form);
+
+ DCHECK(canvas_);
+ canvas_ = nullptr;
+ document_->endPage();
+
+ has_output_ = true;
+ }
+
+ bool Write(const std::string& /*name*/,
+ int /*page_index*/,
+ bool /*md5*/) override {
+ bool success = HasOutput();
+ if (success) {
+ document_->close();
+ } else {
+ document_->abort();
+ }
+
+ document_.reset();
+ stream_.reset();
+ return success;
+ }
+
+ protected:
+ SkCanvas* canvas() override { return canvas_; }
+
+ private:
+ std::unique_ptr<SkWStream> stream_;
+ sk_sp<SkDocument> document_;
+
+ SkCanvas* canvas_ = nullptr;
+ bool has_output_ = false;
+};
#endif // PDF_ENABLE_SKIA
-bool ProcessPage(const std::string& name,
- FPDF_DOCUMENT doc,
- FPDF_FORMHANDLE form,
- FPDF_FORMFILLINFO_PDFiumTest* form_fill_info,
- const int page_index,
- const Options& options,
- const std::string& events,
- const std::function<void()>& idler) {
- FPDF_PAGE page = GetPageForIndex(form_fill_info, doc, page_index);
- if (!page)
+bool PdfProcessor::ProcessPage(const int page_index) {
+ FPDF_PAGE page = GetPage(page_index);
+ if (!page) {
return false;
- if (options.send_events)
- SendPageEvents(form, page, events, idler);
- if (options.save_images)
- WriteImages(page, name.c_str(), page_index);
- if (options.save_rendered_images)
- WriteRenderedImages(doc, page, name.c_str(), page_index);
- if (options.save_thumbnails)
- WriteThumbnail(page, name.c_str(), page_index);
- if (options.save_thumbnails_decoded)
- WriteDecodedThumbnailStream(page, name.c_str(), page_index);
- if (options.save_thumbnails_raw)
- WriteRawThumbnailStream(page, name.c_str(), page_index);
- if (options.output_format == OutputFormat::kPageInfo) {
+ }
+
+ if (options().send_events) {
+ SendPageEvents(form(), page, events(), idler());
+ }
+ if (options().save_images) {
+ WriteImages(page, name().c_str(), page_index);
+ }
+ if (options().save_rendered_images) {
+ WriteRenderedImages(doc(), page, name().c_str(), page_index);
+ }
+ if (options().save_thumbnails) {
+ WriteThumbnail(page, name().c_str(), page_index);
+ }
+ if (options().save_thumbnails_decoded) {
+ WriteDecodedThumbnailStream(page, name().c_str(), page_index);
+ }
+ if (options().save_thumbnails_raw) {
+ WriteRawThumbnailStream(page, name().c_str(), page_index);
+ }
+ if (options().output_format == OutputFormat::kPageInfo) {
DumpPageInfo(page, page_index);
return true;
}
- if (options.output_format == OutputFormat::kStructure) {
+ if (options().output_format == OutputFormat::kStructure) {
DumpPageStructure(page, page_index);
return true;
}
ScopedFPDFTextPage text_page(FPDFText_LoadPage(page));
double scale = 1.0;
- if (!options.scale_factor_as_string.empty())
- std::stringstream(options.scale_factor_as_string) >> scale;
+ if (!options().scale_factor_as_string.empty()) {
+ std::stringstream(options().scale_factor_as_string) >> scale;
+ }
int width = static_cast<int>(FPDF_GetPageWidthF(page) * scale);
int height = static_cast<int>(FPDF_GetPageHeightF(page) * scale);
- int flags = PageRenderFlagsFromOptions(options);
+ int flags = PageRenderFlagsFromOptions(options());
std::unique_ptr<PageRenderer> renderer;
-#ifdef PDF_ENABLE_SKIA
- if (options.output_format == OutputFormat::kSkp) {
- renderer = std::make_unique<SkPicturePageRenderer>(
- page, /*width=*/width, /*height=*/height, /*flags=*/flags);
- } else {
-#else
- {
-#endif // PDF_ENABLE_SKIA
- BitmapPageRenderer::BitmapWriter writer;
- switch (options.output_format) {
+ BitmapPageRenderer::PageWriter writer;
+ switch (options().output_format) {
+ case OutputFormat::kText:
+ writer = BitmapPageRenderer::WrapPageWriter(WriteText);
+ break;
+
+ case OutputFormat::kAnnot:
+ writer = BitmapPageRenderer::WrapPageWriter(WriteAnnot);
+ break;
+
+ case OutputFormat::kPpm:
+ writer = BitmapPageRenderer::WrapPageWriter(WritePpm);
+ break;
+
+ case OutputFormat::kPng:
+ writer = BitmapPageRenderer::WrapPageWriter(WritePng);
+ break;
+
#ifdef _WIN32
- case OutputFormat::kBmp:
- writer = WriteBmp;
- break;
+ case OutputFormat::kBmp:
+ writer = BitmapPageRenderer::WrapPageWriter(WriteBmp);
+ break;
+
+ case OutputFormat::kEmf:
+ // TODO(crbug.com/pdfium/2054): Render directly to DC.
+ writer = BitmapPageRenderer::WrapPageWriter(WriteEmf);
+ break;
+
+ case OutputFormat::kPs2:
+ case OutputFormat::kPs3:
+ // TODO(crbug.com/pdfium/2054): Render directly to DC.
+ writer = BitmapPageRenderer::WrapPageWriter(WritePS);
+ break;
#endif // _WIN32
- case OutputFormat::kPng:
- writer = WritePng;
+#ifdef PDF_ENABLE_SKIA
+ case OutputFormat::kSkp:
+ renderer = std::make_unique<SkPicturePageRenderer>(
+ page, /*width=*/width, /*height=*/height, /*flags=*/flags);
+ break;
+
+#ifdef _WIN32
+ case OutputFormat::kXps: {
+ IXpsOMObjectFactory* xps_factory = com_factory().GetXpsOMObjectFactory();
+ if (!xps_factory) {
break;
+ }
- case OutputFormat::kPpm:
- writer = WritePpm;
+ std::unique_ptr<SkWStream> stream =
+ WriteToSkWStream(name(), page_index, "xps");
+ if (!stream) {
break;
+ }
- default:
- // Other formats won't write the output to a file, but still rasterize.
- writer = nullptr;
+ sk_sp<SkDocument> document =
+ SkXPS::MakeDocument(stream.get(), xps_factory);
+ if (!document) {
break;
+ }
+
+ renderer = std::make_unique<SkDocumentPageRenderer>(
+ std::move(stream), std::move(document), page, width, height, flags);
+ break;
}
+#endif // _WIN32
+#endif // PDF_ENABLE_SKIA
+
+ default:
+ // Other formats won't write the output to a file, but still rasterize.
+ break;
+ }
+
+#ifdef _WIN32
+ if (!renderer && options().use_renderer_type == RendererType::kGdi) {
+ renderer = std::make_unique<GdiDisplayPageRenderer>(
+ page, /*width=*/width, /*height=*/height, /*flags=*/flags, idler(),
+ std::move(writer));
+ }
+#endif // _WIN32
- if (options.render_oneshot) {
+ if (!renderer) {
+ // Use a rasterizing page renderer by default.
+ if (options().render_oneshot) {
renderer = std::make_unique<OneShotBitmapPageRenderer>(
- page, /*width=*/width, /*height=*/height, /*flags=*/flags, idler,
- writer);
+ page, /*width=*/width, /*height=*/height, /*flags=*/flags, idler(),
+ std::move(writer));
} else {
// Client programs will be setting these values when rendering.
// This is a sample color scheme with distinct colors.
- // Used only when `options.forced_color` is true.
+ // Used only when `options().forced_color` is true.
FPDF_COLORSCHEME color_scheme;
color_scheme.path_fill_color = 0xFFFF0000;
color_scheme.path_stroke_color = 0xFF00FF00;
@@ -1108,59 +1502,33 @@ bool ProcessPage(const std::string& name,
color_scheme.text_stroke_color = 0xFF00FFFF;
renderer = std::make_unique<ProgressiveBitmapPageRenderer>(
- page, /*width=*/width, /*height=*/height, /*flags=*/flags, idler,
- writer, options.forced_color ? &color_scheme : nullptr);
+ page, /*width=*/width, /*height=*/height, /*flags=*/flags, idler(),
+ std::move(writer), options().forced_color ? &color_scheme : nullptr);
}
}
if (renderer->Start()) {
while (renderer->Continue())
continue;
- renderer->Finish(form);
-
- switch (options.output_format) {
-#ifdef _WIN32
- case OutputFormat::kEmf:
- WriteEmf(page, name.c_str(), page_index);
- break;
-
- case OutputFormat::kPs2:
- case OutputFormat::kPs3:
- WritePS(page, name.c_str(), page_index);
- break;
-#endif // _WIN32
-
- case OutputFormat::kText:
- WriteText(text_page.get(), name.c_str(), page_index);
- break;
-
- case OutputFormat::kAnnot:
- WriteAnnot(page, name.c_str(), page_index);
- break;
-
- default:
- renderer->Write(name, page_index, /*md5=*/options.md5);
- break;
- }
+ renderer->Finish(form());
+ renderer->Write(name(), page_index, /*md5=*/options().md5);
} else {
fprintf(stderr, "Page was too large to be rendered.\n");
}
- FORM_DoPageAAction(page, form, FPDFPAGE_AACTION_CLOSE);
- idler();
+ FORM_DoPageAAction(page, form(), FPDFPAGE_AACTION_CLOSE);
+ Idle();
- FORM_OnBeforeClosePage(page, form);
- idler();
+ FORM_OnBeforeClosePage(page, form());
+ Idle();
return renderer->HasOutput();
}
-void ProcessPdf(const std::string& name,
- const char* buf,
- size_t len,
- const Options& options,
- const std::string& events,
- const std::function<void()>& idler) {
+void Processor::ProcessPdf(const std::string& name,
+ const char* buf,
+ size_t len,
+ const std::string& events) {
TestLoader loader({buf, len});
FPDF_FILEACCESS file_access = {};
@@ -1183,9 +1551,9 @@ void ProcessPdf(const std::string& name,
ScopedFPDFDocument doc;
const char* password =
- options.password.empty() ? nullptr : options.password.c_str();
+ options().password.empty() ? nullptr : options().password.c_str();
bool is_linearized = false;
- if (options.use_load_mem_document) {
+ if (options().use_load_mem_document) {
doc.reset(FPDF_LoadMemDocument(buf, len, password));
} else {
if (FPDFAvail_IsLinearized(pdf_avail.get()) == PDF_LINEARIZED) {
@@ -1224,11 +1592,13 @@ void ProcessPdf(const std::string& name,
(void)FPDF_GetDocPermissions(doc.get());
- if (options.show_metadata)
+ if (options().show_metadata) {
DumpMetaData(doc.get());
+ }
- if (options.save_attachments)
+ if (options().save_attachments) {
WriteAttachments(doc.get(), name);
+ }
#ifdef PDF_ENABLE_V8
IPDF_JSPLATFORM platform_callbacks = {};
@@ -1248,7 +1618,7 @@ void ProcessPdf(const std::string& name,
#ifdef PDF_ENABLE_XFA
form_callbacks.version = 2;
form_callbacks.xfa_disabled =
- options.disable_xfa || options.disable_javascript;
+ options().disable_xfa || options().disable_javascript;
form_callbacks.FFI_PopupMenu = ExamplePopupMenu;
#else // PDF_ENABLE_XFA
form_callbacks.version = 1;
@@ -1257,8 +1627,9 @@ void ProcessPdf(const std::string& name,
form_callbacks.FFI_GetPage = GetPageForIndex;
#ifdef PDF_ENABLE_V8
- if (!options.disable_javascript)
+ if (!options().disable_javascript) {
form_callbacks.m_pJsPlatform = &platform_callbacks;
+ }
#endif // PDF_ENABLE_V8
ScopedFPDFFormHandle form(
@@ -1266,7 +1637,7 @@ void ProcessPdf(const std::string& name,
form_callbacks.form_handle = form.get();
#ifdef PDF_ENABLE_XFA
- if (!options.disable_xfa && !options.disable_javascript) {
+ if (!options().disable_xfa && !options().disable_javascript) {
int doc_type = FPDF_GetFormType(doc.get());
if (doc_type == FORMTYPE_XFA_FULL || doc_type == FORMTYPE_XFA_FOREGROUND) {
if (!FPDF_LoadXFA(doc.get()))
@@ -1281,19 +1652,22 @@ void ProcessPdf(const std::string& name,
FORM_DoDocumentOpenAction(form.get());
#if _WIN32
- if (options.output_format == OutputFormat::kPs2)
+ if (options().output_format == OutputFormat::kPs2) {
FPDF_SetPrintMode(FPDF_PRINTMODE_POSTSCRIPT2);
- else if (options.output_format == OutputFormat::kPs3)
+ } else if (options().output_format == OutputFormat::kPs3) {
FPDF_SetPrintMode(FPDF_PRINTMODE_POSTSCRIPT3);
- else if (options.output_format == OutputFormat::kPs3Type42)
+ } else if (options().output_format == OutputFormat::kPs3Type42) {
FPDF_SetPrintMode(FPDF_PRINTMODE_POSTSCRIPT3_TYPE42);
+ }
#endif
int page_count = FPDF_GetPageCount(doc.get());
int processed_pages = 0;
int bad_pages = 0;
- int first_page = options.pages ? options.first_page : 0;
- int last_page = options.pages ? options.last_page + 1 : page_count;
+ int first_page = options().pages ? options().first_page : 0;
+ int last_page = options().pages ? options().last_page + 1 : page_count;
+ PdfProcessor pdf_processor(this, &name, &events, doc.get(), form.get(),
+ &form_callbacks);
for (int i = first_page; i < last_page; ++i) {
if (is_linearized) {
int avail_status = PDF_DATA_NOTAVAIL;
@@ -1306,17 +1680,16 @@ void ProcessPdf(const std::string& name,
return;
}
}
- if (ProcessPage(name, doc.get(), form.get(), &form_callbacks, i, options,
- events, idler)) {
+ if (pdf_processor.ProcessPage(i)) {
++processed_pages;
} else {
++bad_pages;
}
- idler();
+ Idle();
}
FORM_DoDocumentAAction(form.get(), FPDFDOC_AACTION_WC);
- idler();
+ Idle();
fprintf(stderr, "Processed %d pages.\n", processed_pages);
if (bad_pages)
@@ -1346,6 +1719,9 @@ void ShowConfig() {
#ifdef PDF_ENABLE_SKIA
append_config("SKIA");
#endif
+#ifdef _WIN32
+ append_config("GDI");
+#endif
printf("%s\n", config.c_str());
}
@@ -1385,9 +1761,21 @@ constexpr char kUsageString[] =
"<pdf-name>.thumbnail.decoded.<page-number>.png\n"
" --save-thumbs-raw - write page thumbnails' raw stream data"
"<pdf-name>.thumbnail.raw.<page-number>.png\n"
-#if defined(_SKIA_SUPPORT_)
+
+#if defined(PDF_ENABLE_SKIA)
+#ifdef _WIN32
+ " --use-renderer - renderer to use, one of [agg | gdi | skia]\n"
+#else
" --use-renderer - renderer to use, one of [agg | skia]\n"
-#endif
+#endif // _WIN32
+#else
+#ifdef _WIN32
+ " --use-renderer - renderer to use, one of [agg | gdi]\n"
+#else
+ " --use-renderer - renderer to use, one of [agg]\n"
+#endif // _WIN32
+#endif // defined(PDF_ENABLE_SKIA)
+
#ifdef PDF_ENABLE_V8
" --disable-javascript - do not execute JS in PDF files\n"
" --js-flags=<flags> - additional flags to pass to V8\n"
@@ -1424,7 +1812,10 @@ constexpr char kUsageString[] =
" --annot - write annotation info <pdf-name>.<page-number>.annot.txt\n"
#ifdef PDF_ENABLE_SKIA
" --skp - write page images <pdf-name>.<page-number>.skp\n"
-#endif
+#ifdef _WIN32
+ " --xps - write page images <pdf-name>.<page-number>.xps\n"
+#endif // _WIN32
+#endif // PDF_ENABLE_SKIA
" --md5 - write output image paths and their md5 hashes to stdout.\n"
" --time=<number> - Seconds since the epoch to set system time.\n"
"";
@@ -1445,6 +1836,10 @@ void SetUpErrorHandling() {
} // namespace
int main(int argc, const char* argv[]) {
+#if defined(PDF_USE_PARTITION_ALLOC)
+ pdfium::ConfigurePartitionAllocShimPartitionForTest();
+#endif
+
SetUpErrorHandling();
setlocale(LC_CTYPE, "en_US.UTF-8"); // For printf() of high-characters.
@@ -1466,23 +1861,40 @@ int main(int argc, const char* argv[]) {
return 1;
}
- const FPDF_RENDERER_TYPE renderer_type =
- options.use_renderer_type.value_or(GetDefaultRendererType());
-#if defined(PDF_ENABLE_SKIA) && defined(BUILD_WITH_CHROMIUM)
- if (renderer_type == FPDF_RENDERERTYPE_SKIA) {
- // Needed to support Chromium's copy of Skia, which uses a
- // DiscardableMemoryAllocator.
- chromium_support::InitializeDiscardableMemoryAllocator();
- }
-#endif
-
FPDF_LIBRARY_CONFIG config;
config.version = 4;
config.m_pUserFontPaths = nullptr;
config.m_pIsolate = nullptr;
config.m_v8EmbedderSlot = 0;
config.m_pPlatform = nullptr;
- config.m_RendererType = renderer_type;
+
+ switch (options.use_renderer_type) {
+ case RendererType::kDefault:
+ config.m_RendererType = GetDefaultRendererType();
+ break;
+
+ case RendererType::kAgg:
+ config.m_RendererType = FPDF_RENDERERTYPE_AGG;
+ break;
+
+#ifdef _WIN32
+ case RendererType::kGdi:
+ // GDI renderer uses `FPDF_RenderPage()`, rather than a renderer type.
+ config.m_RendererType = GetDefaultRendererType();
+ break;
+#endif // _WIN32
+
+#if defined(PDF_ENABLE_SKIA)
+ case RendererType::kSkia:
+#if defined(BUILD_WITH_CHROMIUM)
+ // Needed to support Chromium's copy of Skia, which uses a
+ // `DiscardableMemoryAllocator`.
+ chromium_support::InitializeDiscardableMemoryAllocator();
+#endif // defined(BUILD_WITH_CHROMIUM)
+ config.m_RendererType = FPDF_RENDERERTYPE_SKIA;
+ break;
+#endif // defined(PDF_ENABLE_SKIA)
+ }
std::function<void()> idler = []() {};
#ifdef PDF_ENABLE_V8
@@ -1547,6 +1959,7 @@ int main(int argc, const char* argv[]) {
FSDK_SetLocaltimeFunction([](const time_t* tp) { return gmtime(tp); });
}
+ Processor processor(&options, &idler);
for (const std::string& filename : files) {
size_t file_length = 0;
std::unique_ptr<char, pdfium::FreeDeleter> file_contents =
@@ -1580,8 +1993,7 @@ int main(int argc, const char* argv[]) {
}
}
- ProcessPdf(filename, file_contents.get(), file_length, options, events,
- idler);
+ processor.ProcessPdf(filename, file_contents.get(), file_length, events);
#ifdef ENABLE_CALLGRIND
if (options.callgrind_delimiters)
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index ff91366fe..f9d1bf856 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -173,7 +173,9 @@ component("skia") {
sources += skia_core_public
sources += skia_sksl_gpu_sources
sources += skia_sksl_sources
- sources += skia_utils_sources
+ sources += skia_utils_private
+ sources += skia_xps_sources
+ sources += skia_needs_sksl_sources
sources += skia_codec_core
sources += skia_codec_decode_bmp
sources += skia_encode_srcs
@@ -213,13 +215,15 @@ component("skia") {
"//third_party/skia/src/utils/SkParsePath.cpp",
]
+ if (is_win) {
+ libs = [ "fontsub.lib" ]
+ }
+
# need separate win section to handle chromes auto gn filter
# (build/config/BUILDCONFIG.gn)
if (is_win) {
sources -= [
#windows
- "//third_party/skia/src/utils/win/SkAutoCoInitialize.cpp",
- "//third_party/skia/src/utils/win/SkIStream.cpp",
"//third_party/skia/src/utils/win/SkWGL_win.cpp",
]
}
@@ -350,7 +354,7 @@ component("skia") {
if (is_android) {
deps += [
- "//third_party/android_ndk:cpu_features",
+ "//third_party/cpu_features:ndk_compat",
"//third_party/expat",
]
}
@@ -409,19 +413,14 @@ skia_source_set("skia_core_and_effects") {
defines = []
sources = skia_core_sources
sources += skia_effects_sources
+ sources += skia_colorfilters_sources
+ sources += skia_colorfilters_sksl_sources
sources += skia_effects_imagefilter_sources
visibility = [ ":skia" ]
}
# Bits that involve special vector-y hardware.
-if (current_cpu == "arm64") {
- skia_source_set("skia_opts_crc32") {
- sources = skia_opts.crc32_sources
- cflags = [ "-march=armv8-a+crc" ]
- visibility = [ ":skia_opts" ]
- }
-}
if (current_cpu == "x86" || current_cpu == "x64") {
skia_source_set("skia_opts_sse3") {
sources = skia_opts.ssse3_sources
@@ -433,16 +432,6 @@ if (current_cpu == "x86" || current_cpu == "x64") {
}
visibility = [ ":skia_opts" ]
}
- skia_source_set("skia_opts_sse42") {
- sources = skia_opts.sse42_sources
- if (!is_win || is_clang) {
- cflags = [ "-msse4.2" ]
- }
- if (is_win) {
- defines = [ "SK_CPU_SSE_LEVEL=42" ]
- }
- visibility = [ ":skia_opts" ]
- }
skia_source_set("skia_opts_avx") {
sources = skia_opts.avx_sources
if (!is_win) {
@@ -469,16 +458,6 @@ if (current_cpu == "x86" || current_cpu == "x64") {
}
visibility = [ ":skia_opts" ]
}
- skia_source_set("skia_opts_skx") {
- sources = skia_opts.skx_sources
- if (!is_win) {
- cflags = [ "-march=skylake-avx512" ]
- }
- if (is_win) {
- cflags = [ "/arch:AVX512" ]
- }
- visibility = [ ":skia_opts" ]
- }
}
skia_source_set("skia_opts") {
@@ -489,9 +468,7 @@ skia_source_set("skia_opts") {
deps = [
":skia_opts_avx",
":skia_opts_hsw",
- ":skia_opts_skx",
":skia_opts_sse3",
- ":skia_opts_sse42",
]
} else if (current_cpu == "arm") {
# The assembly uses the frame pointer register (r7 in Thumb/r11 in
@@ -509,7 +486,7 @@ skia_source_set("skia_opts") {
}
}
} else if (current_cpu == "arm64") {
- deps = [ ":skia_opts_crc32" ]
+ # Conditional and empty body needed to avoid assert below
} else if (current_cpu == "mipsel" || current_cpu == "mips64el") {
cflags += [ "-fomit-frame-pointer" ]
} else {
diff --git a/testing/BUILD.gn b/testing/BUILD.gn
index 034de3c72..331c2af41 100644
--- a/testing/BUILD.gn
+++ b/testing/BUILD.gn
@@ -2,6 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/config/sanitizers/sanitizers.gni")
+import("//build_overrides/build.gni")
import("../pdfium.gni")
source_set("test_support") {
@@ -49,6 +51,13 @@ source_set("test_support") {
"../:pdfium_noshorten_config",
]
visibility = [ "../*" ]
+ if (pdf_use_partition_alloc) {
+ sources += [
+ "allocator_shim_config.cpp",
+ "allocator_shim_config.h",
+ ]
+ deps += [ "//base/allocator/partition_allocator:partition_alloc" ]
+ }
if (pdf_enable_v8) {
sources += [
"v8_initializer.cpp",
@@ -170,7 +179,6 @@ source_set("embedder_test_support") {
deps = [
"../:pdfium_public_headers",
"../core/fdrm",
- "../core/fxcrt",
"../core/fxge",
"../third_party:pdfium_base",
"//testing/gmock",
@@ -179,6 +187,7 @@ source_set("embedder_test_support") {
public_deps = [
":test_environments",
":test_support",
+ "../core/fxcrt",
]
configs += [
"../:pdfium_strict_config",
diff --git a/testing/DEPS b/testing/DEPS
index d0dc17242..d0dd4fb81 100644
--- a/testing/DEPS
+++ b/testing/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ '+base',
'+core',
'+fpdfsdk',
'+fxjs',
diff --git a/testing/SUPPRESSIONS b/testing/SUPPRESSIONS
index b50d3ce4f..47b807cc9 100644
--- a/testing/SUPPRESSIONS
+++ b/testing/SUPPRESSIONS
@@ -10,7 +10,7 @@
# Column 1: platform: *, win, mac, linux
# Column 2: v8 support: *, nov8, v8
# Column 3: xfa support: *, noxfa, xfa
-# Column 4: rendering support: *, agg, skia
+# Column 4: rendering support: *, agg, gdi, skia
#
# 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
@@ -313,6 +313,300 @@ Oneof3.pdf * * * *
Sum.pdf * * * *
Test_CheckBox.pdf * * * *
+# GDI
+
+# TODO(pdfium:2054): Remove after associated bug is fixed
+1.pdf * * * gdi
+123.pdf * * * gdi
+1_image.pdf * * * gdi
+2_halftone.pdf * * * gdi
+3_alternate.pdf * * * gdi
+3_interpolate_image.pdf * * * gdi
+3bigpreview.pdf * * * gdi
+4_3.pdf * * * gdi
+4_36.pdf * * * gdi
+FRC_10_8.2.4_View_C.pdf * * * gdi
+FRC_8.4.1_Annotations_Type.pdf * * * gdi
+FRC_8.4.3_Border_Stypes_W_different_values.pdf * * * gdi
+FRC_8.5_Screen_Img_D_Launch.pdf * * * gdi
+FRC_8.5_URI_IsMap.pdf * * * gdi
+bug_691967.pdf * * * gdi
+bug_86459.pdf * * * gdi
+bug_880920.pdf * * * gdi
+bug_898443.pdf * * * gdi
+ch_7_0.pdf * * * gdi
+ch_7_1.pdf * * * gdi
+ch_7_4.pdf * * * gdi
+ch_7_5.pdf * * * gdi
+ch_7_6.pdf * * * gdi
+ch_7_7.pdf * * * gdi
+ch_7_8.pdf * * * gdi
+en_tem.pdf * * * gdi
+example_001.pdf * * * gdi
+example_003.pdf * * * gdi
+example_004.pdf * * * gdi
+example_005.pdf * * * gdi
+example_006.pdf * * * gdi
+example_007.pdf * * * gdi
+example_008.pdf * * * gdi
+example_009.pdf * * * gdi
+example_010.pdf * * * gdi
+example_011.pdf * * * gdi
+example_013.pdf * * * gdi
+example_015.pdf * * * gdi
+example_016.pdf * * * gdi
+example_017.pdf * * * gdi
+example_018.pdf * * * gdi
+example_019.pdf * * * gdi
+example_020.pdf * * * gdi
+example_021.pdf * * * gdi
+example_022.pdf * * * gdi
+example_023.pdf * * * gdi
+example_024.pdf * * * gdi
+example_025.pdf * * * gdi
+example_026.pdf * * * gdi
+example_027.pdf * * * gdi
+example_029.pdf * * * gdi
+example_030.pdf * * * gdi
+example_031.pdf * * * gdi
+example_032.pdf * * * gdi
+example_033.pdf * * * gdi
+example_034.pdf * * * gdi
+example_035.pdf * * * gdi
+example_036.pdf * * * gdi
+example_037.pdf * * * gdi
+example_038.pdf * * * gdi
+example_039.pdf * * * gdi
+example_040.pdf * * * gdi
+example_041.pdf * * * gdi
+example_042.pdf * * * gdi
+example_043.pdf * * * gdi
+example_044.pdf * * * gdi
+example_045.pdf * * * gdi
+example_046.pdf * * * gdi
+example_047.pdf * * * gdi
+example_048.pdf * * * gdi
+example_049.pdf * * * gdi
+example_050.pdf * * * gdi
+example_051.pdf * * * gdi
+example_052.pdf * * * gdi
+example_053.pdf * * * gdi
+example_055.pdf * * * gdi
+example_056.pdf * * * gdi
+example_057.pdf * * * gdi
+example_058.pdf * * * gdi
+example_059.pdf * * * gdi
+example_060.pdf * * * gdi
+example_061.pdf * * * gdi
+example_062.pdf * * * gdi
+example_063.pdf * * * gdi
+example_064.pdf * * * gdi
+example_065.pdf * * * gdi
+image_8bit_devicergb_dctdecode.pdf * * * gdi
+image_bmp.pdf * * * gdi
+image_foxit.pdf * * * gdi
+image_jpg.pdf * * * gdi
+image_png.pdf * * * gdi
+image_tif.pdf * * * gdi
+lines.pdf * * * gdi
+mask_array.pdf * * * gdi
+new_stamp2.pdf * * * gdi
+quick_start_guide.pdf * * * gdi
+whats_new_in_v3.0.pdf * * * gdi
+xfermodeimagefilter.pdf * * * gdi
+
+# TODO(pdfium:2055): Remove after associated bug is fixed
+Date_FormCale.pdf * * * gdi
+FRC_3.5_P__3648_Password_1.pdf * * * gdi
+FRC_8.4.1_Annotations_AP_N_R.D_.pdf * * * gdi
+FRC_8.4.1_Annotations_AS_Off_.pdf * * * gdi
+FRC_8.4.1_Annotations_AS_Yes_.pdf * * * gdi
+FRC_8.5_Bl_Hide.pdf * * * gdi
+FRC_8.5_E_GoTo_D.pdf * * * gdi
+FRC_8.5_Fo_URI_Base.pdf * * * gdi
+FRC_8.5_U_GoToR_NewWindow.pdf * * * gdi
+FRC_8.5_U_GoToR_NewWindow_2.pdf * * * gdi
+FRC_8.5_Widget_C.pdf * * * gdi
+FRC_8.5_Widget_F.pdf * * * gdi
+FRC_8.5_Widget_K.pdf * * * gdi
+FRC_8.5_Widget_V.pdf * * * gdi
+FRC_8.5_X_GoToR_D.pdf * * * gdi
+Line_Stroke.pdf * * * gdi
+Oneof1.pdf * * * gdi
+Oneof2.pdf * * * gdi
+PagePosition_any_rest.pdf * * * gdi
+PagePosition_first.pdf * * * gdi
+PagePosition_last.pdf * * * gdi
+PagePosition_no_any.pdf * * * gdi
+PagePosition_rest.pdf * * * gdi
+PagePosition_rest_any.pdf * * * gdi
+Test_DateField_locale_en_CA.pdf * * * gdi
+Test_DateField_locale_en_GB.pdf * * * gdi
+Test_DateField_locale_en_US.pdf * * * gdi
+Test_DateField_locale_fr_CA.pdf * * * gdi
+Test_DateField_locale_fr_FR.pdf * * * gdi
+Test_DateField_locale_nl_NL.pdf * * * gdi
+Test_DateField_locale_zh_CN.pdf * * * gdi
+Test_DateField_locale_zh_HK.pdf * * * gdi
+Test_Drop_downList.pdf * * * gdi
+Test_NumericField.pdf * * * gdi
+Test_PasswordField.pdf * * * gdi
+Test_RadioButton.pdf * * * gdi
+Test_ResetButton.pdf * * * gdi
+Test_TextField.pdf * * * gdi
+TimeField.pdf * * * gdi
+action_execute_a_menu_item.pdf * * * gdi
+action_hide_show_form.pdf * * * gdi
+action_on_focus.pdf * * * gdi
+action_reset.pdf * * * gdi
+action_run_javascript.pdf * * * gdi
+action_submit_a_form.pdf * * * gdi
+all_trigger_browsefordoc.pdf * * * gdi
+all_trigger_newdoc.pdf * * * gdi
+all_trigger_run_js_lunchurl.pdf * * * gdi
+all_trigger_run_js_maildoc.pdf * * * gdi
+annotation_highlight_author_content.pdf * * * gdi
+annotation_highlight_long_content.pdf * * * gdi
+annotation_highlight_no_author.pdf * * * gdi
+app_launchurl.pdf * * * gdi
+bi.pdf * * * gdi
+bug_434.pdf * * * gdi
+bug_440132.pdf * * * gdi
+calculate_average.pdf * * * gdi
+calculate_sum_a_b_c.pdf * * * gdi
+calculate_validate.pdf * * * gdi
+check_box_no_color.pdf * * * gdi
+combo_box_format.pdf * * * gdi
+date.pdf * * * gdi
+event.change.pdf * * * gdi
+event.changeex.pdf * * * gdi
+event.keydown.pdf * * * gdi
+event.keydown_1_.pdf * * * gdi
+event.shift.pdf * * * gdi
+event.type_name.pdf * * * gdi
+event.value.pdf * * * gdi
+event_change.pdf * * * gdi
+event_fieldfull.pdf * * * gdi
+event_fieldfull_1_.pdf * * * gdi
+example_014.pdf * * * gdi
+example_054.pdf * * * gdi
+form_button0.pdf * * * gdi
+form_button1.pdf * * * gdi
+form_button10.pdf * * * gdi
+form_button2.pdf * * * gdi
+form_button3.pdf * * * gdi
+form_button4.pdf * * * gdi
+form_button5.pdf * * * gdi
+form_button7.pdf * * * gdi
+form_button8.pdf * * * gdi
+form_button9.pdf * * * gdi
+form_checkbox.pdf * * * gdi
+form_checkbox1.pdf * * * gdi
+form_checkbox2.pdf * * * gdi
+form_checkbox3.pdf * * * gdi
+form_combobox_date.pdf * * * gdi
+form_combobox_date2.pdf * * * gdi
+form_combobox_num.pdf * * * gdi
+form_combobox_per.pdf * * * gdi
+form_combobox_plus.pdf * * * gdi
+form_combobox_product.pdf * * * gdi
+form_combobox_time.pdf * * * gdi
+form_radio.pdf * * * gdi
+form_same.pdf * * * gdi
+format_alert_box.pdf * * * gdi
+format_combo_box.pdf * * * gdi
+format_custom_format.pdf * * * gdi
+format_date.pdf * * * gdi
+format_number.pdf * * * gdi
+format_percentage.pdf * * * gdi
+format_special.pdf * * * gdi
+format_text_color.pdf * * * gdi
+getarray.pdf * * * gdi
+js_value_chack_box.pdf * * * gdi
+negative.pdf * * * gdi
+new_certify1.pdf * * * gdi
+new_signature1.pdf * * * gdi
+new_signature2.pdf * * * gdi
+none.pdf * * * gdi
+open_a_weblink.pdf * * * gdi
+percentage.pdf * * * gdi
+rotate.pdf * * * gdi
+show_1.pdf * * * gdi
+simplified_field_notation.pdf * * * gdi
+special.pdf * * * gdi
+submit_form.pdf * * * gdi
+text_field_font_input_decimal_point.pdf * * * gdi
+text_field_multiline_line_spacing.pdf * * * gdi
+time.pdf * * * gdi
+validate_alert_box.pdf * * * gdi
+widget_javascript.pdf * * * gdi
+
+# TODO(pdfium:2056): Remove after associated bug is fixed
+11.pdf * * * gdi
+1_10_watermark.pdf * * * gdi
+1_matrix.pdf * * * gdi
+2_color_tiling.pdf * * * gdi
+2_shading_type_6_00.pdf * * * gdi
+2_shading_type_6_001.pdf * * * gdi
+2_uncolor_tiling.pdf * * * gdi
+3_image_imagemask.pdf * * * gdi
+FRC_11_8.2.4_View_edit.pdf * * * gdi
+FRC_12_8.2.4_View_remove_all.pdf * * * gdi
+FRC_13_8.2.4_View_remove_value.pdf * * * gdi
+FRC_14_8.2.4_Sort_remove_all.pdf * * * gdi
+FRC_15_8.2.4_Sort_remove_value.pdf * * * gdi
+FRC_1_8.2.4_Type_8.6_.pdf * * * gdi
+FRC_2_8.2.4_Type_8.6__remove_value.pdf * * * gdi
+FRC_3.5_AuthEvent_EFOpen.pdf * * * gdi
+FRC_3.5_CFM_AESV2__EncryptMetadata_F.pdf * * * gdi
+FRC_3.5_CF_EFF_StdCF_Strf_Stmf_Identity.pdf * * * gdi
+FRC_3.5_CF_Strf_stmf_StdCF.pdf * * * gdi
+FRC_3.5_EncryptMetadata_None.pdf * * * gdi
+FRC_3.5_V_4_CFM_V2_.pdf * * * gdi
+FRC_3.5_V_5_CFM_AESV3.pdf * * * gdi
+FRC_3.5_v_1_length_40_Filter_standard.pdf * * * gdi
+FRC_3.5_v_2_length_128_AuthEvent_DocOpen_.pdf * * * gdi
+FRC_3_8.2.4_Type_8.6__edit_.pdf * * * gdi
+FRC_4.5.5_Pattern_shading.pdf * * * gdi
+FRC_4.5.5_Pattern_tiling.pdf * * * gdi
+FRC_4_8.2.4_Schema_8.6__remove_all.pdf * * * gdi
+FRC_5_8.2.4_Schema_8.6__remove_value.pdf * * * gdi
+FRC_6_8.2.4_Schema_8.6__remove_obj.pdf * * * gdi
+FRC_7_8.2.4_View_H.pdf * * * gdi
+FRC_8_8.2.4_View_D.pdf * * * gdi
+FRC_9_8.2.4_View_T.pdf * * * gdi
+annotation_circle_fill_opacity.pdf * * * gdi
+annotation_highlight_opacity.pdf * * * gdi
+annotation_square_fill_opacity.pdf * * * gdi
+annotation_square_fill_opacity_dash.pdf * * * gdi
+bug_0_length_line.pdf * * * gdi
+bug_668762.pdf * * * gdi
+bug_883026.pdf * * * gdi
+clipping_text.pdf * * * gdi
+en_fqa.pdf * * * gdi
+en_introduce.pdf * * * gdi
+en_system.pdf * * * gdi
+example_012.pdf * * * gdi
+gradient_many_stops.pdf * * * gdi
+group_xobject.pdf * * * gdi
+image_gif.pdf * * * gdi
+image_ico.pdf * * * gdi
+new_pdfsign1.pdf * * * gdi
+new_pdfsign2.pdf * * * gdi
+new_pdfsign3.pdf * * * gdi
+new_pdfsign4.pdf * * * gdi
+new_stamp3.pdf * * * gdi
+path_10_jd.pdf * * * gdi
+path_5_pattern.pdf * * * gdi
+path_7.pdf * * * gdi
+path_9.pdf * * * gdi
+transformation.pdf * * * gdi
+transparent.pdf * * * gdi
+transparent1.pdf * * * gdi
+xfermodes.pdf * * * gdi
+xfermodes2.pdf * * * gdi
+xfermodes3.pdf * * * gdi
+
#
# JavaScript tests
#
@@ -333,6 +627,12 @@ resolve_nodes_1.pdf * * * *
# Pixel tests
#
+# TODO(pdfium:1098): Remove after associated bug is fixed
+bug_1098.in * * * *
+
+# TODO(chromium:1131694): Remove after associated bug is fixed
+bug_1131694.in * * * *
+
# TODO(pdfium:1747): Remove after associated bug is fixed
bug_1258634.in * * * *
@@ -342,6 +642,11 @@ bug_1331.in * * * *
# TODO(chromium:1356149): Remove after associated bug is fixed
bug_1356149.in mac * * agg
+# This test is intentionally suppressed on Windows. Normally, Windows provides
+# the Symbol font, so this PDF would render correctly. However, in the hermetic
+# test environment, there is no Symbol font and the rendering is incorrect.
+bug_1442723.in win * * *
+
# TODO(pdfium:1457): Remove after associated bug is fixed
bug_1457.in * * * *
@@ -398,3 +703,87 @@ standard_symbols.pdf * * * *
xfa_example.in win * * *
# TODO(pdfium:1095): Remove after associated bug is fixed
xfa_textfield.in win * * *
+
+# GDI
+
+# TODO(pdfium:2054): Remove after associated bug is fixed
+bug_1012369.in * * * gdi
+bug_1258968.in * * * gdi
+bug_1383708.in * * * gdi
+bug_1469.in * * * gdi
+bug_1693.in * * * gdi
+bug_1733.in * * * gdi
+bug_1750.in * * * gdi
+bug_512557.pdf * * * gdi
+bug_71.in * * * gdi
+bug_718762.in * * * gdi
+bug_867501.pdf * * * gdi
+bug_966263.in * * * gdi
+bug_986108.in * * * gdi
+image_transformer_other.in * * * gdi
+jpxdecode_without_smaskindata.in * * * gdi
+
+# TODO(pdfium:2055): Remove after associated bug is fixed
+barcode_test.pdf * * * gdi
+bug_1072440.in * * * gdi
+bug_113910.in * * * gdi
+bug_1282.in * * * gdi
+bug_1304714.in * * * gdi
+bug_1337.in * * * gdi
+bug_1372651.in * * * gdi
+bug_725389.in * * * gdi
+bug_733528.in * * * gdi
+bug_736695_1.in * * * gdi
+bug_736695_2.in * * * gdi
+bug_736695_3.in * * * gdi
+bug_736695_4.in * * * gdi
+bug_983137.in * * * gdi
+checkbox_radiobutton.in * * * gdi
+checkbox_radiobutton_hide.in * * * gdi
+checkbox_radiobutton_reset.in * * * gdi
+combobox_form.in * * * gdi
+dynamic_list_box_allow_multiple_selection.pdf * * * gdi
+dynamic_password_field_background_fill.pdf * * * gdi
+dynamic_table_color_and_width.pdf * * * gdi
+password.in * * * gdi
+resolve_nodes_0.pdf * * * gdi
+scrollable_widgets1.in * * * gdi
+scrollable_widgets2.in * * * gdi
+static_list_box_caption.pdf * * * gdi
+static_password_field_rotate.pdf * * * gdi
+text_form_custom_font.in * * * gdi
+xfa_bmp_image.in * * * gdi
+xfa_gif_image.in * * * gdi
+xfa_jpg_image.in * * * gdi
+xfa_node_caption.pdf * * * gdi
+xfa_png_image.in * * * gdi
+xfa_rectangle_node.in * * * gdi
+xfa_tiff_image.in * * * gdi
+xfa_tiff_lzw_image.in * * * gdi
+xfa_tiff_packbits_image.in * * * gdi
+
+# TODO(pdfium:2056): Remove after associated bug is fixed
+bug_1015233.in * * * gdi
+bug_1087.pdf * * * gdi
+bug_1099446.in * * * gdi
+bug_1161.in * * * gdi
+bug_1236.in * * * gdi
+bug_1288_1.in * * * gdi
+bug_1330.in * * * gdi
+bug_1395648.in * * * gdi
+bug_1396266.in * * * gdi
+bug_1430333.in * * * gdi
+bug_1822.in * * * gdi
+bug_1845.in * * * gdi
+bug_1847.in * * * gdi
+bug_1949.in * * * gdi
+bug_1966.in * * * gdi
+bug_1972_1.in * * * gdi
+bug_1972_3.in * * * gdi
+bug_1976.in * * * gdi
+bug_1995.in * * * gdi
+bug_451366.in * * * gdi
+bug_632.in * * * gdi
+bug_660850.in * * * gdi
+long_dashed_line.in * * * gdi
+matte.in * * * gdi
diff --git a/testing/SUPPRESSIONS_EXACT_MATCHING b/testing/SUPPRESSIONS_EXACT_MATCHING
index 7c260d1f5..b9734d9f1 100644
--- a/testing/SUPPRESSIONS_EXACT_MATCHING
+++ b/testing/SUPPRESSIONS_EXACT_MATCHING
@@ -10,7 +10,7 @@
# Column 1: platform: *, win, mac, linux
# Column 2: v8 support: *, nov8, v8
# Column 3: xfa support: *, noxfa, xfa
-# Column 4: rendering support: *, agg, skia
+# Column 4: rendering support: *, agg, gdi, skia
#
# 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
diff --git a/testing/SUPPRESSIONS_IMAGE_DIFF b/testing/SUPPRESSIONS_IMAGE_DIFF
index e5017568d..e7ecd214d 100644
--- a/testing/SUPPRESSIONS_IMAGE_DIFF
+++ b/testing/SUPPRESSIONS_IMAGE_DIFF
@@ -10,7 +10,7 @@
# Column 1: platform: *, win, mac, linux
# Column 2: v8 support: *, nov8, v8
# Column 3: xfa support: *, noxfa, xfa
-# Column 4: rendering support: *, agg, skia
+# Column 4: rendering support: *, agg, gdi, skia
#
# 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
diff --git a/testing/allocator_shim_config.cpp b/testing/allocator_shim_config.cpp
new file mode 100644
index 000000000..8f0380d52
--- /dev/null
+++ b/testing/allocator_shim_config.cpp
@@ -0,0 +1,25 @@
+// Copyright 2023 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/allocator_shim_config.h"
+
+#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
+#include "base/allocator/partition_allocator/shim/allocator_shim.h"
+
+namespace pdfium {
+
+void ConfigurePartitionAllocShimPartitionForTest() {
+#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
+#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+ allocator_shim::ConfigurePartitions(
+ allocator_shim::EnableBrp(true),
+ allocator_shim::EnableMemoryTagging(false),
+ allocator_shim::SplitMainPartition(true),
+ allocator_shim::UseDedicatedAlignedPartition(true), 0,
+ allocator_shim::BucketDistribution::kNeutral);
+#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
+}
+
+} // namespace pdfium
diff --git a/testing/allocator_shim_config.h b/testing/allocator_shim_config.h
new file mode 100644
index 000000000..cd1448404
--- /dev/null
+++ b/testing/allocator_shim_config.h
@@ -0,0 +1,18 @@
+// Copyright 2023 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TESTING_ALLOCATOR_SHIM_CONFIG_H_
+#define TESTING_ALLOCATOR_SHIM_CONFIG_H_
+
+#if !defined(PDF_USE_PARTITION_ALLOC)
+#error "Included under the wrong build options"
+#endif
+
+namespace pdfium {
+
+void ConfigurePartitionAllocShimPartitionForTest();
+
+} // namespace pdfium
+
+#endif // TESTING_ALLOCATOR_SHIM_CONFIG_H_
diff --git a/testing/embedder_test.cpp b/testing/embedder_test.cpp
index 366088d18..4d31c91b2 100644
--- a/testing/embedder_test.cpp
+++ b/testing/embedder_test.cpp
@@ -24,8 +24,10 @@
#include "testing/utils/hash.h"
#include "testing/utils/path_service.h"
#include "third_party/base/check.h"
+#include "third_party/base/check_op.h"
#include "third_party/base/containers/contains.h"
#include "third_party/base/notreached.h"
+#include "third_party/base/numerics/checked_math.h"
#include "third_party/base/numerics/safe_conversions.h"
namespace {
@@ -540,10 +542,8 @@ void EmbedderTest::UnloadPageNoEvents(FPDF_PAGE page) {
void EmbedderTest::UnloadPageCommon(FPDF_PAGE page, bool do_events) {
DCHECK(form_handle());
int page_number = GetPageNumberForLoadedPage(page);
- if (page_number < 0) {
- NOTREACHED();
- return;
- }
+ CHECK_GE(page_number, 0);
+
if (do_events) {
FORM_DoPageAAction(page, form_handle(), FPDFPAGE_AACTION_CLOSE);
FORM_OnBeforeClosePage(page, form_handle());
@@ -563,10 +563,8 @@ ScopedFPDFBitmap EmbedderTest::RenderLoadedPage(FPDF_PAGE page) {
ScopedFPDFBitmap EmbedderTest::RenderLoadedPageWithFlags(FPDF_PAGE page,
int flags) {
- if (GetPageNumberForLoadedPage(page) < 0) {
- NOTREACHED();
- return nullptr;
- }
+ int page_number = GetPageNumberForLoadedPage(page);
+ CHECK_GE(page_number, 0);
return RenderPageWithFlags(page, form_handle(), flags);
}
@@ -576,10 +574,8 @@ ScopedFPDFBitmap EmbedderTest::RenderSavedPage(FPDF_PAGE page) {
ScopedFPDFBitmap EmbedderTest::RenderSavedPageWithFlags(FPDF_PAGE page,
int flags) {
- if (GetPageNumberForSavedPage(page) < 0) {
- NOTREACHED();
- return nullptr;
- }
+ int page_number = GetPageNumberForSavedPage(page);
+ CHECK_GE(page_number, 0);
return RenderPageWithFlags(page, saved_form_handle(), flags);
}
@@ -681,8 +677,7 @@ int EmbedderTest::BytesPerPixelForFormat(int format) {
case FPDFBitmap_BGRA:
return 4;
default:
- NOTREACHED();
- return 0;
+ NOTREACHED_NORETURN();
}
}
@@ -733,10 +728,7 @@ void EmbedderTest::CloseSavedPage(FPDF_PAGE page) {
DCHECK(saved_form_handle());
int page_number = GetPageNumberForSavedPage(page);
- if (page_number < 0) {
- NOTREACHED();
- return;
- }
+ CHECK_GE(page_number, 0);
FORM_DoPageAAction(page, saved_form_handle(), FPDFPAGE_AACTION_CLOSE);
FORM_OnBeforeClosePage(page, saved_form_handle());
@@ -853,15 +845,11 @@ int EmbedderTest::GetBlockFromString(void* param,
unsigned char* buf,
unsigned long size) {
std::string* new_file = static_cast<std::string*>(param);
- if (!new_file || pos + size < pos) {
- NOTREACHED();
- return 0;
- }
+ CHECK(new_file);
- if (pos + size > new_file->size()) {
- NOTREACHED();
- return 0;
- }
+ pdfium::base::CheckedNumeric<size_t> end = pos;
+ end += size;
+ CHECK_LE(end.ValueOrDie(), new_file->size());
memcpy(buf, new_file->data() + pos, size);
return 1;
diff --git a/testing/embedder_test.h b/testing/embedder_test.h
index c73dd6190..829b1aac7 100644
--- a/testing/embedder_test.h
+++ b/testing/embedder_test.h
@@ -21,7 +21,7 @@
#include "testing/fake_file_access.h"
#include "testing/free_deleter.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class TestLoader;
diff --git a/testing/embedder_test_constants.cpp b/testing/embedder_test_constants.cpp
index 9e8caee9f..1364de1d7 100644
--- a/testing/embedder_test_constants.cpp
+++ b/testing/embedder_test_constants.cpp
@@ -11,7 +11,7 @@ namespace pdfium {
const char* AnnotationStampWithApChecksum() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "a31381406d0b95049e418720750b78dd";
+ return "c7ff65a3ad1b01c3a0e94d635f10670e";
#if BUILDFLAG(IS_APPLE)
return "0521eaa52fe2aa43aafd3e4495f63f0b";
#else
@@ -28,19 +28,25 @@ const char* Bug890322Checksum() {
}
const char* HelloWorldChecksum() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "d1decde2de1c07b5274cc8cb44f92427";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "6eef7237f7591f07616e238422086737";
-#endif
+ return "6eef7237f7591f07616e238422086737";
+#else
return "c1c548442e0e0f949c5550d89bf8ae3b";
+#endif
}
const char* HelloWorldRemovedChecksum() {
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "6e0307348e7c1b92f2f061f92f62fd45";
+ }
#if BUILDFLAG(IS_APPLE)
- if (!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "6e1cae48a2e35c521dee4ca502f48af6";
-#endif
+ return "6e1cae48a2e35c521dee4ca502f48af6";
+#else
return "4a9b80f675f7f3bf2da1b02f12449e4b";
+#endif
}
const char* ManyRectanglesChecksum() {
@@ -57,7 +63,7 @@ const char* RectanglesChecksum() {
const char* TextFormChecksum() {
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "e6d2eb75f18d773f0dad938b1bb22e23";
+ return "b259776fd156003e2a594d1c7ce2d8d7";
#if BUILDFLAG(IS_APPLE)
return "fa2bf756942a950101fc147fc4ef3f82";
#else
diff --git a/testing/embedder_test_main.cpp b/testing/embedder_test_main.cpp
index 53049b694..e089b1a2f 100644
--- a/testing/embedder_test_main.cpp
+++ b/testing/embedder_test_main.cpp
@@ -12,10 +12,18 @@
#include "testing/v8_test_environment.h"
#endif // PDF_ENABLE_V8
+#if defined(PDF_USE_PARTITION_ALLOC)
+#include "testing/allocator_shim_config.h"
+#endif
+
// Can't use gtest-provided main since we need to create our own
// testing environment which needs the executable path in order to
// find the external V8 binary data files.
int main(int argc, char** argv) {
+#if defined(PDF_USE_PARTITION_ALLOC)
+ pdfium::ConfigurePartitionAllocShimPartitionForTest();
+#endif
+
FX_InitializeMemoryAllocators();
#ifdef PDF_ENABLE_V8
diff --git a/testing/fuzzers/BUILD.gn b/testing/fuzzers/BUILD.gn
index 35624cba1..698987fc2 100644
--- a/testing/fuzzers/BUILD.gn
+++ b/testing/fuzzers/BUILD.gn
@@ -2,7 +2,6 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("//build_overrides/build.gni")
import("../../pdfium.gni")
config("fuzzer_config") {
@@ -247,9 +246,6 @@ template("pdfium_fuzzer") {
if (is_public && pdf_enable_xfa) {
deps += [ ":fuzzer_xfa_process_state" ]
}
- if (build_with_chromium) {
- defines += [ "BUILD_WITH_CHROMIUM" ]
- }
}
}
@@ -620,11 +616,5 @@ pdfium_fuzzer("pdf_xml_fuzzer") {
pdfium_fuzzer("pdfium_fuzzer") {
sources = [ "pdfium_fuzzer.cc" ]
deps = [ ":fuzzer_helper" ]
- if (build_with_chromium) {
- deps += [
- "//base",
- "//base/test:test_support",
- ]
- }
public_fuzzer = true
}
diff --git a/testing/fuzzers/DEPS b/testing/fuzzers/DEPS
index d5770448c..fe9eaf63e 100644
--- a/testing/fuzzers/DEPS
+++ b/testing/fuzzers/DEPS
@@ -1,7 +1,4 @@
include_rules = [
'+fxbarcode',
'+xfa',
-
- # Only used when the fuzzer is embedded in Chromium.
- '+base',
]
diff --git a/testing/fuzzers/pdf_cmap_fuzzer.cc b/testing/fuzzers/pdf_cmap_fuzzer.cc
index d4f9c7043..58dfbe671 100644
--- a/testing/fuzzers/pdf_cmap_fuzzer.cc
+++ b/testing/fuzzers/pdf_cmap_fuzzer.cc
@@ -6,7 +6,7 @@
#include "core/fpdfapi/font/cpdf_cmap.h"
#include "core/fxcrt/retain_ptr.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size > 256 * 1024)
diff --git a/testing/fuzzers/pdf_codec_icc_fuzzer.cc b/testing/fuzzers/pdf_codec_icc_fuzzer.cc
index 4db79d255..ada4bc718 100644
--- a/testing/fuzzers/pdf_codec_icc_fuzzer.cc
+++ b/testing/fuzzers/pdf_codec_icc_fuzzer.cc
@@ -5,7 +5,7 @@
#include <cstdint>
#include "core/fxcodec/icc/icc_transform.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
std::unique_ptr<fxcodec::IccTransform> transform =
diff --git a/testing/fuzzers/pdf_codec_jbig2_fuzzer.cc b/testing/fuzzers/pdf_codec_jbig2_fuzzer.cc
index 59eda7610..4c48b6f75 100644
--- a/testing/fuzzers/pdf_codec_jbig2_fuzzer.cc
+++ b/testing/fuzzers/pdf_codec_jbig2_fuzzer.cc
@@ -38,7 +38,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
Jbig2Context jbig2_context;
FXCODEC_STATUS status = Jbig2Decoder::StartDecode(
&jbig2_context, &document_context, width, height, {data, size}, 1, {}, 0,
- bitmap->GetBuffer(), bitmap->GetPitch(), nullptr);
+ bitmap->GetWritableBuffer(), bitmap->GetPitch(), nullptr);
while (status == FXCODEC_STATUS::kDecodeToBeContinued)
status = Jbig2Decoder::ContinueDecode(&jbig2_context, nullptr);
diff --git a/testing/fuzzers/pdf_fuzzer_init_public.cc b/testing/fuzzers/pdf_fuzzer_init_public.cc
index 3227d47bc..993c8a773 100644
--- a/testing/fuzzers/pdf_fuzzer_init_public.cc
+++ b/testing/fuzzers/pdf_fuzzer_init_public.cc
@@ -36,8 +36,9 @@
namespace {
// pdf_fuzzer_init.cc and pdf_fuzzer_init_public.cc are mutually exclusive
-// and should not be built together.
-PDFFuzzerInitPublic* g_instance = new PDFFuzzerInitPublic();
+// and should not be built together. Static initializers and destructors
+// avoid problems with fuzzer initialization and termination.
+PDFFuzzerInitPublic g_instance;
#ifdef PDF_ENABLE_V8
std::string ProgramPath() {
diff --git a/testing/fuzzers/pdf_hint_table_fuzzer.cc b/testing/fuzzers/pdf_hint_table_fuzzer.cc
index 3743b1af7..1351a042d 100644
--- a/testing/fuzzers/pdf_hint_table_fuzzer.cc
+++ b/testing/fuzzers/pdf_hint_table_fuzzer.cc
@@ -11,7 +11,7 @@
#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/span.h"
+#include "third_party/base/containers/span.h"
int32_t GetData(const int32_t** data32, const uint8_t** data, size_t* size) {
const int32_t* ret = *data32;
diff --git a/testing/fuzzers/pdf_jpx_fuzzer.cc b/testing/fuzzers/pdf_jpx_fuzzer.cc
index 3021d7688..c7e7e2f68 100644
--- a/testing/fuzzers/pdf_jpx_fuzzer.cc
+++ b/testing/fuzzers/pdf_jpx_fuzzer.cc
@@ -69,8 +69,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
static_cast<uint32_t>(bitmap->GetHeight()))
return 0;
- decoder->Decode(bitmap->GetBuffer(), bitmap->GetPitch(), /*swap_rgb=*/false,
- GetCompsFromFormat(format));
+ decoder->Decode(bitmap->GetWritableBuffer(), bitmap->GetPitch(),
+ /*swap_rgb=*/false, GetCompsFromFormat(format));
return 0;
}
diff --git a/testing/fuzzers/pdf_nametree_fuzzer.cc b/testing/fuzzers/pdf_nametree_fuzzer.cc
index bc141ed3c..43c10c789 100644
--- a/testing/fuzzers/pdf_nametree_fuzzer.cc
+++ b/testing/fuzzers/pdf_nametree_fuzzer.cc
@@ -11,7 +11,7 @@
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_object.h"
#include "core/fpdfdoc/cpdf_nametree.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
struct Params {
bool delete_backwards;
diff --git a/testing/fuzzers/pdf_psengine_fuzzer.cc b/testing/fuzzers/pdf_psengine_fuzzer.cc
index 5cc2a7608..f24bdce8c 100644
--- a/testing/fuzzers/pdf_psengine_fuzzer.cc
+++ b/testing/fuzzers/pdf_psengine_fuzzer.cc
@@ -5,7 +5,7 @@
#include <stdint.h>
#include "core/fpdfapi/page/cpdf_psengine.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
CPDF_PSEngine engine;
diff --git a/testing/fuzzers/pdf_streamparser_fuzzer.cc b/testing/fuzzers/pdf_streamparser_fuzzer.cc
index e3bd7873b..6921cc946 100644
--- a/testing/fuzzers/pdf_streamparser_fuzzer.cc
+++ b/testing/fuzzers/pdf_streamparser_fuzzer.cc
@@ -6,7 +6,7 @@
#include "core/fpdfapi/page/cpdf_streamparser.h"
#include "core/fpdfapi/parser/cpdf_object.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
CPDF_StreamParser parser(pdfium::make_span(data, size));
diff --git a/testing/fuzzers/pdf_xfa_fdp_fuzzer.cc b/testing/fuzzers/pdf_xfa_fdp_fuzzer.cc
index c438c89ae..cefd09d9a 100644
--- a/testing/fuzzers/pdf_xfa_fdp_fuzzer.cc
+++ b/testing/fuzzers/pdf_xfa_fdp_fuzzer.cc
@@ -159,9 +159,6 @@ class PDFiumXFAFuzzer : public PDFiumFuzzerHelper {
FORM_GetFocusedText(form, page, local_buf, sizeof(local_buf));
break;
}
- default: {
- break;
- }
}
}
}
diff --git a/testing/fuzzers/pdf_xml_fuzzer.cc b/testing/fuzzers/pdf_xml_fuzzer.cc
index 31ab6d76a..e908a7e98 100644
--- a/testing/fuzzers/pdf_xml_fuzzer.cc
+++ b/testing/fuzzers/pdf_xml_fuzzer.cc
@@ -12,7 +12,7 @@
#include "core/fxcrt/xml/cfx_xmldocument.h"
#include "core/fxcrt/xml/cfx_xmlelement.h"
#include "core/fxcrt/xml/cfx_xmlparser.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
FX_SAFE_SIZE_T safe_size = size;
diff --git a/testing/fuzzers/pdfium_fuzzer.cc b/testing/fuzzers/pdfium_fuzzer.cc
index 7e25fedb0..e70702a71 100644
--- a/testing/fuzzers/pdfium_fuzzer.cc
+++ b/testing/fuzzers/pdfium_fuzzer.cc
@@ -6,12 +6,6 @@
#include "testing/fuzzers/pdfium_fuzzer_helper.h"
-#if defined(BUILD_WITH_CHROMIUM)
-#include "base/memory/discardable_memory_allocator.h"
-#include "base/no_destructor.h"
-#include "base/test/test_discardable_memory_allocator.h"
-#endif
-
class PDFiumFuzzer : public PDFiumFuzzerHelper {
public:
PDFiumFuzzer() = default;
@@ -21,12 +15,6 @@ class PDFiumFuzzer : public PDFiumFuzzerHelper {
};
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-#if defined(BUILD_WITH_CHROMIUM)
- static base::NoDestructor<base::TestDiscardableMemoryAllocator>
- test_memory_allocator;
- base::DiscardableMemoryAllocator::SetInstance(test_memory_allocator.get());
-#endif
-
PDFiumFuzzer fuzzer;
fuzzer.RenderPdf(reinterpret_cast<const char*>(data), size);
return 0;
diff --git a/testing/fuzzers/pdfium_fuzzer_helper.cc b/testing/fuzzers/pdfium_fuzzer_helper.cc
index f011b18b3..1d26787e3 100644
--- a/testing/fuzzers/pdfium_fuzzer_helper.cc
+++ b/testing/fuzzers/pdfium_fuzzer_helper.cc
@@ -20,8 +20,9 @@
#include "public/fpdf_dataavail.h"
#include "public/fpdf_ext.h"
#include "public/fpdf_text.h"
-#include "third_party/base/notreached.h"
-#include "third_party/base/span.h"
+#include "third_party/base/check_op.h"
+#include "third_party/base/containers/span.h"
+#include "third_party/base/numerics/checked_math.h"
namespace {
@@ -34,10 +35,9 @@ class FuzzerTestLoader {
unsigned char* pBuf,
unsigned long size) {
FuzzerTestLoader* pLoader = static_cast<FuzzerTestLoader*>(param);
- if (pos + size < pos || pos + size > pLoader->m_Span.size()) {
- NOTREACHED();
- return 0;
- }
+ pdfium::base::CheckedNumeric<size_t> end = pos;
+ end += size;
+ CHECK_LE(end.ValueOrDie(), pLoader->m_Span.size());
memcpy(pBuf, &pLoader->m_Span[pos], size);
return 1;
diff --git a/testing/fuzzers/xfa_codec_fuzzer.h b/testing/fuzzers/xfa_codec_fuzzer.h
index b14b7d7a0..aaa884b9f 100644
--- a/testing/fuzzers/xfa_codec_fuzzer.h
+++ b/testing/fuzzers/xfa_codec_fuzzer.h
@@ -14,7 +14,7 @@
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxge/dib/cfx_dibitmap.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
// Support up to 64 MB. This prevents trivial OOM when MSAN is on and
// time outs.
diff --git a/testing/fx_string_testhelpers.cpp b/testing/fx_string_testhelpers.cpp
index 8e76a76d2..09f765312 100644
--- a/testing/fx_string_testhelpers.cpp
+++ b/testing/fx_string_testhelpers.cpp
@@ -11,7 +11,7 @@
#include "core/fxcrt/cfx_datetime.h"
#include "core/fxcrt/fx_string.h"
#include "third_party/base/check_op.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
std::ostream& operator<<(std::ostream& os, const CFX_DateTime& dt) {
os << dt.GetYear() << "-" << std::to_string(dt.GetMonth()) << "-"
@@ -76,6 +76,6 @@ ScopedFPDFWideString GetFPDFWideString(const std::wstring& wstr) {
}
std::vector<FPDF_WCHAR> GetFPDFWideStringBuffer(size_t length_bytes) {
- DCHECK_EQ(length_bytes % sizeof(FPDF_WCHAR), 0);
+ DCHECK_EQ(length_bytes % sizeof(FPDF_WCHAR), 0u);
return std::vector<FPDF_WCHAR>(length_bytes / sizeof(FPDF_WCHAR));
}
diff --git a/testing/image_diff/image_diff.cpp b/testing/image_diff/image_diff.cpp
index a7019211e..a203bf5e7 100644
--- a/testing/image_diff/image_diff.cpp
+++ b/testing/image_diff/image_diff.cpp
@@ -21,7 +21,6 @@
#include "core/fxcrt/fx_memory.h"
#include "testing/image_diff/image_diff_png.h"
#include "testing/utils/path_service.h"
-#include "third_party/base/cxx17_backports.h"
#include "third_party/base/numerics/safe_conversions.h"
#if BUILDFLAG(IS_WIN)
@@ -351,9 +350,9 @@ bool SubtractImages(const Image& image1, const Image& image2, Image* out) {
int32_t delta_b = b1 - b2;
same &= (delta_r == 0 && delta_g == 0 && delta_b == 0);
- delta_r = pdfium::clamp(128 + delta_r * 8, 0, 255);
- delta_g = pdfium::clamp(128 + delta_g * 8, 0, 255);
- delta_b = pdfium::clamp(128 + delta_b * 8, 0, 255);
+ delta_r = std::clamp(128 + delta_r * 8, 0, 255);
+ delta_g = std::clamp(128 + delta_g * 8, 0, 255);
+ delta_b = std::clamp(128 + delta_b * 8, 0, 255);
uint32_t new_pixel = RGBA_ALPHA;
new_pixel |= delta_r;
@@ -369,11 +368,17 @@ int DiffImages(const std::string& binary_name,
const std::string& file1,
const std::string& file2,
const std::string& out_file,
- bool do_subtraction) {
+ bool do_subtraction,
+ bool reverse_byte_order) {
Image actual_image;
Image baseline_image;
- if (!actual_image.CreateFromFilename(file1)) {
+ bool actual_load_result =
+ reverse_byte_order
+ ? actual_image.CreateFromFilenameWithReverseByteOrder(file1)
+ : actual_image.CreateFromFilename(file1);
+
+ if (!actual_load_result) {
fprintf(stderr, "%s: Unable to open file \"%s\"\n", binary_name.c_str(),
file1.c_str());
return kStatusError;
@@ -451,7 +456,7 @@ int main(int argc, const char* argv[]) {
if (produce_diff_image || produce_image_subtraction) {
if (!diff_filename.empty()) {
return DiffImages(binary_name, filename1, filename2, diff_filename,
- produce_image_subtraction);
+ produce_image_subtraction, reverse_byte_order);
}
} else if (!filename2.empty()) {
return CompareImages(binary_name, filename1, filename2, histograms,
diff --git a/testing/image_diff/image_diff_png.cpp b/testing/image_diff/image_diff_png.cpp
index c2e8b03ca..5a89e35ba 100644
--- a/testing/image_diff/image_diff_png.cpp
+++ b/testing/image_diff/image_diff_png.cpp
@@ -16,6 +16,7 @@
#include <string>
+#include "third_party/base/check_op.h"
#include "third_party/base/notreached.h"
#ifdef USE_SYSTEM_ZLIB
@@ -253,8 +254,7 @@ void DecodeInfoCallback(png_struct* png_ptr, png_info* info_ptr) {
state->output_channels = 1;
break;
default:
- NOTREACHED();
- break;
+ NOTREACHED_NORETURN();
}
} else if (channels == 4) {
switch (state->output_format) {
@@ -271,12 +271,10 @@ void DecodeInfoCallback(png_struct* png_ptr, png_info* info_ptr) {
state->output_channels = 4;
break;
default:
- NOTREACHED();
- break;
+ NOTREACHED_NORETURN();
}
} else {
- NOTREACHED();
- longjmp(png_jmpbuf(png_ptr), 1);
+ NOTREACHED_NORETURN();
}
state->output->resize(state->width * state->output_channels * state->height);
@@ -288,11 +286,7 @@ void DecodeRowCallback(png_struct* png_ptr,
int pass) {
PngDecoderState* state =
static_cast<PngDecoderState*>(png_get_progressive_ptr(png_ptr));
-
- if (static_cast<int>(row_num) > state->height) {
- NOTREACHED();
- return;
- }
+ CHECK_LE(static_cast<int>(row_num), state->height);
uint8_t* base = nullptr;
base = &state->output->front();
@@ -609,10 +603,6 @@ std::vector<uint8_t> EncodeWithCompressionLevel(
output_color_components = 1;
png_output_color_type = PNG_COLOR_TYPE_GRAY;
break;
-
- default:
- NOTREACHED();
- return output;
}
// Row stride should be at least as long as the length of the data.
diff --git a/testing/image_diff/image_diff_png.h b/testing/image_diff/image_diff_png.h
index 370ce3238..5d54c9573 100644
--- a/testing/image_diff/image_diff_png.h
+++ b/testing/image_diff/image_diff_png.h
@@ -9,7 +9,7 @@
#include <vector>
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
namespace image_diff_png {
diff --git a/testing/resources/bug_1658.in b/testing/resources/bug_1658.in
new file mode 100644
index 000000000..0301c9d29
--- /dev/null
+++ b/testing/resources/bug_1658.in
@@ -0,0 +1,65 @@
+{{header}}
+{{object 1 0}} <<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+{{object 2 0}} <<
+ /Type /Pages
+ /Count 1
+ /MediaBox [0 0 400 400]
+ /Kids [3 0 R]
+>>
+endobj
+{{object 3 0}} <<
+ /Type /Page
+ /Parent 2 0 R
+ /Annots [4 0 R]
+>>
+endobj
+{{object 4 0}} <<
+ /Type /Annot
+ /Subtype /Highlight
+ /AP <<
+ /N 5 0 R
+ >>
+ /F 8
+ /P 3 0 R
+ /Rect 6 0 R
+>>
+endobj
+{{object 5 0}} <<
+ /Type /XObject
+ /Subtype /Form
+ /FormType 1
+ /BBox 6 0 R
+ /ProcSet [/PDF]
+ /Resources <<
+ /ExtGState <<
+ /R0 <<
+ /Type /ExtGState
+ /AIS false
+ /BM /Multiply
+ >>
+ >>
+ >>
+ {{streamlen}}
+>>
+stream
+/R0 gs
+1 1 0 rg
+1 w
+72 305 m
+68 309 68 317 72 321 c
+132 321 l
+136 317 136 309 132 305 c
+f
+endstream
+endobj
+{{object 6 0}}
+[67 304 137 322]
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/bug_1658.pdf b/testing/resources/bug_1658.pdf
new file mode 100644
index 000000000..8c47b65d7
--- /dev/null
+++ b/testing/resources/bug_1658.pdf
@@ -0,0 +1,78 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+2 0 obj <<
+ /Type /Pages
+ /Count 1
+ /MediaBox [0 0 400 400]
+ /Kids [3 0 R]
+>>
+endobj
+3 0 obj <<
+ /Type /Page
+ /Parent 2 0 R
+ /Annots [4 0 R]
+>>
+endobj
+4 0 obj <<
+ /Type /Annot
+ /Subtype /Highlight
+ /AP <<
+ /N 5 0 R
+ >>
+ /F 8
+ /P 3 0 R
+ /Rect 6 0 R
+>>
+endobj
+5 0 obj <<
+ /Type /XObject
+ /Subtype /Form
+ /FormType 1
+ /BBox 6 0 R
+ /ProcSet [/PDF]
+ /Resources <<
+ /ExtGState <<
+ /R0 <<
+ /Type /ExtGState
+ /AIS false
+ /BM /Multiply
+ >>
+ >>
+ >>
+ /Length 90
+>>
+stream
+/R0 gs
+1 1 0 rg
+1 w
+72 305 m
+68 309 68 317 72 321 c
+132 321 l
+136 317 136 309 132 305 c
+f
+endstream
+endobj
+6 0 obj
+[67 304 137 322]
+endobj
+xref
+0 7
+0000000000 65535 f
+0000000015 00000 n
+0000000068 00000 n
+0000000157 00000 n
+0000000226 00000 n
+0000000343 00000 n
+0000000698 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 7
+>>
+startxref
+730
+%%EOF
diff --git a/testing/resources/bug_2034.idat b/testing/resources/bug_2034.idat
new file mode 100644
index 000000000..873c40831
--- /dev/null
+++ b/testing/resources/bug_2034.idat
Binary files differ
diff --git a/testing/resources/bug_2034.in b/testing/resources/bug_2034.in
new file mode 100644
index 000000000..f762659cd
--- /dev/null
+++ b/testing/resources/bug_2034.in
@@ -0,0 +1,65 @@
+{{header}}
+{{object 1 0}} <<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+{{object 2 0}} <<
+ /Type /Pages
+ /Count 1
+ /Kids [3 0 R]
+>>
+endobj
+{{object 3 0}} <<
+ /Type /Page
+ /Parent 2 0 R
+ /Contents 4 0 R
+ /MediaBox [0 0 612 792]
+ /Resources <<
+ /XObject <<
+ /HighResolutionImage 5 0 R
+ >>
+ >>
+>>
+endobj
+{{object 4 0}} <<
+ {{streamlen}}
+>>
+stream
+q
+ 612 0 0 792 0 0 cm
+ /HighResolutionImage Do
+Q
+endstream
+endobj
+
+% Image meant to simulate scanner output: full page, 600 DPI, in RGB color.
+{{object 5 0}} <<
+ /Type /XObject
+ /Subtype /Image
+ /BitsPerComponent 4
+ /ColorSpace [
+ /Indexed
+ /DeviceRGB
+ 4
+ <000000 FF0000 00FF00 0000FF FFFFFF>
+ ]
+ /DecodeParms <<
+ /BitsPerComponent 4
+ /Columns 5100
+ /Predictor 10
+ >>
+ /Filter /FlateDecode
+ /Height 6600
+ /Width 5100
+ {{streamlen}}
+>>
+stream
+{{include bug_2034.idat}}
+endstream
+endobj
+
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/bug_2034.pdf b/testing/resources/bug_2034.pdf
new file mode 100644
index 000000000..78ddedff8
--- /dev/null
+++ b/testing/resources/bug_2034.pdf
Binary files differ
diff --git a/testing/resources/javascript/bug_1447268.evt b/testing/resources/javascript/bug_1447268.evt
new file mode 100644
index 000000000..be4c96c73
--- /dev/null
+++ b/testing/resources/javascript/bug_1447268.evt
@@ -0,0 +1,2 @@
+mouseup,left,107,521
+mousedown,left,108,521
diff --git a/testing/resources/javascript/bug_1447268.in b/testing/resources/javascript/bug_1447268.in
new file mode 100644
index 000000000..b12a389e7
--- /dev/null
+++ b/testing/resources/javascript/bug_1447268.in
@@ -0,0 +1,209 @@
+{{header}}
+{{object 1 0}} <<
+ /Type /Catalog
+ /Pages 2 0 R
+ /AcroForm 4 0 R
+ /OpenAction 40 0 R
+>>
+endobj
+{{object 2 0}} <<
+ /Type /Pages
+ /Count 5
+ /Kids [
+ 30 0 R
+ 31 0 R
+ 32 0 R
+ 33 0 R
+ 34 0 R
+ ]
+>>
+endobj
+% Forms
+{{object 4 0}} <<
+ /Fields [
+ 5 0 R
+ 8 0 R
+ 9 0 R
+ 10 0 R
+ 11 0 R
+ ]
+>>
+endobj
+% Fields
+{{object 5 0}} <<
+ /T (Field)
+ /Kids [6 0 R]
+ /V (my_field)
+>>
+endobj
+{{object 6 0}} <<
+ /FT /Tx
+ /Parent 5 0 R
+ /Kids [7 0 R]
+ /Rect [200 200 220 220]
+>>
+endobj
+{{object 7 0}} <<
+ /Type /Annot
+ /Subtype /Widget
+ /Parent 6 0 R
+ /Rect [0 500 600 600]
+
+>>
+endobj
+{{object 8 0}} <<
+ /Type /Annot
+ /Subtype /Widget
+ /FT /Tx
+ /T (Field2)
+ /V (Field_2)
+ /Rect [0 500 600 600]
+>>
+endobj
+{{object 9 0}} <<
+ /Type /Annot
+ /Subtype /Widget
+ /FT /Tx
+ /T (Field4)
+ /V (Field_4)
+ /Rect [0 500 600 600]
+ /AA << /F 24 0 R >>
+>>
+endobj
+{{object 10 0}} <<
+ /Type /Annot
+ /Subtype /Widget
+ /FT /Tx
+ /T (Field5)
+ /V (Field_5)
+ /Rect [0 500 600 600]
+>>
+endobj
+{{object 11 0}} <<
+ /T (Field3)
+ /Parent 4 0 R
+ /Kids [12 0 R]
+ /Opt [(aa) (bb) (cc) (dd) (ee)]
+ /V [(aa) (bb) (cc) (dd) (ee)]
+>>
+endobj
+{{object 12 0}} <<
+ /Type /Annot
+ /Subtype /Widget
+ /FT /Ch
+ /Ff 131072
+ /Parent 11 0 R
+ /Kids [13 0 R]
+>>
+endobj
+{{object 13 0}} <<
+ /Type /Annot
+ /Subtype /Widget
+ /Parent 12 0 R
+ /Rect [0 400 600 600]
+>>
+endobj
+{{object 14 0}} <<
+ /Type /Annot
+ /Subtype /Widget
+ /Parent 12 0 R
+ /Rect [100 400 500 500]
+>>
+endobj
+% OpenAction action
+{{object 22 0}} <<
+ /S /JavaScript
+ /JS 23 0 R
+>>
+endobj
+{{object 23 0}} <<
+ {{streamlen}}
+>>
+stream
+doc = this;
+function cb_func() {
+ doc.pageNum = 1;
+ doc.getField("Field" ).setFocus();
+ doc.getField("Field1").setFocus();
+ doc.getField("Field2").setFocus();
+ doc.getField("Field3").setFocus();
+ doc.getField("Field4").setFocus();
+ doc.getField("Field5").setFocus();
+ return 0;
+}
+doc.getField("Field").checkThisBox ({valueOf: cb_func});
+doc.getField("Field1").checkThisBox({valueOf: cb_func});
+doc.getField("Field2").checkThisBox({valueOf: cb_func});
+doc.getField("Field3").checkThisBox({valueOf: cb_func});
+doc.getField("Field4").checkThisBox({valueOf: cb_func});
+doc.getField("Field5").checkThisBox({valueOf: cb_func});
+endstream
+endobj
+% OpenAction action
+{{object 24 0}} <<
+ /S /JavaScript
+ /JS 25 0 R
+>>
+endobj
+{{object 25 0}} <<
+ {{streamlen}}
+>>
+stream
+this.pageNum = 2;
+this.pageNum = 3;
+endstream
+endobj
+% Pages
+{{object 30 0}} <<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+>>
+endobj
+{{object 31 0}} <<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Annots [9 0 R]
+>>
+endobj
+{{object 32 0}} <<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Annots [13 0 R]
+>>
+endobj
+{{object 33 0}} <<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /AA <</C 22 0 R>>
+>>
+endobj
+{{object 34 0}} <<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Annots [10 0 R]
+>>
+endobj
+% Document JS Action
+{{object 40 0}} <<
+ /Type /Action
+ /S /JavaScript
+ /JS 41 0 R
+>>
+endobj
+{{object 41 0}} <<
+ {{streamlen}}
+>>
+stream
+var f = this.getField("Field4");
+f.setFocus();
+endstream
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/javascript/bug_1447268_expected.txt b/testing/resources/javascript/bug_1447268_expected.txt
new file mode 100644
index 000000000..5d198feba
--- /dev/null
+++ b/testing/resources/javascript/bug_1447268_expected.txt
@@ -0,0 +1,3 @@
+Goto Page: 2
+Goto Page: 3
+Goto Page: 1
diff --git a/testing/resources/multiple_graphics_states.in b/testing/resources/multiple_graphics_states.in
new file mode 100644
index 000000000..882495fb4
--- /dev/null
+++ b/testing/resources/multiple_graphics_states.in
@@ -0,0 +1,58 @@
+{{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
+ /Resources <<
+ /ExtGState <<
+ /GS1 5 0 R
+ /GS2 6 0 R
+ >>
+ >>
+>>
+endobj
+{{object 4 0}} <<
+ {{streamlen}}
+>>
+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*
+/GS1 gs /GS2 gs
+1 0 0 rg
+0 0 10 10 re B*
+70 67 50 30 re B*
+Q
+endstream
+endobj
+{{object 5 0}} <<
+ /ca 0.25
+>>
+endobj
+{{object 6 0}} <<
+ /LW 4
+>>
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/multiple_graphics_states.pdf b/testing/resources/multiple_graphics_states.pdf
new file mode 100644
index 000000000..d9a8d4a88
--- /dev/null
+++ b/testing/resources/multiple_graphics_states.pdf
@@ -0,0 +1,71 @@
+%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
+ /Resources <<
+ /ExtGState <<
+ /GS1 5 0 R
+ /GS2 6 0 R
+ >>
+ >>
+>>
+endobj
+4 0 obj <<
+ /Length 204
+>>
+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*
+/GS1 gs /GS2 gs
+1 0 0 rg
+0 0 10 10 re B*
+70 67 50 30 re B*
+Q
+endstream
+endobj
+5 0 obj <<
+ /ca 0.25
+>>
+endobj
+6 0 obj <<
+ /LW 4
+>>
+endobj
+xref
+0 7
+0000000000 65535 f
+0000000015 00000 n
+0000000068 00000 n
+0000000157 00000 n
+0000000306 00000 n
+0000000562 00000 n
+0000000594 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 7
+>>
+startxref
+623
+%%EOF
diff --git a/testing/resources/pixel/bug_1021762_expected_skia_linux.pdf.0.png b/testing/resources/pixel/bug_1021762_expected_skia_linux.pdf.0.png
new file mode 100644
index 000000000..1419d2ece
--- /dev/null
+++ b/testing/resources/pixel/bug_1021762_expected_skia_linux.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1021762_expected_skia_win.pdf.0.png b/testing/resources/pixel/bug_1021762_expected_skia_win.pdf.0.png
new file mode 100644
index 000000000..1419d2ece
--- /dev/null
+++ b/testing/resources/pixel/bug_1021762_expected_skia_win.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1072440_expected_skia.pdf.0.png b/testing/resources/pixel/bug_1072440_expected_skia.pdf.0.png
index 6ce4fbe71..b0d2d8de5 100644
--- a/testing/resources/pixel/bug_1072440_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/bug_1072440_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1098.evt b/testing/resources/pixel/bug_1098.evt
new file mode 100644
index 000000000..0e0538b6a
--- /dev/null
+++ b/testing/resources/pixel/bug_1098.evt
@@ -0,0 +1,2 @@
+# Show text annotation pop-up
+mousemove,20,250
diff --git a/testing/resources/pixel/bug_1098.in b/testing/resources/pixel/bug_1098.in
new file mode 100644
index 000000000..a18aa1948
--- /dev/null
+++ b/testing/resources/pixel/bug_1098.in
@@ -0,0 +1,60 @@
+{{header}}
+{{object 1 0}} <<
+ /Type /Catalog
+ /AcroForm 2 0 R
+ /Pages 3 0 R
+>>
+{{object 2 0}} <<
+ /Fields [6 0 R]
+ /NeedAppearances true
+>>
+endobj
+{{object 3 0}} <<
+ /Type /Pages
+ /Count 1
+ /Kids [4 0 R]
+>>
+endobj
+{{object 4 0}} <<
+ /Type /Page
+ /Parent 3 0 R
+ /Annots [5 0 R 6 0 R]
+ /MediaBox [0 0 220 270]
+>>
+endobj
+
+% Text annotation with a pop-up containing the test string.
+{{object 5 0}} <<
+ /Type /Annot
+ /Subtype /Text
+ /Contents 7 0 R
+
+ % GenerateTextAP() always uses a 20x20 rectangle for the note icon.
+ % CreatePopupAnnot() always uses a 200x200 rectangle for the pop-up.
+ /Rect [10 240 30 260]
+>>
+endobj
+
+% Text field widget annotation with a black border containing the test string.
+{{object 6 0}} <<
+ /Type /Annot
+ /Subtype /Widget
+ /FT /Tx
+ /MK <<
+ /BC [0]
+ >>
+ /Rect [10 10 210 30]
+ /T (FieldName)
+ /V 7 0 R
+>>
+endobj
+
+% Test string "AaÄäКк€🎨!" in UTF-16BE.
+{{object 7 0}}
+<feff 0041 0061 00c4 00e4 041a 043a 20ac d83cdfa8 0021>
+endobj
+
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/pixel/bug_1098_expected.pdf.0.png b/testing/resources/pixel/bug_1098_expected.pdf.0.png
new file mode 100644
index 000000000..0c518b240
--- /dev/null
+++ b/testing/resources/pixel/bug_1098_expected.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1098_expected_mac.pdf.0.png b/testing/resources/pixel/bug_1098_expected_mac.pdf.0.png
new file mode 100644
index 000000000..39532a1c9
--- /dev/null
+++ b/testing/resources/pixel/bug_1098_expected_mac.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1098_expected_skia.pdf.0.png b/testing/resources/pixel/bug_1098_expected_skia.pdf.0.png
new file mode 100644
index 000000000..8884a3ff4
--- /dev/null
+++ b/testing/resources/pixel/bug_1098_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1098_expected_skia_mac.pdf.0.png b/testing/resources/pixel/bug_1098_expected_skia_mac.pdf.0.png
new file mode 100644
index 000000000..e02cdf9d5
--- /dev/null
+++ b/testing/resources/pixel/bug_1098_expected_skia_mac.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1131694.in b/testing/resources/pixel/bug_1131694.in
new file mode 100644
index 000000000..98ad7fc3a
--- /dev/null
+++ b/testing/resources/pixel/bug_1131694.in
@@ -0,0 +1,125 @@
+{{header}}
+{{object 1 0}} <<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+{{object 2 0}} <<
+ /Type /Pages
+ /Count 1
+ /MediaBox [0 0 200 200]
+ /Kids [3 0 R]
+>>
+endobj
+{{object 3 0}} <<
+ /Type /Page
+ /Parent 2 0 R
+ /Contents 4 0 R
+ /Resources <<
+ /Font <<
+ /F1 5 0 R
+ >>
+ /Pattern <<
+ /P1 8 0 R
+ >>
+ /XObject <<
+ /Img 9 0 R
+ >>
+ >>
+>>
+endobj
+{{object 4 0}} <<
+ {{streamlen}}
+>>
+stream
+/Pattern CS
+/Pattern cs
+/P1 SCN
+/P1 scn
+BT
+/F1 2 Tf
+1 0 0 1 50 50 Tm
+(a)Tj
+ET
+endstream
+endobj
+{{object 5 0}} <<
+ /Type /Font
+ /Subtype /Type3
+ /CharProcs <<
+ /a0 7 0 R
+ >>
+ /Encoding 6 0 R
+ /FirstChar 97
+ /FontBBox [0 0 1000 1000]
+ /FontMatrix [1 0 0 1 0 0]
+ /LastChar 97
+ /Widths [60]
+>>
+endobj
+{{object 6 0}} <<
+ /Type /Encoding
+ /BaseEncoding /WinAnsiEncoding
+ /Differences [97 /a0]
+>>
+endobj
+{{object 7 0}} <<
+ {{streamlen}}
+>>
+stream
+50 0 4 -1 48 45 d1
+q
+4 -1 m
+4 45 l
+48 45 l
+48 -1 l
+h
+W n
+q
+44 0 0 46 4.1 -1.1 cm
+/Img Do
+Q
+Q
+endstream
+endobj
+{{object 8 0}} <<
+ /Type /Pattern
+ /PatternType 2
+ /Matrix [0.75 0 0 -0.75 77 691]
+ /Shading <<
+ /ShadingType 2
+ /ColorSpace /DeviceRGB
+ /Coords [0 0 0 62]
+ /Extend [true true]
+ /Function <<
+ /FunctionType 2
+ /C0 [0.7 0.5 0.3]
+ /C1 [0.9 0.7 0.5]
+ /Domain [0 1]
+ /N 1
+ >>
+ >>
+>>
+endobj
+{{object 9 0}} <<
+ /Type /XObject
+ /Subtype /Image
+ /BitsPerComponent 1
+ /Decode [1 0]
+ /DecodeParms [null <</Columns 44 /K -1>>]
+ /Filter [/ASCIIHexDecode /CCITTFaxDecode]
+ /Height 46
+ /ImageMask true
+ /Width 44
+ {{streamlen}}
+>>
+stream
+26a08680de081e11e187840830f4137a4df0ef4dbedbffff6ffdaf0c2f1f
+fff21b34c82e33044e7c11a09c205e105e97a5e97a5ffa5fe0a3f5ffafff
+b5c9aaa30bed27adb4ad70da4da5b6128f0c426b216818500100100a
+endstream
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/pixel/bug_1131694_expected.pdf.0.png b/testing/resources/pixel/bug_1131694_expected.pdf.0.png
new file mode 100644
index 000000000..37b4cdd01
--- /dev/null
+++ b/testing/resources/pixel/bug_1131694_expected.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_113910_expected_skia.pdf.0.png b/testing/resources/pixel/bug_113910_expected_skia.pdf.0.png
index 3c3cd819c..4eb3fa0ed 100644
--- a/testing/resources/pixel/bug_113910_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/bug_113910_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1271578_expected_skia.pdf.0.png b/testing/resources/pixel/bug_1271578_expected_skia.pdf.0.png
new file mode 100644
index 000000000..b37b9ec8a
--- /dev/null
+++ b/testing/resources/pixel/bug_1271578_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1286_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_1286_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..c20b97408
--- /dev/null
+++ b/testing/resources/pixel/bug_1286_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1287409_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_1287409_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..72da0cd60
--- /dev/null
+++ b/testing/resources/pixel/bug_1287409_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1288_2_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_1288_2_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..0433e4de8
--- /dev/null
+++ b/testing/resources/pixel/bug_1288_2_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1296_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_1296_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..d26193001
--- /dev/null
+++ b/testing/resources/pixel/bug_1296_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1308_1_expected_skia_linux.pdf.0.png b/testing/resources/pixel/bug_1308_1_expected_skia_linux.pdf.0.png
new file mode 100644
index 000000000..784332c7d
--- /dev/null
+++ b/testing/resources/pixel/bug_1308_1_expected_skia_linux.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1308_1_expected_skia_win.pdf.0.png b/testing/resources/pixel/bug_1308_1_expected_skia_win.pdf.0.png
new file mode 100644
index 000000000..784332c7d
--- /dev/null
+++ b/testing/resources/pixel/bug_1308_1_expected_skia_win.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1308_expected_skia_linux.pdf.0.png b/testing/resources/pixel/bug_1308_expected_skia_linux.pdf.0.png
new file mode 100644
index 000000000..252d0a800
--- /dev/null
+++ b/testing/resources/pixel/bug_1308_expected_skia_linux.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1308_expected_skia_win.pdf.0.png b/testing/resources/pixel/bug_1308_expected_skia_win.pdf.0.png
new file mode 100644
index 000000000..252d0a800
--- /dev/null
+++ b/testing/resources/pixel/bug_1308_expected_skia_win.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1338_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_1338_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..5fc2b32f3
--- /dev/null
+++ b/testing/resources/pixel/bug_1338_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1355_expected_skia.pdf.0.png b/testing/resources/pixel/bug_1355_expected_skia.pdf.0.png
index dae811b47..f09778868 100644
--- a/testing/resources/pixel/bug_1355_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/bug_1355_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1355_expected_skia_mac.pdf.0.png b/testing/resources/pixel/bug_1355_expected_skia_mac.pdf.0.png
new file mode 100644
index 000000000..dae811b47
--- /dev/null
+++ b/testing/resources/pixel/bug_1355_expected_skia_mac.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1356149_expected_skia.pdf.0.png b/testing/resources/pixel/bug_1356149_expected_skia.pdf.0.png
new file mode 100644
index 000000000..8f67a344a
--- /dev/null
+++ b/testing/resources/pixel/bug_1356149_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1372651_expected_skia.pdf.0.png b/testing/resources/pixel/bug_1372651_expected_skia.pdf.0.png
index f1823f32f..e7c07b7d1 100644
--- a/testing/resources/pixel/bug_1372651_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/bug_1372651_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1388_2_expected_skia.pdf.0.png b/testing/resources/pixel/bug_1388_2_expected_skia.pdf.0.png
new file mode 100644
index 000000000..c5270f810
--- /dev/null
+++ b/testing/resources/pixel/bug_1388_2_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1388_3_expected_skia.pdf.0.png b/testing/resources/pixel/bug_1388_3_expected_skia.pdf.0.png
new file mode 100644
index 000000000..b97bdeb67
--- /dev/null
+++ b/testing/resources/pixel/bug_1388_3_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1388_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_1388_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..7753a6f3c
--- /dev/null
+++ b/testing/resources/pixel/bug_1388_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1395648_expected_skia.pdf.0.png b/testing/resources/pixel/bug_1395648_expected_skia.pdf.0.png
index 80a944bb1..e62f06ba7 100644
--- a/testing/resources/pixel/bug_1395648_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/bug_1395648_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1396266_expected_skia.pdf.0.png b/testing/resources/pixel/bug_1396266_expected_skia.pdf.0.png
index e872c2c43..4d483cb6a 100644
--- a/testing/resources/pixel/bug_1396266_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/bug_1396266_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1402_expected_skia.pdf.0.png b/testing/resources/pixel/bug_1402_expected_skia.pdf.0.png
index f34b78ea3..9d2c92e2f 100644
--- a/testing/resources/pixel/bug_1402_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/bug_1402_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1402_expected_skia_mac.pdf.0.png b/testing/resources/pixel/bug_1402_expected_skia_mac.pdf.0.png
new file mode 100644
index 000000000..f34b78ea3
--- /dev/null
+++ b/testing/resources/pixel/bug_1402_expected_skia_mac.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1442723.in b/testing/resources/pixel/bug_1442723.in
new file mode 100644
index 000000000..070c97ce1
--- /dev/null
+++ b/testing/resources/pixel/bug_1442723.in
@@ -0,0 +1,80 @@
+{{header}}
+{{object 1 0}} <<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+{{object 2 0}} <<
+ /Type /Pages
+ /Count 1
+ /Kids [3 0 R]
+>>
+endobj
+{{object 3 0}} <<
+ /Type /Page
+ /Parent 2 0 R
+ /Contents 4 0 R
+ /MediaBox [0 0 200 100]
+ /Resources <<
+ /Font <<
+ /F1 5 0 R
+ >>
+ >>
+>>
+endobj
+{{object 4 0}} <<
+ {{streamlen}}
+>>
+stream
+BT
+75 50 TD
+/F1 12 Tf
+10 Tc (=\331\367\370\366\347) Tj
+ET
+endstream
+endobj
+{{object 5 0}} <<
+ /Type /Font
+ /Subtype /TrueType
+ /BaseFont /Symbol
+ /FirstChar 31
+ /FontDescriptor 6 0 R
+ /LastChar 255
+ /Widths [600 250 333 713 500 549 833 778 439 333 333 500 549 250 549 250 278
+ 500 500 500 500 500 500 500 500 500 500 278 278 549 549 549 444 549
+ 722 667 722 612 611 763 603 722 333 631 722 686 889 722 722 768 741
+ 556 592 611 690 439 768 645 795 611 333 863 333 658 500 500 631 549
+ 549 494 439 521 411 603 329 603 549 549 576 521 549 549 521 549 603
+ 439 576 713 686 493 686 494 480 200 480 549 600 600 600 600 600 600
+ 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600
+ 600 600 600 600 600 600 600 600 600 600 600 620 247 549 167 713 500
+ 753 753 753 753 1042 987 603 987 603 400 549 411 549 549 713 494 460
+ 549 549 549 549 1000 603 1000 658 823 686 795 987 768 768 823 768 768
+ 713 713 713 713 713 713 713 768 713 790 790 890 823 549 250 713 603
+ 603 1042 987 603 987 603 494 329 790 790 786 713 384 384 384 384 384
+ 384 494 494 494 494 600 329 274 686 686 686 384 384 384 384 384 384
+ 494 494 494 600]
+>>
+endobj
+{{object 6 0}} <<
+ /Type /FontDescriptor
+ /Ascent 1000
+ /AvgWidth 602
+ /CapHeight 1000
+ /Descent -217
+ /Flags 6
+ /FontBBox [-250 -217 1258 1000]
+ /FontName /Symbol
+ /ItalicAngle 0
+ /Leading 217
+ /MaxWidth 1048
+ /MissingWidth 602
+ /StemH 110
+ /StemV 110
+ /XHeight 700
+>>
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/pixel/bug_1442723_expected.pdf.0.png b/testing/resources/pixel/bug_1442723_expected.pdf.0.png
new file mode 100644
index 000000000..eacc91461
--- /dev/null
+++ b/testing/resources/pixel/bug_1442723_expected.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1442723_expected_agg_mac.pdf.0.png b/testing/resources/pixel/bug_1442723_expected_agg_mac.pdf.0.png
new file mode 100644
index 000000000..46281bcdb
--- /dev/null
+++ b/testing/resources/pixel/bug_1442723_expected_agg_mac.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1442723_expected_skia.pdf.0.png b/testing/resources/pixel/bug_1442723_expected_skia.pdf.0.png
new file mode 100644
index 000000000..21011a4f8
--- /dev/null
+++ b/testing/resources/pixel/bug_1442723_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1491_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_1491_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..fdae5799a
--- /dev/null
+++ b/testing/resources/pixel/bug_1491_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1638_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_1638_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..9d00646da
--- /dev/null
+++ b/testing/resources/pixel/bug_1638_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1639_1_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_1639_1_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..7c19cc3a3
--- /dev/null
+++ b/testing/resources/pixel/bug_1639_1_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1752_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_1752_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..ac5a6417b
--- /dev/null
+++ b/testing/resources/pixel/bug_1752_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1752_expected_skia.pdf.0.png b/testing/resources/pixel/bug_1752_expected_skia.pdf.0.png
index 9cb41b858..6c129efd9 100644
--- a/testing/resources/pixel/bug_1752_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/bug_1752_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1772_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_1772_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..e721e2a32
--- /dev/null
+++ b/testing/resources/pixel/bug_1772_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1774_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_1774_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..4f4537cad
--- /dev/null
+++ b/testing/resources/pixel/bug_1774_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1883_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_1883_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..61c32c7bd
--- /dev/null
+++ b/testing/resources/pixel/bug_1883_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1883_expected_gdi.pdf.1.png b/testing/resources/pixel/bug_1883_expected_gdi.pdf.1.png
new file mode 100644
index 000000000..38fc46a33
--- /dev/null
+++ b/testing/resources/pixel/bug_1883_expected_gdi.pdf.1.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1883_expected_gdi.pdf.2.png b/testing/resources/pixel/bug_1883_expected_gdi.pdf.2.png
new file mode 100644
index 000000000..cffe10fa1
--- /dev/null
+++ b/testing/resources/pixel/bug_1883_expected_gdi.pdf.2.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1883_expected_gdi.pdf.3.png b/testing/resources/pixel/bug_1883_expected_gdi.pdf.3.png
new file mode 100644
index 000000000..a2e91a342
--- /dev/null
+++ b/testing/resources/pixel/bug_1883_expected_gdi.pdf.3.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1922_expected.pdf.0.png b/testing/resources/pixel/bug_1922_expected.pdf.0.png
index 73057ac73..2242e857c 100644
--- a/testing/resources/pixel/bug_1922_expected.pdf.0.png
+++ b/testing/resources/pixel/bug_1922_expected.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1922_expected_skia.pdf.0.png b/testing/resources/pixel/bug_1922_expected_skia.pdf.0.png
new file mode 100644
index 000000000..8b11ac680
--- /dev/null
+++ b/testing/resources/pixel/bug_1922_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1963_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_1963_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..592b62654
--- /dev/null
+++ b/testing/resources/pixel/bug_1963_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1972_2_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_1972_2_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..2d0ce1d52
--- /dev/null
+++ b/testing/resources/pixel/bug_1972_2_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_1983_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_1983_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..ce22301b1
--- /dev/null
+++ b/testing/resources/pixel/bug_1983_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_491_invisible_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_491_invisible_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..82bf239ca
--- /dev/null
+++ b/testing/resources/pixel/bug_491_invisible_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_491_unspecified_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_491_unspecified_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..5beb865d5
--- /dev/null
+++ b/testing/resources/pixel/bug_491_unspecified_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_491_visible_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_491_visible_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..5beb865d5
--- /dev/null
+++ b/testing/resources/pixel/bug_491_visible_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_524043_1_expected_skia.pdf.0.png b/testing/resources/pixel/bug_524043_1_expected_skia.pdf.0.png
new file mode 100644
index 000000000..5bec703c1
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_1_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_524043_2_expected_skia.pdf.0.png b/testing/resources/pixel/bug_524043_2_expected_skia.pdf.0.png
new file mode 100644
index 000000000..376f3915d
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_2_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_524043_3_expected_skia.pdf.0.png b/testing/resources/pixel/bug_524043_3_expected_skia.pdf.0.png
new file mode 100644
index 000000000..5bec703c1
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_3_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_524043_4_expected_skia.pdf.0.png b/testing/resources/pixel/bug_524043_4_expected_skia.pdf.0.png
new file mode 100644
index 000000000..5bec703c1
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_4_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_524043_5_expected_skia.pdf.0.png b/testing/resources/pixel/bug_524043_5_expected_skia.pdf.0.png
new file mode 100644
index 000000000..5bec703c1
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_5_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_524043_7_expected_skia.pdf.0.png b/testing/resources/pixel/bug_524043_7_expected_skia.pdf.0.png
new file mode 100644
index 000000000..376f3915d
--- /dev/null
+++ b/testing/resources/pixel/bug_524043_7_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_528103_expected_skia.pdf.0.png b/testing/resources/pixel/bug_528103_expected_skia.pdf.0.png
new file mode 100644
index 000000000..6c4c4acfc
--- /dev/null
+++ b/testing/resources/pixel/bug_528103_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_543018_1_expected_skia.pdf.0.png b/testing/resources/pixel/bug_543018_1_expected_skia.pdf.0.png
new file mode 100644
index 000000000..5bec703c1
--- /dev/null
+++ b/testing/resources/pixel/bug_543018_1_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_543018_2_expected_skia.pdf.0.png b/testing/resources/pixel/bug_543018_2_expected_skia.pdf.0.png
new file mode 100644
index 000000000..5bec703c1
--- /dev/null
+++ b/testing/resources/pixel/bug_543018_2_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_551258_1_expected_skia.pdf.0.png b/testing/resources/pixel/bug_551258_1_expected_skia.pdf.0.png
new file mode 100644
index 000000000..5bec703c1
--- /dev/null
+++ b/testing/resources/pixel/bug_551258_1_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_585_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_585_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..b1056a0d8
--- /dev/null
+++ b/testing/resources/pixel/bug_585_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_601362_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_601362_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..9288387a6
--- /dev/null
+++ b/testing/resources/pixel/bug_601362_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_632_expected_skia.pdf.1.png b/testing/resources/pixel/bug_632_expected_skia.pdf.1.png
index 002dcbabd..3e66da2e7 100644
--- a/testing/resources/pixel/bug_632_expected_skia.pdf.1.png
+++ b/testing/resources/pixel/bug_632_expected_skia.pdf.1.png
Binary files differ
diff --git a/testing/resources/pixel/bug_665467_expected_skia.pdf.0.png b/testing/resources/pixel/bug_665467_expected_skia.pdf.0.png
index 2cd13ff01..2e9c91541 100644
--- a/testing/resources/pixel/bug_665467_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/bug_665467_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_714187_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_714187_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..57b110864
--- /dev/null
+++ b/testing/resources/pixel/bug_714187_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_725389_expected_skia.pdf.0.png b/testing/resources/pixel/bug_725389_expected_skia.pdf.0.png
index 25ad89097..0cdd2ccff 100644
--- a/testing/resources/pixel/bug_725389_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/bug_725389_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_725389_expected_skia_mac.pdf.0.png b/testing/resources/pixel/bug_725389_expected_skia_mac.pdf.0.png
index 4a5a4b051..48a208758 100644
--- a/testing/resources/pixel/bug_725389_expected_skia_mac.pdf.0.png
+++ b/testing/resources/pixel/bug_725389_expected_skia_mac.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_725555_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_725555_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..a29266938
--- /dev/null
+++ b/testing/resources/pixel/bug_725555_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_733528_expected_skia.pdf.0.png b/testing/resources/pixel/bug_733528_expected_skia.pdf.0.png
index 6dfa99db7..7e13f3122 100644
--- a/testing/resources/pixel/bug_733528_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/bug_733528_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_736695_2_expected_skia.pdf.0.png b/testing/resources/pixel/bug_736695_2_expected_skia.pdf.0.png
index 801b157f4..3cddbc018 100644
--- a/testing/resources/pixel/bug_736695_2_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/bug_736695_2_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_736695_3_expected_skia.pdf.0.png b/testing/resources/pixel/bug_736695_3_expected_skia.pdf.0.png
index 1b02f1b4c..8f668d040 100644
--- a/testing/resources/pixel/bug_736695_3_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/bug_736695_3_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_736703_expected_skia.pdf.0.png b/testing/resources/pixel/bug_736703_expected_skia.pdf.0.png
new file mode 100644
index 000000000..f850bff76
--- /dev/null
+++ b/testing/resources/pixel/bug_736703_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_820345_expected_skia.pdf.0.png b/testing/resources/pixel/bug_820345_expected_skia.pdf.0.png
new file mode 100644
index 000000000..9813a9624
--- /dev/null
+++ b/testing/resources/pixel/bug_820345_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_843_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_843_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..47d721dfb
--- /dev/null
+++ b/testing/resources/pixel/bug_843_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_845697_expected_skia.pdf.0.png b/testing/resources/pixel/bug_845697_expected_skia.pdf.0.png
new file mode 100644
index 000000000..cf04e70b9
--- /dev/null
+++ b/testing/resources/pixel/bug_845697_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_846_expected_skia.pdf.0.png b/testing/resources/pixel/bug_846_expected_skia.pdf.0.png
index f7fa9ff20..10cde92c9 100644
--- a/testing/resources/pixel/bug_846_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/bug_846_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_846_expected_skia_mac.pdf.0.png b/testing/resources/pixel/bug_846_expected_skia_mac.pdf.0.png
index 56355273d..0f361df2e 100644
--- a/testing/resources/pixel/bug_846_expected_skia_mac.pdf.0.png
+++ b/testing/resources/pixel/bug_846_expected_skia_mac.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_846_expected_skia_win.pdf.0.png b/testing/resources/pixel/bug_846_expected_skia_win.pdf.0.png
index 56355273d..0f361df2e 100644
--- a/testing/resources/pixel/bug_846_expected_skia_win.pdf.0.png
+++ b/testing/resources/pixel/bug_846_expected_skia_win.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_909762_expected_skia_linux.pdf.0.png b/testing/resources/pixel/bug_909762_expected_skia_linux.pdf.0.png
new file mode 100644
index 000000000..2a06ee056
--- /dev/null
+++ b/testing/resources/pixel/bug_909762_expected_skia_linux.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_909762_expected_skia_win.pdf.0.png b/testing/resources/pixel/bug_909762_expected_skia_win.pdf.0.png
new file mode 100644
index 000000000..2a06ee056
--- /dev/null
+++ b/testing/resources/pixel/bug_909762_expected_skia_win.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_925736_expected_skia.pdf.0.png b/testing/resources/pixel/bug_925736_expected_skia.pdf.0.png
new file mode 100644
index 000000000..154cfeee2
--- /dev/null
+++ b/testing/resources/pixel/bug_925736_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_972999_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_972999_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..72da0cd60
--- /dev/null
+++ b/testing/resources/pixel/bug_972999_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_983289_expected_gdi.pdf.0.png b/testing/resources/pixel/bug_983289_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..80fa56b4c
--- /dev/null
+++ b/testing/resources/pixel/bug_983289_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/bug_984811_expected_skia.pdf.0.png b/testing/resources/pixel/bug_984811_expected_skia.pdf.0.png
new file mode 100644
index 000000000..9c713b55e
--- /dev/null
+++ b/testing/resources/pixel/bug_984811_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/font_size_expected_skia.pdf.0.png b/testing/resources/pixel/font_size_expected_skia.pdf.0.png
new file mode 100644
index 000000000..2b638ab31
--- /dev/null
+++ b/testing/resources/pixel/font_size_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/generation_numbers1_expected_skia.pdf.0.png b/testing/resources/pixel/generation_numbers1_expected_skia.pdf.0.png
new file mode 100644
index 000000000..5e3dc05df
--- /dev/null
+++ b/testing/resources/pixel/generation_numbers1_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/generation_numbers2_expected_skia.pdf.0.png b/testing/resources/pixel/generation_numbers2_expected_skia.pdf.0.png
new file mode 100644
index 000000000..5e3dc05df
--- /dev/null
+++ b/testing/resources/pixel/generation_numbers2_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/matte_expected_skia.pdf.0.png b/testing/resources/pixel/matte_expected_skia.pdf.0.png
index bdab40406..97fa17e63 100644
--- a/testing/resources/pixel/matte_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/matte_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/password_expected_skia.pdf.0.png b/testing/resources/pixel/password_expected_skia.pdf.0.png
index 01b4b6866..c5c0b2389 100644
--- a/testing/resources/pixel/password_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/password_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/rectangles_wrong_xref_size.in b/testing/resources/pixel/rectangles_wrong_xref_size.in
new file mode 100644
index 000000000..18d9ca3e1
--- /dev/null
+++ b/testing/resources/pixel/rectangles_wrong_xref_size.in
@@ -0,0 +1,48 @@
+{{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}} <<
+ {{streamlen}}
+>>
+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 <<
+ /Root 1 0 R
+ % Manually specify the trailer instead of using the macro to deliberately set
+ % the /Size to an incorrect value.
+ /Size 4
+>>
+{{startxref}}
+%%EOF
diff --git a/testing/resources/pixel/rectangles_wrong_xref_size_expected.pdf.0.png b/testing/resources/pixel/rectangles_wrong_xref_size_expected.pdf.0.png
new file mode 100644
index 000000000..ee652fa5a
--- /dev/null
+++ b/testing/resources/pixel/rectangles_wrong_xref_size_expected.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/rectangles_wrong_xref_size_expected_gdi.pdf.0.png b/testing/resources/pixel/rectangles_wrong_xref_size_expected_gdi.pdf.0.png
new file mode 100644
index 000000000..72da0cd60
--- /dev/null
+++ b/testing/resources/pixel/rectangles_wrong_xref_size_expected_gdi.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/rectangles_wrong_xref_size_expected_skia.pdf.0.png b/testing/resources/pixel/rectangles_wrong_xref_size_expected_skia.pdf.0.png
new file mode 100644
index 000000000..8a6b8ed44
--- /dev/null
+++ b/testing/resources/pixel/rectangles_wrong_xref_size_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/scrollable_widgets1_expected_skia.pdf.0.png b/testing/resources/pixel/scrollable_widgets1_expected_skia.pdf.0.png
index d4c1f9d22..348c1a55c 100644
--- a/testing/resources/pixel/scrollable_widgets1_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/scrollable_widgets1_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/scrollable_widgets2_expected_skia.pdf.0.png b/testing/resources/pixel/scrollable_widgets2_expected_skia.pdf.0.png
index dd9f6a196..79ca0f500 100644
--- a/testing/resources/pixel/scrollable_widgets2_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/scrollable_widgets2_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/text_form_custom_font_expected_skia.pdf.0.png b/testing/resources/pixel/text_form_custom_font_expected_skia.pdf.0.png
index 47582b6c2..5f898f8e1 100644
--- a/testing/resources/pixel/text_form_custom_font_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/text_form_custom_font_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/barcode_test_expected_skia.pdf.0.png b/testing/resources/pixel/xfa_specific/barcode_test_expected_skia.pdf.0.png
index 3716b9cd8..e144c04e2 100644
--- a/testing/resources/pixel/xfa_specific/barcode_test_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/xfa_specific/barcode_test_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/dynamic_list_box_allow_multiple_selection_expected_skia.pdf.0.png b/testing/resources/pixel/xfa_specific/dynamic_list_box_allow_multiple_selection_expected_skia.pdf.0.png
index 3ccc1a290..da9e4b301 100644
--- a/testing/resources/pixel/xfa_specific/dynamic_list_box_allow_multiple_selection_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/xfa_specific/dynamic_list_box_allow_multiple_selection_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/dynamic_list_box_allow_multiple_selection_expected_skia_mac.pdf.0.png b/testing/resources/pixel/xfa_specific/dynamic_list_box_allow_multiple_selection_expected_skia_mac.pdf.0.png
index eb303b233..6adaba654 100644
--- a/testing/resources/pixel/xfa_specific/dynamic_list_box_allow_multiple_selection_expected_skia_mac.pdf.0.png
+++ b/testing/resources/pixel/xfa_specific/dynamic_list_box_allow_multiple_selection_expected_skia_mac.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/dynamic_password_field_background_fill_expected_skia.pdf.0.png b/testing/resources/pixel/xfa_specific/dynamic_password_field_background_fill_expected_skia.pdf.0.png
index 072a537a7..b4b8c0d35 100644
--- a/testing/resources/pixel/xfa_specific/dynamic_password_field_background_fill_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/xfa_specific/dynamic_password_field_background_fill_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/dynamic_table_color_and_width_expected_skia.pdf.0.png b/testing/resources/pixel/xfa_specific/dynamic_table_color_and_width_expected_skia.pdf.0.png
index d443a3574..ab5214f71 100644
--- a/testing/resources/pixel/xfa_specific/dynamic_table_color_and_width_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/xfa_specific/dynamic_table_color_and_width_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/resolve_nodes_0_expected_skia.pdf.0.png b/testing/resources/pixel/xfa_specific/resolve_nodes_0_expected_skia.pdf.0.png
index 884a23f42..d90125f68 100644
--- a/testing/resources/pixel/xfa_specific/resolve_nodes_0_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/xfa_specific/resolve_nodes_0_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/static_list_box_caption_expected_skia.pdf.0.png b/testing/resources/pixel/xfa_specific/static_list_box_caption_expected_skia.pdf.0.png
index 3beefe0be..a2c47a33d 100644
--- a/testing/resources/pixel/xfa_specific/static_list_box_caption_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/xfa_specific/static_list_box_caption_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/static_list_box_caption_expected_skia_mac.pdf.0.png b/testing/resources/pixel/xfa_specific/static_list_box_caption_expected_skia_mac.pdf.0.png
new file mode 100644
index 000000000..2c2a5b0b0
--- /dev/null
+++ b/testing/resources/pixel/xfa_specific/static_list_box_caption_expected_skia_mac.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/static_password_field_rotate_expected_skia.pdf.0.png b/testing/resources/pixel/xfa_specific/static_password_field_rotate_expected_skia.pdf.0.png
index 4b35140e7..0a9ff37d3 100644
--- a/testing/resources/pixel/xfa_specific/static_password_field_rotate_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/xfa_specific/static_password_field_rotate_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/static_password_field_rotate_expected_skia.pdf.1.png b/testing/resources/pixel/xfa_specific/static_password_field_rotate_expected_skia.pdf.1.png
index fd88db211..fa7e97e0f 100644
--- a/testing/resources/pixel/xfa_specific/static_password_field_rotate_expected_skia.pdf.1.png
+++ b/testing/resources/pixel/xfa_specific/static_password_field_rotate_expected_skia.pdf.1.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/static_password_field_rotate_expected_skia_mac.pdf.0.png b/testing/resources/pixel/xfa_specific/static_password_field_rotate_expected_skia_mac.pdf.0.png
new file mode 100644
index 000000000..29d3b0963
--- /dev/null
+++ b/testing/resources/pixel/xfa_specific/static_password_field_rotate_expected_skia_mac.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/static_password_field_rotate_expected_skia_mac.pdf.1.png b/testing/resources/pixel/xfa_specific/static_password_field_rotate_expected_skia_mac.pdf.1.png
new file mode 100644
index 000000000..77b3a7b41
--- /dev/null
+++ b/testing/resources/pixel/xfa_specific/static_password_field_rotate_expected_skia_mac.pdf.1.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/use_ahem/xfa_textfield_expected_skia.pdf.0.png b/testing/resources/pixel/xfa_specific/use_ahem/xfa_textfield_expected_skia.pdf.0.png
index ad18d2670..00bad268b 100644
--- a/testing/resources/pixel/xfa_specific/use_ahem/xfa_textfield_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/xfa_specific/use_ahem/xfa_textfield_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia.pdf.0.png b/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia.pdf.0.png
index fe509a875..ffc1b8027 100644
--- a/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia.pdf.0.png
+++ b/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia.pdf.1.png b/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia.pdf.1.png
index e720b9b30..13174e57d 100644
--- a/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia.pdf.1.png
+++ b/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia.pdf.1.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_mac.pdf.0.png b/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_mac.pdf.0.png
index 384294c94..52e6d96ce 100644
--- a/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_mac.pdf.0.png
+++ b/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_mac.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_mac.pdf.1.png b/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_mac.pdf.1.png
index 3366bc017..e7fb0f307 100644
--- a/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_mac.pdf.1.png
+++ b/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_mac.pdf.1.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_win.pdf.0.png b/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_win.pdf.0.png
index 54f04d850..a974ba2bf 100644
--- a/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_win.pdf.0.png
+++ b/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_win.pdf.0.png
Binary files differ
diff --git a/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_win.pdf.1.png b/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_win.pdf.1.png
index 7691fb18f..605ed4c97 100644
--- a/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_win.pdf.1.png
+++ b/testing/resources/pixel/xfa_specific/xfa_node_caption_expected_skia_win.pdf.1.png
Binary files differ
diff --git a/testing/resources/rectangles_object_zero.in b/testing/resources/rectangles_object_zero.in
new file mode 100644
index 000000000..40a45e7f5
--- /dev/null
+++ b/testing/resources/rectangles_object_zero.in
@@ -0,0 +1,45 @@
+{{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
+ % Deliberately references object 0.
+ /CropBox 0 0 R
+>>
+endobj
+{{object 4 0}} <<
+ {{streamlen}}
+>>
+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_object_zero.pdf b/testing/resources/rectangles_object_zero.pdf
new file mode 100644
index 000000000..469ba0b02
--- /dev/null
+++ b/testing/resources/rectangles_object_zero.pdf
@@ -0,0 +1,56 @@
+%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
+ % Deliberately references object 0.
+ /CropBox 0 0 R
+>>
+endobj
+4 0 obj <<
+ /Length 188
+>>
+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
+0000000157 00000 n
+0000000281 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 5
+>>
+startxref
+521
+%%EOF
diff --git a/testing/resources/tagged_table.in b/testing/resources/tagged_table.in
index ee298c57b..6e2ddc020 100644
--- a/testing/resources/tagged_table.in
+++ b/testing/resources/tagged_table.in
@@ -203,14 +203,22 @@ endobj
/S /TD
/P 13 0 R
/Pg 3 0 R
- /A [<<
- /O /Table
- /ColProp (Sum)
- /CurUSD true
- >>]
+ /A 18 0 R
/ID (node18)
>>
endobj
+{{object 18 0}} [
+ <<
+ /O /Table
+ /ColProp (Sum)
+ /CurUSD true
+ /RowSpan 19 0 R
+ >>
+]
+endobj
+{{object 19 0}}
+ 3
+endobj
{{xref}}
{{trailer}}
{{startxref}}
diff --git a/testing/resources/tagged_table.pdf b/testing/resources/tagged_table.pdf
index 4428682a2..6e2bf9e49 100644
--- a/testing/resources/tagged_table.pdf
+++ b/testing/resources/tagged_table.pdf
@@ -204,16 +204,24 @@ endobj
/S /TD
/P 13 0 R
/Pg 3 0 R
- /A [<<
- /O /Table
- /ColProp (Sum)
- /CurUSD true
- >>]
+ /A 18 0 R
/ID (node18)
>>
endobj
+18 0 obj [
+ <<
+ /O /Table
+ /ColProp (Sum)
+ /CurUSD true
+ /RowSpan 19 0 R
+ >>
+]
+endobj
+19 0 obj
+ 3
+endobj
xref
-0 18
+0 20
0000000000 65535 f
0000000015 00000 n
0000000145 00000 n
@@ -232,10 +240,12 @@ xref
0000002276 00000 n
0000002366 00000 n
0000002513 00000 n
+0000002615 00000 n
+0000002715 00000 n
trailer <<
/Root 1 0 R
- /Size 18
+ /Size 20
>>
startxref
-2683
+2735
%%EOF
diff --git a/testing/resources/tagged_table_bad_parent.in b/testing/resources/tagged_table_bad_parent.in
new file mode 100644
index 000000000..8175cba8d
--- /dev/null
+++ b/testing/resources/tagged_table_bad_parent.in
@@ -0,0 +1,217 @@
+{{header}}
+{{object 1 0}} <<
+ /Type /Catalog
+ /Pages 2 0 R
+ /StructTreeRoot 8 0 R
+ /Lang (en-US)
+ /MarkInfo <<
+ /Marked true
+ >>
+>>
+endobj
+{{object 2 0}} <<
+ /Type /Pages
+ /Count 1
+ /Kids [3 0 R]
+>>
+endobj
+{{object 3 0}} <<
+ /Type /Page
+ /Parent 2 0 R
+ /Contents 4 0 R
+ /MediaBox [0 0 612 792]
+ /Group <<
+ /CS /DeviceRGB
+ /I true
+ /S /Transparency
+ >>
+ /Resources <<
+ /ProcSet [/PDF /ImageC /ImageI /ImageB]
+ /XObject <<
+ /Tr8 5 0 R
+ /Im7 6 0 R
+ >>
+ /ExtGState <<
+ /EGS9 7 0 R
+ >>
+ >>
+ /StructParents 0
+>>
+endobj
+{{object 4 0}} <<
+ {{streamlen}}
+>>
+stream
+0.1 w
+/Artifact
+BMC
+q
+0 0 612 792 re
+W* n
+EMC
+/Figure<</MCID 0>>
+BDC
+Q
+q
+281 685.3 50 50 re
+W* n
+q
+49.9 0 0 50 281.1 685.4 cm
+/Im7 Do
+Q
+EMC
+Q
+q
+EGS9 gs /Tr8 Do
+Q
+endstream
+endobj
+{{object 5 0}} <<
+ /Type /XObject
+ /Subtype /Form
+ /BBox [-140 395 753 395.1]
+ /Group <<
+ /CS /DeviceRGB
+ /K true
+ /S /Transparency
+ >>
+ {{streamlen}}
+>>
+stream
+endstream
+endobj
+{{object 6 0}} <<
+ /Type /XObject
+ /Subtype /Image
+ /Width 50
+ /Height 50
+ /BitsPerComponent 8
+ /ColorSpace /DeviceRGB
+ /Filter [/ASCIIHexDecode /FlateDecode]
+ {{streamlen}}
+>>
+stream
+789cedc13101000000c2a0f54fed6f06a00000000000000078031d4c0001
+endstream
+endobj
+{{object 7 0}} <<
+ /ca 0.5
+ /CA 0.5
+>>
+endobj
+{{object 8 0}} <<
+ /Type /StructTreeRoot
+ /ParentTree 9 0 R
+ /K [10 0 R]
+ /RoleMap <<
+ /Document /Document
+ /Standard /P
+ /Figure /Figure
+ >>
+>>
+endobj
+{{object 9 0}} <<
+ /Nums [
+ 0
+ [10 0 R 11 0 R 12 0 R 13 0 R 14 0 R 15 0 R 16 0 R 17 0 R]
+ ]
+>>
+endobj
+{{object 10 0}} <<
+ /Type /StructElem
+ /S /Document
+ /K [11 0 R]
+ /P 8 0 R
+ /T (TitleText)
+ /Pg 3 0 R
+ /Lang (en-US)
+>>
+endobj
+{{object 11 0}} <<
+ /Type /StructElem
+ /S /Table
+ /K [12 0 R] % Deliberately left off object 13 0.
+ /P 10 0 R
+ /Pg 3 0 R
+ /A [<<
+ /O /Table
+ /Summary ()
+ >>]
+ /ID (node12)
+ /Lang (hu)
+>>
+endobj
+{{object 12 0}} <<
+ /Type /StructElem
+ /S /TR
+ /K [14 0 R 15 0 R]
+ /P 11 0 R
+ /Pg 3 0 R
+ /ID ()
+>>
+endobj
+{{object 13 0}} <<
+ /Type /StructElem
+ /S /TR
+ /K [16 0 R] % Deliberately left off object 17 0.
+ /P 11 0 R
+ /Pg 3 0 R
+ /A <<
+ /O /Table
+ >>
+ /ID (node14)
+>>
+endobj
+{{object 14 0}} <<
+ /Type /StructElem
+ /S /TH
+ /P 12 0 R
+ /Pg 3 0 R
+ /A [<<
+ /O /Table
+ /Scope /Row
+ >>
+ <<
+ /O /Table
+ /ColSpan 2
+ >>]
+ /ID (node15)
+>>
+endobj
+{{object 15 0}} <<
+ /Type /StructElem
+ /S /TD
+ /P 12 0 R
+ /Pg 3 0 R
+ /ID (node16)
+>>
+endobj
+{{object 16 0}} <<
+ /Type /StructElem
+ /S /TH
+ /P 13 0 R
+ /Pg 3 0 R
+ /A [<<
+ /O /Table
+ /Scope /Row
+ >>]
+ /ID (node17)
+>>
+endobj
+{{object 17 0}} <<
+ /Type /StructElem
+ /S /TD
+ /P 13 0 R
+ /Pg 3 0 R
+ /A [<<
+ /O /Table
+ /ColProp (Sum)
+ /CurUSD true
+ >>]
+ /ID (node18)
+>>
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/tagged_table_bad_parent.pdf b/testing/resources/tagged_table_bad_parent.pdf
new file mode 100644
index 000000000..43d9aa38a
--- /dev/null
+++ b/testing/resources/tagged_table_bad_parent.pdf
@@ -0,0 +1,241 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+ /Type /Catalog
+ /Pages 2 0 R
+ /StructTreeRoot 8 0 R
+ /Lang (en-US)
+ /MarkInfo <<
+ /Marked true
+ >>
+>>
+endobj
+2 0 obj <<
+ /Type /Pages
+ /Count 1
+ /Kids [3 0 R]
+>>
+endobj
+3 0 obj <<
+ /Type /Page
+ /Parent 2 0 R
+ /Contents 4 0 R
+ /MediaBox [0 0 612 792]
+ /Group <<
+ /CS /DeviceRGB
+ /I true
+ /S /Transparency
+ >>
+ /Resources <<
+ /ProcSet [/PDF /ImageC /ImageI /ImageB]
+ /XObject <<
+ /Tr8 5 0 R
+ /Im7 6 0 R
+ >>
+ /ExtGState <<
+ /EGS9 7 0 R
+ >>
+ >>
+ /StructParents 0
+>>
+endobj
+4 0 obj <<
+ /Length 162
+>>
+stream
+0.1 w
+/Artifact
+BMC
+q
+0 0 612 792 re
+W* n
+EMC
+/Figure<</MCID 0>>
+BDC
+Q
+q
+281 685.3 50 50 re
+W* n
+q
+49.9 0 0 50 281.1 685.4 cm
+/Im7 Do
+Q
+EMC
+Q
+q
+EGS9 gs /Tr8 Do
+Q
+endstream
+endobj
+5 0 obj <<
+ /Type /XObject
+ /Subtype /Form
+ /BBox [-140 395 753 395.1]
+ /Group <<
+ /CS /DeviceRGB
+ /K true
+ /S /Transparency
+ >>
+ /Length 0
+>>
+stream
+endstream
+endobj
+6 0 obj <<
+ /Type /XObject
+ /Subtype /Image
+ /Width 50
+ /Height 50
+ /BitsPerComponent 8
+ /ColorSpace /DeviceRGB
+ /Filter [/ASCIIHexDecode /FlateDecode]
+ /Length 61
+>>
+stream
+789cedc13101000000c2a0f54fed6f06a00000000000000078031d4c0001
+endstream
+endobj
+7 0 obj <<
+ /ca 0.5
+ /CA 0.5
+>>
+endobj
+8 0 obj <<
+ /Type /StructTreeRoot
+ /ParentTree 9 0 R
+ /K [10 0 R]
+ /RoleMap <<
+ /Document /Document
+ /Standard /P
+ /Figure /Figure
+ >>
+>>
+endobj
+9 0 obj <<
+ /Nums [
+ 0
+ [10 0 R 11 0 R 12 0 R 13 0 R 14 0 R 15 0 R 16 0 R 17 0 R]
+ ]
+>>
+endobj
+10 0 obj <<
+ /Type /StructElem
+ /S /Document
+ /K [11 0 R]
+ /P 8 0 R
+ /T (TitleText)
+ /Pg 3 0 R
+ /Lang (en-US)
+>>
+endobj
+11 0 obj <<
+ /Type /StructElem
+ /S /Table
+ /K [12 0 R] % Deliberately left off object 13 0.
+ /P 10 0 R
+ /Pg 3 0 R
+ /A [<<
+ /O /Table
+ /Summary ()
+ >>]
+ /ID (node12)
+ /Lang (hu)
+>>
+endobj
+12 0 obj <<
+ /Type /StructElem
+ /S /TR
+ /K [14 0 R 15 0 R]
+ /P 11 0 R
+ /Pg 3 0 R
+ /ID ()
+>>
+endobj
+13 0 obj <<
+ /Type /StructElem
+ /S /TR
+ /K [16 0 R] % Deliberately left off object 17 0.
+ /P 11 0 R
+ /Pg 3 0 R
+ /A <<
+ /O /Table
+ >>
+ /ID (node14)
+>>
+endobj
+14 0 obj <<
+ /Type /StructElem
+ /S /TH
+ /P 12 0 R
+ /Pg 3 0 R
+ /A [<<
+ /O /Table
+ /Scope /Row
+ >>
+ <<
+ /O /Table
+ /ColSpan 2
+ >>]
+ /ID (node15)
+>>
+endobj
+15 0 obj <<
+ /Type /StructElem
+ /S /TD
+ /P 12 0 R
+ /Pg 3 0 R
+ /ID (node16)
+>>
+endobj
+16 0 obj <<
+ /Type /StructElem
+ /S /TH
+ /P 13 0 R
+ /Pg 3 0 R
+ /A [<<
+ /O /Table
+ /Scope /Row
+ >>]
+ /ID (node17)
+>>
+endobj
+17 0 obj <<
+ /Type /StructElem
+ /S /TD
+ /P 13 0 R
+ /Pg 3 0 R
+ /A [<<
+ /O /Table
+ /ColProp (Sum)
+ /CurUSD true
+ >>]
+ /ID (node18)
+>>
+endobj
+xref
+0 18
+0000000000 65535 f
+0000000015 00000 n
+0000000145 00000 n
+0000000208 00000 n
+0000000556 00000 n
+0000000770 00000 n
+0000000952 00000 n
+0000001212 00000 n
+0000001253 00000 n
+0000001412 00000 n
+0000001515 00000 n
+0000001642 00000 n
+0000001856 00000 n
+0000001961 00000 n
+0000002134 00000 n
+0000002336 00000 n
+0000002426 00000 n
+0000002573 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 18
+>>
+startxref
+2743
+%%EOF
diff --git a/testing/test_loader.cpp b/testing/test_loader.cpp
index aac8429a0..a3fad8a47 100644
--- a/testing/test_loader.cpp
+++ b/testing/test_loader.cpp
@@ -6,7 +6,8 @@
#include <string.h>
-#include "third_party/base/notreached.h"
+#include "third_party/base/check_op.h"
+#include "third_party/base/numerics/checked_math.h"
TestLoader::TestLoader(pdfium::span<const char> span) : m_Span(span) {}
@@ -16,10 +17,9 @@ int TestLoader::GetBlock(void* param,
unsigned char* pBuf,
unsigned long size) {
TestLoader* pLoader = static_cast<TestLoader*>(param);
- if (pos + size < pos || pos + size > pLoader->m_Span.size()) {
- NOTREACHED();
- return 0;
- }
+ pdfium::base::CheckedNumeric<size_t> end = pos;
+ end += size;
+ CHECK_LE(end.ValueOrDie(), pLoader->m_Span.size());
memcpy(pBuf, &pLoader->m_Span[pos], size);
return 1;
diff --git a/testing/test_loader.h b/testing/test_loader.h
index f3d0042c8..d0e83c5c3 100644
--- a/testing/test_loader.h
+++ b/testing/test_loader.h
@@ -5,7 +5,7 @@
#ifndef TESTING_TEST_LOADER_H_
#define TESTING_TEST_LOADER_H_
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
class TestLoader {
public:
diff --git a/testing/tools/BUILD.gn b/testing/tools/BUILD.gn
new file mode 100644
index 000000000..8815b536f
--- /dev/null
+++ b/testing/tools/BUILD.gn
@@ -0,0 +1,47 @@
+# Copyright 2023 The PDFium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("../../pdfium.gni")
+
+if (pdf_is_standalone) {
+ # Generates the list of inputs required by `test_runner.py` tests.
+ action("test_runner_py") {
+ testonly = true
+
+ write_runtime_deps = "${root_out_dir}/${target_name}.runtime_deps"
+
+ sources = [ write_runtime_deps ]
+ outputs = [ "${root_out_dir}/${target_name}.json" ]
+
+ script = "generate_cas_paths.py"
+ args = [
+ "--root",
+ rebase_path("../..", root_build_dir),
+ ] + rebase_path(sources + outputs, root_build_dir)
+
+ # Unbuilt runtime dependencies.
+ data = [
+ ".",
+ "../SUPPRESSIONS",
+ "../SUPPRESSIONS_EXACT_MATCHING",
+ "../SUPPRESSIONS_IMAGE_DIFF",
+ "../corpus/",
+ "../../.vpython3",
+ "../../build/skia_gold_common/",
+ "../../build/util/lib/",
+ "../../third_party/test_fonts/",
+ "../../tools/resultdb/",
+ "../../tools/skia_goldctl/",
+ ]
+
+ # Built runtime dependencies.
+ data_deps = [
+ "../../:pdfium_diff",
+ "../../samples:pdfium_test",
+ ]
+
+ # Force `data_deps` to be built before this target, rather than in parallel.
+ deps = data_deps
+ }
+}
diff --git a/testing/tools/generate_cas_paths.py b/testing/tools/generate_cas_paths.py
new file mode 100644
index 000000000..43690eb94
--- /dev/null
+++ b/testing/tools/generate_cas_paths.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python3
+# Copyright 2023 The PDFium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Tool for converting GN runtime_deps to CAS archive paths."""
+
+import argparse
+from collections import deque
+import filecmp
+import json
+import logging
+from pathlib import Path
+import os
+
+EXCLUDE_DIRS = {
+ '.git',
+ '__pycache__',
+}
+
+
+def parse_runtime_deps(runtime_deps):
+ """Parses GN's `runtime_deps` format."""
+ with runtime_deps:
+ return [line.rstrip() for line in runtime_deps]
+
+
+def resolve_paths(root, initial_paths):
+ """Converts paths to CAS archive paths format."""
+ absolute_root = os.path.abspath(root)
+
+ resolved_paths = []
+ unvisited_paths = deque(map(Path, initial_paths))
+ while unvisited_paths:
+ path = unvisited_paths.popleft()
+
+ if not path.exists():
+ logging.warning('"%(path)s" does not exist', {'path': path})
+ continue
+
+ if path.is_dir():
+ # Expand specific children if any are excluded.
+ child_paths = expand_dir(path)
+ if child_paths:
+ unvisited_paths.extendleft(child_paths)
+ continue
+
+ resolved_paths.append(os.path.relpath(path, start=absolute_root))
+
+ resolved_paths.sort()
+ return [[absolute_root, path] for path in resolved_paths]
+
+
+def expand_dir(path):
+ """Explicitly expands directory if any children are excluded."""
+ expand = False
+ expanded_paths = []
+
+ for child_path in path.iterdir():
+ if child_path.name in EXCLUDE_DIRS and path.is_dir():
+ expand = True
+ continue
+ expanded_paths.append(child_path)
+
+ return expanded_paths if expand else []
+
+
+def replace_output(resolved, output_path):
+ """Atomically replaces the output with the resolved JSON if changed."""
+ new_output_path = output_path + '.new'
+ try:
+ with open(new_output_path, 'w', encoding='ascii') as new_output:
+ json.dump(resolved, new_output)
+
+ if (os.path.exists(output_path) and
+ filecmp.cmp(new_output_path, output_path, shallow=False)):
+ return
+
+ os.replace(new_output_path, output_path)
+ new_output_path = None
+ finally:
+ if new_output_path:
+ os.remove(new_output_path)
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--root')
+ parser.add_argument(
+ 'runtime_deps',
+ help='runtime_deps written by GN',
+ type=argparse.FileType('r', encoding='utf_8'),
+ metavar='input.runtime_deps')
+ parser.add_argument(
+ 'output_json',
+ help='CAS archive paths in JSON format',
+ metavar='output.json')
+ args = parser.parse_args()
+
+ runtime_deps = parse_runtime_deps(args.runtime_deps)
+ resolved_paths = resolve_paths(args.root, runtime_deps)
+ replace_output(resolved_paths, args.output_json)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/testing/tools/pngdiffer.py b/testing/tools/pngdiffer.py
index 2044a3477..ceb402223 100755
--- a/testing/tools/pngdiffer.py
+++ b/testing/tools/pngdiffer.py
@@ -15,8 +15,11 @@ FUZZY_MATCHING = 'fuzzy'
_PNG_OPTIMIZER = 'optipng'
+# Each suffix order acts like a path along a tree, with the leaves being the
+# most specific, and the root being the least specific.
_COMMON_SUFFIX_ORDER = ('_{os}', '')
_AGG_SUFFIX_ORDER = ('_agg_{os}', '_agg') + _COMMON_SUFFIX_ORDER
+_GDI_SUFFIX_ORDER = ('_gdi_{os}', '_gdi') + _COMMON_SUFFIX_ORDER
_SKIA_SUFFIX_ORDER = ('_skia_{os}', '_skia') + _COMMON_SUFFIX_ORDER
@@ -37,14 +40,19 @@ class ImageDiff:
class PNGDiffer():
- def __init__(self, finder, features, reverse_byte_order):
+ def __init__(self, finder, reverse_byte_order, rendering_option):
self.pdfium_diff_path = finder.ExecutablePath('pdfium_diff')
self.os_name = finder.os_name
self.reverse_byte_order = reverse_byte_order
- if 'SKIA' in features:
+
+ if rendering_option == 'agg':
+ self.suffix_order = _AGG_SUFFIX_ORDER
+ elif rendering_option == 'gdi':
+ self.suffix_order = _GDI_SUFFIX_ORDER
+ elif rendering_option == 'skia':
self.suffix_order = _SKIA_SUFFIX_ORDER
else:
- self.suffix_order = _AGG_SUFFIX_ORDER
+ raise ValueError(f'rendering_option={rendering_option}')
def CheckMissingTools(self, regenerate_expected):
if regenerate_expected and not shutil.which(_PNG_OPTIMIZER):
diff --git a/testing/tools/skia_gold/pdfium_skia_gold_properties.py b/testing/tools/skia_gold/pdfium_skia_gold_properties.py
index aeb8ef944..874e643f8 100644
--- a/testing/tools/skia_gold/pdfium_skia_gold_properties.py
+++ b/testing/tools/skia_gold/pdfium_skia_gold_properties.py
@@ -3,25 +3,12 @@
# found in the LICENSE file.
"""PDFium implementation of //build/skia_gold_common/skia_gold_properties.py."""
-import subprocess
-import sys
-
import pdfium_root
from skia_gold_common import skia_gold_properties
class PDFiumSkiaGoldProperties(skia_gold_properties.SkiaGoldProperties):
- @staticmethod
- def _GetGitOriginMainHeadSha1():
+ def _GetGitRepoDirectory(self):
root_finder = pdfium_root.RootDirectoryFinder()
- try:
- return subprocess.check_output(['git', 'rev-parse', 'origin/main'],
- shell=_IsWin(),
- cwd=root_finder.pdfium_root).strip()
- except subprocess.CalledProcessError:
- return None
-
-
-def _IsWin():
- return sys.platform == 'win32'
+ return root_finder.pdfium_root
diff --git a/testing/tools/skia_gold/skia_gold.py b/testing/tools/skia_gold/skia_gold.py
index e3595d2d8..9eb9871d4 100644
--- a/testing/tools/skia_gold/skia_gold.py
+++ b/testing/tools/skia_gold/skia_gold.py
@@ -112,7 +112,6 @@ class SkiaGoldTester:
process_name)
clear_gold_output_dir(self._output_dir)
self._keys = _ParseKeyValuePairs(skia_gold_args.gold_key)
- self._old_gold_props = _ParseKeyValuePairs(skia_gold_args.gold_properties)
self._skia_gold_args = skia_gold_args
self._skia_gold_session_manager = None
self._skia_gold_properties = None
@@ -129,13 +128,6 @@ class SkiaGoldTester:
def GetSkiaGoldProperties(self):
if not self._skia_gold_properties:
- if self._old_gold_props:
- self._skia_gold_args.git_revision = self._old_gold_props['gitHash']
- self._skia_gold_args.gerrit_issue = self._old_gold_props['issue']
- self._skia_gold_args.gerrit_patchset = self._old_gold_props['patchset']
- self._skia_gold_args.buildbucket_id = \
- self._old_gold_props['buildbucket_build_id']
-
if self._skia_gold_args.local_pixel_tests is None:
self._skia_gold_args.local_pixel_tests = 'SWARMING_SERVER' \
not in os.environ
diff --git a/testing/tools/suppressor.py b/testing/tools/suppressor.py
index 989f4dd00..6fea73571 100755
--- a/testing/tools/suppressor.py
+++ b/testing/tools/suppressor.py
@@ -11,10 +11,11 @@ import pngdiffer
class Suppressor:
- def __init__(self, finder, features, js_disabled, xfa_disabled):
+ def __init__(self, finder, features, js_disabled, xfa_disabled,
+ rendering_option):
self.has_v8 = not js_disabled and 'V8' in features
self.has_xfa = not js_disabled and not xfa_disabled and 'XFA' in features
- self.has_skia = 'SKIA' in features
+ self.rendering_option = rendering_option
self.suppression_set = self._LoadSuppressedSet('SUPPRESSIONS', finder)
self.image_suppression_set = self._LoadSuppressedSet(
'SUPPRESSIONS_IMAGE_DIFF', finder)
@@ -24,11 +25,10 @@ class Suppressor:
def _LoadSuppressedSet(self, suppressions_filename, finder):
v8_option = "v8" if self.has_v8 else "nov8"
xfa_option = "xfa" if self.has_xfa else "noxfa"
- rendering_option = "skia" if self.has_skia else "agg"
with open(os.path.join(finder.TestingDir(), suppressions_filename)) as f:
return set(
- self._FilterSuppressions(common.os_name(), v8_option,
- xfa_option, rendering_option,
+ self._FilterSuppressions(common.os_name(), v8_option, xfa_option,
+ self.rendering_option,
self._ExtractSuppressions(f)))
def _ExtractSuppressions(self, f):
diff --git a/testing/tools/test_runner.py b/testing/tools/test_runner.py
index ad348aa3c..c7f8aa783 100644
--- a/testing/tools/test_runner.py
+++ b/testing/tools/test_runner.py
@@ -93,8 +93,7 @@ class TestRunner:
if test_result.reason:
print(f'Failure reason: {test_result.reason}')
if test_result.log:
- decoded_log = bytes.decode(test_result.log, errors='backslashreplace')
- print(f'Test output:\n{decoded_log}')
+ print(f'Test output:\n{test_result.log}')
for artifact in test_result.image_artifacts:
if artifact.skia_gold_status == result_types.FAIL:
print(f'Failed Skia Gold: {artifact.image_path}')
@@ -200,19 +199,6 @@ class TestRunner:
default=False,
help='When flag is on, skia gold tests will be run.')
- # TODO: Remove when pdfium recipe stops passing this argument
- parser.add_argument(
- '--gold_properties',
- default='',
- help='Key value pairs that are written to the top level of the JSON '
- 'file that is ingested by Gold.')
-
- # TODO: Remove when pdfium recipe stops passing this argument
- parser.add_argument(
- '--gold_ignore_hashes',
- default='',
- help='Path to a file with MD5 hashes we wish to ignore.')
-
parser.add_argument(
'--regenerate_expected',
action='store_true',
@@ -235,6 +221,11 @@ class TestRunner:
'when image comparison fails.')
parser.add_argument(
+ '--use-renderer',
+ choices=('agg', 'gdi', 'skia'),
+ help='Forces the renderer to use.')
+
+ parser.add_argument(
'inputted_file_paths',
nargs='*',
help='Path to test files to run, relative to '
@@ -252,7 +243,11 @@ class TestRunner:
print(f"FAILURE: Can't find test executable '{pdfium_test_path}'")
print('Use --build-dir to specify its location.')
return 1
- self.per_process_config.InitializeFeatures(pdfium_test_path)
+
+ error_message = self.per_process_config.InitializeFeatures(pdfium_test_path)
+ if error_message:
+ print('FAILURE:', error_message)
+ return 1
self.per_process_state = _PerProcessState(self.per_process_config)
shutil.rmtree(self.per_process_state.working_dir, ignore_errors=True)
@@ -431,14 +426,16 @@ class _PerProcessConfig:
delete_output_on_success: Whether to delete output on success.
enforce_expected_images: Whether to enforce expected images.
options: The dictionary of command line options.
- features: The list of features supported by `pdfium_test`.
+ features: The set of features supported by `pdfium_test`.
+ rendering_option: The renderer to use (agg, gdi, or skia).
"""
test_dir: str
test_type: str
delete_output_on_success: bool = False
enforce_expected_images: bool = False
options: dict = None
- features: list = None
+ features: set = None
+ rendering_option: str = None
def NewFinder(self):
return common.DirectoryFinder(self.options.build_dir)
@@ -449,7 +446,25 @@ class _PerProcessConfig:
def InitializeFeatures(self, pdfium_test_path):
output = subprocess.check_output([pdfium_test_path, '--show-config'],
timeout=TEST_TIMEOUT)
- self.features = output.decode('utf-8').strip().split(',')
+ self.features = set(output.decode('utf-8').strip().split(','))
+
+ if 'SKIA' in self.features:
+ self.rendering_option = 'skia'
+ else:
+ self.rendering_option = 'agg'
+
+ if self.options.use_renderer == 'agg':
+ self.rendering_option = 'agg'
+ elif self.options.use_renderer == 'gdi':
+ if 'GDI' not in self.features:
+ return 'pdfium_test does not support the GDI renderer'
+ self.rendering_option = 'gdi'
+ elif self.options.use_renderer == 'skia':
+ if 'SKIA' not in self.features:
+ return 'pdfium_test does not support the Skia renderer'
+ self.rendering_option = 'skia'
+
+ return None
class _PerProcessState:
@@ -475,9 +490,10 @@ class _PerProcessState:
self.test_suppressor = suppressor.Suppressor(
finder, self.features, self.options.disable_javascript,
- self.options.disable_xfa)
- self.image_differ = pngdiffer.PNGDiffer(finder, self.features,
- self.options.reverse_byte_order)
+ self.options.disable_xfa, config.rendering_option)
+ self.image_differ = pngdiffer.PNGDiffer(finder,
+ self.options.reverse_byte_order,
+ config.rendering_option)
self.process_name = multiprocessing.current_process().name
self.skia_tester = None
@@ -598,6 +614,7 @@ class _TestCaseRunner:
test_result.log = run_result.stdout
else:
test_result.log = run_result.stderr
+ test_result.log = test_result.log.decode(errors='backslashreplace')
return test_result
def GenerateAndTest(self, test_function):
@@ -678,7 +695,9 @@ class _TestCaseRunner:
if txt_data:
return self.test_case.NewResult(
- result_types.FAIL, log=txt_data, reason=f'{txt_path} should be empty')
+ result_types.FAIL,
+ log=txt_data.decode(errors='backslashreplace'),
+ reason=f'{txt_path} should be empty')
return self.test_case.NewResult(result_types.PASS)
@@ -714,6 +733,9 @@ class _TestCaseRunner:
if self.options.reverse_byte_order:
cmd_to_run.append('--reverse-byte-order')
+ if self.options.use_renderer:
+ cmd_to_run.append(f'--use-renderer={self.options.use_renderer}')
+
cmd_to_run.append(self.pdf_path)
with BytesIO() as command_output:
@@ -754,7 +776,7 @@ class _TestCaseRunner:
for artifact in test_result.image_artifacts:
artifact.image_diff = diff_map.get(artifact.image_path)
- test_result.log = ''.join(diff_log).encode()
+ test_result.log = ''.join(diff_log)
elif _per_process_state.enforce_expected_images:
if not self.IsImageDiffSuppressed():
diff --git a/testing/unit_test_main.cpp b/testing/unit_test_main.cpp
index 16e8f0fb1..28476b032 100644
--- a/testing/unit_test_main.cpp
+++ b/testing/unit_test_main.cpp
@@ -7,6 +7,10 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/pdf_test_environment.h"
+#if defined(PDF_USE_PARTITION_ALLOC)
+#include "testing/allocator_shim_config.h"
+#endif
+
#ifdef PDF_ENABLE_V8
#include "testing/v8_test_environment.h"
#ifdef PDF_ENABLE_XFA
@@ -17,6 +21,10 @@
// Can't use gtest-provided main since we need to initialize partition
// alloc before invoking any test, and add test environments.
int main(int argc, char** argv) {
+#if defined(PDF_USE_PARTITION_ALLOC)
+ pdfium::ConfigurePartitionAllocShimPartitionForTest();
+#endif // defined(PDF_USE_PARTITION_ALLOC)
+
FX_InitializeMemoryAllocators();
// PDF test environment will be deleted by gtest.
diff --git a/testing/utils/hash.h b/testing/utils/hash.h
index c2164e8d2..e5089939e 100644
--- a/testing/utils/hash.h
+++ b/testing/utils/hash.h
@@ -7,7 +7,7 @@
#include <string>
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
std::string CryptToBase16(const uint8_t* digest);
std::string GenerateMD5Base16(pdfium::span<const uint8_t> data);
diff --git a/third_party/BUILD.gn b/third_party/BUILD.gn
index 534b3b800..3683ab858 100644
--- a/third_party/BUILD.gn
+++ b/third_party/BUILD.gn
@@ -8,16 +8,6 @@ import("//build/config/mips.gni")
import("//build_overrides/build.gni")
import("../pdfium.gni")
-group("third_party") {
- deps = [
- ":pdfium_base",
- ":skia_shared",
- ]
- if (pdf_bundle_freetype) {
- deps += [ ":fx_freetype" ]
- }
-}
-
config("pdfium_third_party_config") {
configs = [
"..:pdfium_common_config",
@@ -218,7 +208,7 @@ if (is_linux || is_chromeos) {
}
config("fx_agg_warnings") {
- visibility = [ ":*" ]
+ visibility = [ ":fx_agg" ]
if (is_clang) {
# calc_butt_cap() in agg_vcgen_stroke.cpp is unused.
cflags = [ "-Wno-unused-function" ]
@@ -234,21 +224,33 @@ source_set("fx_agg") {
":fx_agg_warnings",
]
sources = [
+ "agg23/agg_array.h",
"agg23/agg_basics.h",
"agg23/agg_clip_liang_barsky.h",
+ "agg23/agg_color_gray.h",
+ "agg23/agg_conv_adaptor_vcgen.h",
"agg23/agg_conv_dash.h",
"agg23/agg_conv_stroke.h",
"agg23/agg_curves.cpp",
"agg23/agg_curves.h",
+ "agg23/agg_math.h",
+ "agg23/agg_math_stroke.h",
"agg23/agg_path_storage.cpp",
"agg23/agg_path_storage.h",
+ "agg23/agg_pixfmt_gray.h",
"agg23/agg_rasterizer_scanline_aa.cpp",
"agg23/agg_rasterizer_scanline_aa.h",
+ "agg23/agg_render_scanlines.h",
+ "agg23/agg_renderer_base.h",
"agg23/agg_renderer_scanline.h",
"agg23/agg_rendering_buffer.h",
"agg23/agg_scanline_u.h",
+ "agg23/agg_shorten_path.h",
"agg23/agg_vcgen_dash.cpp",
+ "agg23/agg_vcgen_dash.h",
"agg23/agg_vcgen_stroke.cpp",
+ "agg23/agg_vcgen_stroke.h",
+ "agg23/agg_vertex_sequence.h",
]
deps = [ "../core/fxcrt" ]
}
@@ -546,12 +548,13 @@ source_set("pdfium_base") {
"base/component_export.h",
"base/containers/adapters.h",
"base/containers/contains.h",
- "base/cxx17_backports.h",
+ "base/containers/span.h",
"base/debug/alias.cc",
"base/debug/alias.h",
"base/immediate_crash.h",
"base/memory/aligned_memory.cc",
"base/memory/aligned_memory.h",
+ "base/memory/ptr_util.h",
"base/no_destructor.h",
"base/notreached.h",
"base/numerics/checked_math.h",
@@ -565,7 +568,6 @@ source_set("pdfium_base") {
"base/numerics/safe_math_arm_impl.h",
"base/numerics/safe_math_clang_gcc_impl.h",
"base/numerics/safe_math_shared_impl.h",
- "base/span.h",
"base/sys_byteorder.h",
"base/template_util.h",
]
@@ -599,14 +601,3 @@ source_set("pdfium_base_test_support") {
deps += [ "//testing/gtest" ]
}
}
-
-source_set("skia_shared") {
- sources = [
- "skia_shared/SkFloatToDecimal.cpp",
- "skia_shared/SkFloatToDecimal.h",
- ]
- configs += [
- "../:pdfium_strict_config",
- "../:pdfium_noshorten_config",
- ]
-}
diff --git a/third_party/NotoSansCJK/README.pdfium b/third_party/NotoSansCJK/README.pdfium
index 80b1d091b..5c8ba5aeb 100644
--- a/third_party/NotoSansCJK/README.pdfium
+++ b/third_party/NotoSansCJK/README.pdfium
@@ -4,6 +4,7 @@ Version: Noto Sans CJK V2.001
License: SIL Open Font License v1.1
License File: LICENSE
Security Critical: no
+Shipped: no
Description:
NotoSansSC-Regular.subset.otf contains a subset of NotoSansSC-Regular font.
diff --git a/third_party/agg23/0015-include-string-h.patch b/third_party/agg23/0015-include-string-h.patch
new file mode 100644
index 000000000..dcbec5626
--- /dev/null
+++ b/third_party/agg23/0015-include-string-h.patch
@@ -0,0 +1,26 @@
+diff --git a/third_party/agg23/agg_array.h b/third_party/agg23/agg_array.h
+index b82d95296..ed22c40e9 100644
+--- a/third_party/agg23/agg_array.h
++++ b/third_party/agg23/agg_array.h
+@@ -16,6 +16,8 @@
+ #ifndef AGG_ARRAY_INCLUDED
+ #define AGG_ARRAY_INCLUDED
+
++#include <string.h>
++
+ #include "agg_basics.h"
+ #include "core/fxcrt/fx_memory.h" // For FXSYS_* macros.
+
+diff --git a/third_party/agg23/agg_path_storage.cpp b/third_party/agg23/agg_path_storage.cpp
+index 2981e9c0c..d4225124d 100644
+--- a/third_party/agg23/agg_path_storage.cpp
++++ b/third_party/agg23/agg_path_storage.cpp
+@@ -25,6 +25,8 @@
+
+ #include "agg_path_storage.h"
+
++#include <string.h>
++
+ #include "agg_math.h"
+ #include "core/fxcrt/fx_memory.h"
+
diff --git a/third_party/agg23/README.pdfium b/third_party/agg23/README.pdfium
index 1b8393280..b8286cff2 100644
--- a/third_party/agg23/README.pdfium
+++ b/third_party/agg23/README.pdfium
@@ -3,6 +3,7 @@ URL: https://sourceforge.net/projects/agg/
Version: 2.3
Security Critical: yes
License: MIT
+Shipped: yes
Description:
2D vector graphics library.
@@ -32,3 +33,4 @@ shadow variable.
0013-cxx20.patch: C++20 support.
0014-ubsan-render-line.patch: Fix some integer overflows in
outline_aa::render_line().
+0015-include-string-h.patch: IWYU for <string.h> \ No newline at end of file
diff --git a/third_party/agg23/agg_array.h b/third_party/agg23/agg_array.h
index b82d95296..ed22c40e9 100644
--- a/third_party/agg23/agg_array.h
+++ b/third_party/agg23/agg_array.h
@@ -16,6 +16,8 @@
#ifndef AGG_ARRAY_INCLUDED
#define AGG_ARRAY_INCLUDED
+#include <string.h>
+
#include "agg_basics.h"
#include "core/fxcrt/fx_memory.h" // For FXSYS_* macros.
diff --git a/third_party/agg23/agg_path_storage.cpp b/third_party/agg23/agg_path_storage.cpp
index 2981e9c0c..d4225124d 100644
--- a/third_party/agg23/agg_path_storage.cpp
+++ b/third_party/agg23/agg_path_storage.cpp
@@ -25,6 +25,8 @@
#include "agg_path_storage.h"
+#include <string.h>
+
#include "agg_math.h"
#include "core/fxcrt/fx_memory.h"
diff --git a/third_party/android_sdk/BUILD.gn b/third_party/android_sdk/BUILD.gn
deleted file mode 100644
index da970c374..000000000
--- a/third_party/android_sdk/BUILD.gn
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 2019 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.
-
-import("//build/config/android/rules.gni")
-
-config("cpu_features_include") {
- include_dirs = [ "$android_ndk_root/sources/android/cpufeatures" ]
-}
-
-config("cpu_features_warnings") {
- if (is_clang) {
- # cpu-features.c has few unused functions on x86 b/26403333
- cflags = [ "-Wno-unused-function" ]
- }
-}
-
-source_set("cpu_features") {
- sources = [ "$android_ndk_root/sources/android/cpufeatures/cpu-features.c" ]
- public_configs = [ ":cpu_features_include" ]
-
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [
- "//build/config/compiler:no_chromium_code",
-
- # Must be after no_chromium_code for warning flags to be ordered correctly.
- ":cpu_features_warnings",
- ]
-}
diff --git a/third_party/base/span.h b/third_party/base/containers/span.h
index cc980ba67..660d92c22 100644
--- a/third_party/base/span.h
+++ b/third_party/base/containers/span.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef THIRD_PARTY_BASE_SPAN_H_
-#define THIRD_PARTY_BASE_SPAN_H_
+#ifndef THIRD_PARTY_BASE_CONTAINERS_SPAN_H_
+#define THIRD_PARTY_BASE_CONTAINERS_SPAN_H_
#include <stddef.h>
@@ -200,16 +200,28 @@ class TRIVIAL_ABI GSL_POINTER span {
constexpr span(std::array<T, N>& array) noexcept : span(array.data(), N) {}
// Conversion from a container that provides |T* data()| and |integral_type
- // size()|.
+ // size()|. Note that |data()| may not return nullptr for some empty
+ // containers, which can lead to container overflow errors when probing
+ // unowned ptrs.
+#if defined(ADDRESS_SANITIZER) && defined(UNOWNED_PTR_IS_BASE_RAW_PTR)
+ template <typename Container,
+ typename = internal::EnableIfSpanCompatibleContainer<Container, T>>
+ constexpr span(Container& container)
+ : span(container.size() ? container.data() : nullptr, container.size()) {}
+#else
template <typename Container,
typename = internal::EnableIfSpanCompatibleContainer<Container, T>>
constexpr span(Container& container)
: span(container.data(), container.size()) {}
+#endif
+
template <
typename Container,
typename = internal::EnableIfConstSpanCompatibleContainer<Container, T>>
span(const Container& container) : span(container.data(), container.size()) {}
+
constexpr span(const span& other) noexcept = default;
+
// Conversions from spans of compatible types: this allows a span<T> to be
// seamlessly used as a span<const T>, but not the other way around.
template <typename U, typename = internal::EnableIfLegalSpanConversion<U, T>>
@@ -288,13 +300,19 @@ class TRIVIAL_ABI GSL_POINTER span {
private:
void ReleaseEmptySpan() noexcept {
+#if defined(ADDRESS_SANITIZER) && !defined(UNOWNED_PTR_IS_BASE_RAW_PTR)
// Empty spans might point to byte N+1 of a N-byte object, legal for
// C pointers but not UnownedPtrs.
if (!size_)
data_.ReleaseBadPointer();
+#endif
}
+#if defined(UNOWNED_PTR_IS_BASE_RAW_PTR)
+ raw_ptr<T, AllowPtrArithmetic> data_ = nullptr;
+#else
UnownedPtr<T> data_;
+#endif
size_t size_;
};
@@ -377,4 +395,4 @@ constexpr span<T> make_span(const Container& container) {
} // namespace pdfium
-#endif // THIRD_PARTY_BASE_SPAN_H_
+#endif // THIRD_PARTY_BASE_CONTAINERS_SPAN_H_
diff --git a/third_party/base/cxx17_backports.h b/third_party/base/cxx17_backports.h
deleted file mode 100644
index 0672331c5..000000000
--- a/third_party/base/cxx17_backports.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2021 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 THIRD_PARTY_BASE_CXX17_BACKPORTS_H_
-#define THIRD_PARTY_BASE_CXX17_BACKPORTS_H_
-
-#include <stddef.h>
-
-#include <functional>
-
-#include "third_party/base/check.h"
-
-namespace pdfium {
-
-// C++14 implementation of C++17's std::clamp():
-// https://en.cppreference.com/w/cpp/algorithm/clamp
-// Please note that the C++ spec makes it undefined behavior to call std::clamp
-// with a value of `lo` that compares greater than the value of `hi`. This
-// implementation uses a CHECK to enforce this as a hard restriction.
-template <typename T, typename Compare>
-constexpr const T& clamp(const T& v, const T& lo, const T& hi, Compare comp) {
- CHECK(!comp(hi, lo));
- return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
-}
-
-template <typename T>
-constexpr const T& clamp(const T& v, const T& lo, const T& hi) {
- return pdfium::clamp(v, lo, hi, std::less<T>{});
-}
-
-} // namespace pdfium
-
-#endif // THIRD_PARTY_BASE_CXX17_BACKPORTS_H_
diff --git a/third_party/base/ptr_util.h b/third_party/base/memory/ptr_util.h
index 3be55b43a..c9df8316e 100644
--- a/third_party/base/ptr_util.h
+++ b/third_party/base/memory/ptr_util.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef THIRD_PARTY_BASE_PTR_UTIL_H_
-#define THIRD_PARTY_BASE_PTR_UTIL_H_
+#ifndef THIRD_PARTY_BASE_MEMORY_PTR_UTIL_H_
+#define THIRD_PARTY_BASE_MEMORY_PTR_UTIL_H_
#include <memory>
@@ -19,4 +19,4 @@ std::unique_ptr<T> WrapUnique(T* ptr) {
} // namespace pdfium
-#endif // THIRD_PARTY_BASE_PTR_UTIL_H_
+#endif // THIRD_PARTY_BASE_MEMORY_PTR_UTIL_H_
diff --git a/third_party/base/numerics/README.pdfium b/third_party/base/numerics/README.pdfium
index 8d73ef3ff..c1ad6be71 100644
--- a/third_party/base/numerics/README.pdfium
+++ b/third_party/base/numerics/README.pdfium
@@ -1,3 +1,5 @@
+Shipped: yes
+
Description:
Chromium's safe numerics library
diff --git a/third_party/cpu_features/BUILD.gn b/third_party/cpu_features/BUILD.gn
new file mode 100644
index 000000000..8f1c8dcef
--- /dev/null
+++ b/third_party/cpu_features/BUILD.gn
@@ -0,0 +1,61 @@
+# Copyright 2023 The PDFium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+config("cpu_features_config") {
+ cflags = [ "-Wno-unused-function" ]
+ defines = [
+ "STACK_LINE_READER_BUFFER_SIZE=1024",
+ "HAVE_STRONG_GETAUXVAL",
+ ]
+ include_dirs = [ "src/include" ]
+}
+
+config("ndk_compat_headers") {
+ include_dirs = [ "src/ndk_compat" ]
+}
+
+source_set("cpuinfo") {
+ sources = [
+ "src/src/copy.inl",
+ "src/src/define_introspection.inl",
+ "src/src/define_introspection_and_hwcaps.inl",
+ "src/src/equals.inl",
+ "src/src/filesystem.c",
+ "src/src/hwcaps.c",
+ "src/src/stack_line_reader.c",
+ "src/src/string_view.c",
+ ]
+ if (current_cpu == "x86" || current_cpu == "x64") {
+ sources += [
+ "src/src/impl_x86__base_implementation.inl",
+ "src/src/impl_x86_freebsd.c",
+ "src/src/impl_x86_linux_or_android.c",
+ "src/src/impl_x86_macos.c",
+ "src/src/impl_x86_windows.c",
+ ]
+ } else if (current_cpu == "arm") {
+ sources += [ "src/src/impl_arm_linux_or_android.c" ]
+ } else if (current_cpu == "arm64") {
+ sources += [ "src/src/impl_aarch64_linux_or_android.c" ]
+ } else if (current_cpu == "mips") {
+ sources += [ "src/src/impl_mips_linux_or_android.c" ]
+ } else if (current_cpu == "ppc") {
+ sources += [ "src/src/impl_ppc_linux.c" ]
+ } else if (current_cpu == "riscv64") {
+ sources += [ "src/src/impl_riscv_linux.c" ]
+ } else {
+ error("Missing definition for architecture: $current_cpu")
+ }
+ configs += [ ":cpu_features_config" ]
+}
+
+source_set("ndk_compat") {
+ sources = [
+ "src/ndk_compat/cpu-features.c",
+ "src/ndk_compat/cpu-features.h",
+ ]
+ configs += [ ":cpu_features_config" ]
+ public_configs = [ ":ndk_compat_headers" ]
+ deps = [ ":cpuinfo" ]
+}
diff --git a/third_party/cpu_features/README.pdfium b/third_party/cpu_features/README.pdfium
new file mode 100644
index 000000000..a0c12d6cc
--- /dev/null
+++ b/third_party/cpu_features/README.pdfium
@@ -0,0 +1,15 @@
+Name: cpu_features
+Short Name: cpu_features
+URL: https://github.com/google/cpu_features
+Version: v0.8.0
+Date: 2023/05/17
+License: Apache 2.0
+License File: src/LICENSE
+Security Critical: yes
+Shipped: no
+
+Description:
+cpu_features is a library to retrieve CPU features at runtime. It is used to
+make decisions about performance optimization and features a drop-in replacement
+for Android's cpu-features.h. It is Android's recommended replacement for libraries
+that utilize cpu-features.h.
diff --git a/third_party/freetype/README.pdfium b/third_party/freetype/README.pdfium
index 24ea087dd..22fdfc9f8 100644
--- a/third_party/freetype/README.pdfium
+++ b/third_party/freetype/README.pdfium
@@ -1,9 +1,10 @@
Name: FreeType
URL: http://www.freetype.org/
-Version: VER-2-13-0-65
-Revision: b0a4f99278aa7e14bd1d0d9e40ad28dce543fde6
-CPEPrefix: cpe:/a:freetype:freetype:2.13.0
+Version: VER-2-13-1-15
+Revision: b2584c738f1a92e6369890cff0504cc044315b38
+CPEPrefix: cpe:/a:freetype:freetype:2.13.1
Security Critical: yes
+Shipped: yes
License: FreeType License (FTL)
License File: FTL.TXT
diff --git a/third_party/fuchsia-sdk/README.chromium b/third_party/fuchsia-sdk/README.chromium
index 613c9747a..4bdbe9976 100644
--- a/third_party/fuchsia-sdk/README.chromium
+++ b/third_party/fuchsia-sdk/README.chromium
@@ -2,6 +2,7 @@ Name: Fuchsia SDK
URL: https://fuchsia.dev/fuchsia-src/development/sdk/download
Version: 0
Security Critical: yes
+Shipped: yes
License: BSD 3-Clause, Apache 2.0, MIT
License File: sdk/LICENSE
diff --git a/third_party/googletest/BUILD.gn b/third_party/googletest/BUILD.gn
index 02f0ff842..fb7b18202 100644
--- a/third_party/googletest/BUILD.gn
+++ b/third_party/googletest/BUILD.gn
@@ -61,6 +61,7 @@ config("gmock_config") {
source_set("gtest") {
testonly = true
sources = [
+ "custom/gtest/internal/custom/gtest-printers.h",
"custom/gtest/internal/custom/gtest.h",
"custom/gtest/internal/custom/stack_trace_getter.cc",
"custom/gtest/internal/custom/stack_trace_getter.h",
@@ -127,7 +128,6 @@ source_set("gtest") {
]
deps = []
- public_deps = []
if (is_fuchsia) {
deps += [
diff --git a/third_party/googletest/README.pdfium b/third_party/googletest/README.pdfium
index bd2d36a68..f3ea2de4a 100644
--- a/third_party/googletest/README.pdfium
+++ b/third_party/googletest/README.pdfium
@@ -3,7 +3,7 @@ Short Name: googletest
URL: https://github.com/google/googletest.git
Version: 1.8.0.git-a45c24ac1878932e0dc5fbc0d78a699befd386d3
License: BSD
-License File: NOT_SHIPPED
+Shipped: no
Security critical: no
Google Test is imported as-is, to facilitate version bumping. However, the
diff --git a/third_party/googletest/custom/gtest/internal/custom/gtest-printers.h b/third_party/googletest/custom/gtest/internal/custom/gtest-printers.h
new file mode 100644
index 000000000..523dc1477
--- /dev/null
+++ b/third_party/googletest/custom/gtest/internal/custom/gtest-printers.h
@@ -0,0 +1,35 @@
+// Copyright 2023 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
+#define THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
+
+#include <string>
+
+namespace fxcrt {
+class ByteString;
+}
+
+namespace testing {
+
+// If a C string is compared with a PDFium string object, then it is meant to
+// point to a NUL-terminated string, and thus print it as a string.
+
+#define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \
+ template <> \
+ class internal::FormatForComparison<CharType*, OtherStringType> { \
+ public: \
+ static std::string Format(CharType* value) { \
+ return ::testing::PrintToString(value); \
+ } \
+ }
+
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, fxcrt::ByteString);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, fxcrt::ByteString);
+
+#undef GTEST_IMPL_FORMAT_C_STRING_AS_STRING_
+
+} // namespace testing
+
+#endif // THIRD_PARTY_GOOGLETEST_CUSTOM_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
diff --git a/third_party/lcms/0035-func-ptr-mixup.patch b/third_party/lcms/0035-func-ptr-mixup.patch
new file mode 100644
index 000000000..8232e21cc
--- /dev/null
+++ b/third_party/lcms/0035-func-ptr-mixup.patch
@@ -0,0 +1,29 @@
+diff --git a/third_party/lcms/src/cmsopt.c b/third_party/lcms/src/cmsopt.c
+index e3212fb4d..a5475709b 100644
+--- a/third_party/lcms/src/cmsopt.c
++++ b/third_party/lcms/src/cmsopt.c
+@@ -100,6 +100,15 @@ typedef struct {
+
+ } Curves16Data;
+
++// A simple adapter to prevent _cmsPipelineEval16Fn vs. _cmsInterpFn16
++// confusion, which trips up UBSAN.
++static
++void Lerp16Adapter(CMSREGISTER const cmsUInt16Number in[],
++ CMSREGISTER cmsUInt16Number out[],
++ const void* data) {
++ cmsInterpParams* params = (cmsInterpParams*)data;
++ params->Interpolation.Lerp16(in, out, params);
++}
+
+ // Simple optimizations ----------------------------------------------------------------------------------------------------------
+
+@@ -805,7 +814,7 @@ Error:
+
+ if (DataSetIn == NULL && DataSetOut == NULL) {
+
+- _cmsPipelineSetOptimizationParameters(Dest, (_cmsPipelineEval16Fn) DataCLUT->Params->Interpolation.Lerp16, DataCLUT->Params, NULL, NULL);
++ _cmsPipelineSetOptimizationParameters(Dest, Lerp16Adapter, DataCLUT->Params, NULL, NULL);
+ }
+ else {
+
diff --git a/third_party/lcms/README.pdfium b/third_party/lcms/README.pdfium
index b71c6f29a..ad9383538 100644
--- a/third_party/lcms/README.pdfium
+++ b/third_party/lcms/README.pdfium
@@ -2,6 +2,7 @@ Name: Little CMS
URL: http://www.littlecms.com/
Version: 2.15
Security Critical: yes
+Shipped: yes
License: MIT License
Description:
@@ -20,3 +21,4 @@ Local Modifications:
0030-const-data.patch: Mark many data structures as const.
0033-opt-integer-overflow.patch: Protect against integer overflow.
0034-dead-code.patch: Remove dead code.
+0035-func-ptr-mixup.patch: Prevent mixing up function pointer types.
diff --git a/third_party/lcms/src/cmsopt.c b/third_party/lcms/src/cmsopt.c
index e3212fb4d..a5475709b 100644
--- a/third_party/lcms/src/cmsopt.c
+++ b/third_party/lcms/src/cmsopt.c
@@ -100,6 +100,15 @@ typedef struct {
} Curves16Data;
+// A simple adapter to prevent _cmsPipelineEval16Fn vs. _cmsInterpFn16
+// confusion, which trips up UBSAN.
+static
+void Lerp16Adapter(CMSREGISTER const cmsUInt16Number in[],
+ CMSREGISTER cmsUInt16Number out[],
+ const void* data) {
+ cmsInterpParams* params = (cmsInterpParams*)data;
+ params->Interpolation.Lerp16(in, out, params);
+}
// Simple optimizations ----------------------------------------------------------------------------------------------------------
@@ -805,7 +814,7 @@ Error:
if (DataSetIn == NULL && DataSetOut == NULL) {
- _cmsPipelineSetOptimizationParameters(Dest, (_cmsPipelineEval16Fn) DataCLUT->Params->Interpolation.Lerp16, DataCLUT->Params, NULL, NULL);
+ _cmsPipelineSetOptimizationParameters(Dest, Lerp16Adapter, DataCLUT->Params, NULL, NULL);
}
else {
diff --git a/third_party/libopenjpeg/0046-func-ptr-mixup.patch b/third_party/libopenjpeg/0046-func-ptr-mixup.patch
new file mode 100644
index 000000000..f60e5506f
--- /dev/null
+++ b/third_party/libopenjpeg/0046-func-ptr-mixup.patch
@@ -0,0 +1,1449 @@
+diff --git a/third_party/libopenjpeg/j2k.c b/third_party/libopenjpeg/j2k.c
+index 9b06e7ec8..e2e048760 100644
+--- a/third_party/libopenjpeg/j2k.c
++++ b/third_party/libopenjpeg/j2k.c
+@@ -6685,8 +6685,9 @@ static OPJ_BOOL opj_j2k_read_cpf(opj_j2k_t *p_j2k,
+ /* J2K / JPT decoder interface */
+ /* ----------------------------------------------------------------------- */
+
+-void opj_j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters)
++void opj_j2k_setup_decoder(void *p_j2k, opj_dparameters_t *parameters)
+ {
++ opj_j2k_t* j2k = (opj_j2k_t*)p_j2k;
+ 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;
+@@ -6700,15 +6701,17 @@ void opj_j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters)
+ }
+ }
+
+-void opj_j2k_decoder_set_strict_mode(opj_j2k_t *j2k, OPJ_BOOL strict)
++void opj_j2k_decoder_set_strict_mode(void *p_j2k, OPJ_BOOL strict)
+ {
++ opj_j2k_t* j2k = (opj_j2k_t*)p_j2k;
+ if (j2k) {
+ j2k->m_cp.strict = strict;
+ }
+ }
+
+-OPJ_BOOL opj_j2k_set_threads(opj_j2k_t *j2k, OPJ_UINT32 num_threads)
++OPJ_BOOL opj_j2k_set_threads(void *p_j2k, OPJ_UINT32 num_threads)
+ {
++ opj_j2k_t* j2k = (opj_j2k_t*)p_j2k;
+ /* Currently we pass the thread-pool to the tcd, so we cannot re-set it */
+ /* afterwards */
+ if (opj_has_thread_support() && j2k->m_tcd == NULL) {
+@@ -7613,11 +7616,12 @@ static OPJ_BOOL opj_j2k_is_imf_compliant(opj_cparameters_t *parameters,
+ }
+
+
+-OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k,
++OPJ_BOOL opj_j2k_setup_encoder(void *p_j2k,
+ opj_cparameters_t *parameters,
+ opj_image_t *image,
+ opj_event_mgr_t * p_manager)
+ {
++ opj_j2k_t* j2k = (opj_j2k_t*)p_j2k;
+ OPJ_UINT32 i, j, tileno, numpocs_tile;
+ opj_cp_t *cp = 00;
+ OPJ_UINT32 cblkw, cblkh;
+@@ -7666,10 +7670,10 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k,
+ return OPJ_FALSE;
+ }
+
+- p_j2k->m_specific_param.m_encoder.m_nb_comps = image->numcomps;
++ j2k->m_specific_param.m_encoder.m_nb_comps = image->numcomps;
+
+ /* keep a link to cp so that we can destroy it later in j2k_destroy_compress */
+- cp = &(p_j2k->m_cp);
++ cp = &(j2k->m_cp);
+
+ /* set default values for cp */
+ cp->tw = 1;
+@@ -7834,7 +7838,7 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k,
+ }
+
+ if (OPJ_IS_CINEMA(parameters->rsiz) || OPJ_IS_IMF(parameters->rsiz)) {
+- p_j2k->m_specific_param.m_encoder.m_TLM = OPJ_TRUE;
++ j2k->m_specific_param.m_encoder.m_TLM = OPJ_TRUE;
+ }
+
+ /* Manage profiles and applications and set RSIZ */
+@@ -8379,7 +8383,7 @@ static OPJ_BOOL opj_j2k_add_tlmarker(OPJ_UINT32 tileno,
+ * -----------------------------------------------------------------------
+ */
+
+-OPJ_BOOL opj_j2k_end_decompress(opj_j2k_t *p_j2k,
++OPJ_BOOL opj_j2k_end_decompress(void *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager
+ )
+@@ -8391,10 +8395,11 @@ OPJ_BOOL opj_j2k_end_decompress(opj_j2k_t *p_j2k,
+ }
+
+ OPJ_BOOL opj_j2k_read_header(opj_stream_private_t *p_stream,
+- opj_j2k_t* p_j2k,
++ void* j2k,
+ opj_image_t** p_image,
+ opj_event_mgr_t* p_manager)
+ {
++ opj_j2k_t *p_j2k = (opj_j2k_t*)j2k;
+ /* preconditions */
+ assert(p_j2k != 00);
+ assert(p_stream != 00);
+@@ -9178,8 +9183,9 @@ static const opj_dec_memory_marker_handler_t * opj_j2k_get_marker_handler(
+ return e;
+ }
+
+-void opj_j2k_destroy(opj_j2k_t *p_j2k)
++void opj_j2k_destroy(void *j2k)
+ {
++ opj_j2k_t *p_j2k = (opj_j2k_t*)j2k;
+ if (p_j2k == 00) {
+ return;
+ }
+@@ -9518,7 +9524,7 @@ static OPJ_BOOL opj_j2k_need_nb_tile_parts_correction(opj_stream_private_t
+ return OPJ_TRUE;
+ }
+
+-OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k,
++OPJ_BOOL opj_j2k_read_tile_header(void * j2k,
+ OPJ_UINT32 * p_tile_index,
+ OPJ_UINT32 * p_data_size,
+ OPJ_INT32 * p_tile_x0, OPJ_INT32 * p_tile_y0,
+@@ -9528,6 +9534,7 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager)
+ {
++ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
+ OPJ_UINT32 l_current_marker = J2K_MS_SOT;
+ OPJ_UINT32 l_marker_size;
+ const opj_dec_memory_marker_handler_t * l_marker_handler = 00;
+@@ -9827,13 +9834,14 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k,
+ return OPJ_TRUE;
+ }
+
+-OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k,
++OPJ_BOOL opj_j2k_decode_tile(void * 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_j2k_t* p_j2k = (opj_j2k_t*)j2k;
+ OPJ_UINT32 l_current_marker;
+ OPJ_BYTE l_data [2];
+ opj_tcp_t * l_tcp;
+@@ -10200,11 +10208,12 @@ static OPJ_BOOL opj_j2k_update_image_dimensions(opj_image_t* p_image,
+ return OPJ_TRUE;
+ }
+
+-OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k,
++OPJ_BOOL opj_j2k_set_decoded_components(void *j2k,
+ OPJ_UINT32 numcomps,
+ const OPJ_UINT32* comps_indices,
+ opj_event_mgr_t * p_manager)
+ {
++ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
+ OPJ_UINT32 i;
+ OPJ_BOOL* already_mapped;
+
+@@ -10260,12 +10269,13 @@ OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k,
+ }
+
+
+-OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
++OPJ_BOOL opj_j2k_set_decode_area(void *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_j2k_t* p_j2k = (opj_j2k_t*)j2k;
+ opj_cp_t * l_cp = &(p_j2k->m_cp);
+ opj_image_t * l_image = p_j2k->m_private_image;
+ OPJ_BOOL ret;
+@@ -11200,8 +11210,9 @@ static void opj_j2k_dump_tile_info(opj_tcp_t * l_default_tile,
+ }
+ }
+
+-void j2k_dump(opj_j2k_t* p_j2k, OPJ_INT32 flag, FILE* out_stream)
++void j2k_dump(void* j2k, OPJ_INT32 flag, FILE* out_stream)
+ {
++ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
+ /* Check if the flag is compatible with j2k file*/
+ if ((flag & OPJ_JP2_INFO) || (flag & OPJ_JP2_IND)) {
+ fprintf(out_stream, "Wrong flag\n");
+@@ -11391,8 +11402,9 @@ void j2k_dump_image_comp_header(opj_image_comp_t* comp_header,
+ }
+ }
+
+-opj_codestream_info_v2_t* j2k_get_cstr_info(opj_j2k_t* p_j2k)
++opj_codestream_info_v2_t* j2k_get_cstr_info(void* j2k)
+ {
++ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
+ OPJ_UINT32 compno;
+ OPJ_UINT32 numcomps = p_j2k->m_private_image->numcomps;
+ opj_tcp_t *l_default_tile;
+@@ -11467,8 +11479,9 @@ opj_codestream_info_v2_t* j2k_get_cstr_info(opj_j2k_t* p_j2k)
+ return cstr_info;
+ }
+
+-opj_codestream_index_t* j2k_get_cstr_index(opj_j2k_t* p_j2k)
++opj_codestream_index_t* j2k_get_cstr_index(void* j2k)
+ {
++ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
+ opj_codestream_index_t* l_cstr_index = (opj_codestream_index_t*)
+ opj_calloc(1, sizeof(opj_codestream_index_t));
+ if (!l_cstr_index) {
+@@ -11972,11 +11985,12 @@ static OPJ_BOOL opj_j2k_move_data_from_codec_to_output_image(opj_j2k_t * p_j2k,
+ return OPJ_TRUE;
+ }
+
+-OPJ_BOOL opj_j2k_decode(opj_j2k_t * p_j2k,
++OPJ_BOOL opj_j2k_decode(void * j2k,
+ opj_stream_private_t * p_stream,
+ opj_image_t * p_image,
+ opj_event_mgr_t * p_manager)
+ {
++ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
+ if (!p_image) {
+ return OPJ_FALSE;
+ }
+@@ -12030,12 +12044,13 @@ OPJ_BOOL opj_j2k_decode(opj_j2k_t * p_j2k,
+ return opj_j2k_move_data_from_codec_to_output_image(p_j2k, p_image);
+ }
+
+-OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k,
++OPJ_BOOL opj_j2k_get_tile(void *j2k,
+ opj_stream_private_t *p_stream,
+ opj_image_t* p_image,
+ opj_event_mgr_t * p_manager,
+ OPJ_UINT32 tile_index)
+ {
++ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
+ OPJ_UINT32 compno;
+ OPJ_UINT32 l_tile_x, l_tile_y;
+ opj_image_comp_t* l_img_comp;
+@@ -12143,10 +12158,11 @@ OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k,
+ 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_BOOL opj_j2k_set_decoded_resolution_factor(void *j2k,
+ OPJ_UINT32 res_factor,
+ opj_event_mgr_t * p_manager)
+ {
++ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
+ OPJ_UINT32 it_comp;
+
+ p_j2k->m_cp.m_specific_param.m_dec.m_reduce = res_factor;
+@@ -12177,10 +12193,11 @@ OPJ_BOOL opj_j2k_set_decoded_resolution_factor(opj_j2k_t *p_j2k,
+ /* ----------------------------------------------------------------------- */
+
+ OPJ_BOOL opj_j2k_encoder_set_extra_options(
+- opj_j2k_t *p_j2k,
++ void *j2k,
+ const char* const* p_options,
+ opj_event_mgr_t * p_manager)
+ {
++ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
+ const char* const* p_option_iter;
+
+ if (p_options == NULL) {
+@@ -12239,10 +12256,11 @@ OPJ_BOOL opj_j2k_encoder_set_extra_options(
+
+ /* ----------------------------------------------------------------------- */
+
+-OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
++OPJ_BOOL opj_j2k_encode(void * j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager)
+ {
++ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
+ OPJ_UINT32 i, j;
+ OPJ_UINT32 l_nb_tiles;
+ OPJ_SIZE_T l_max_tile_size = 0, l_current_tile_size;
+@@ -12347,10 +12365,11 @@ OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
+ return OPJ_TRUE;
+ }
+
+-OPJ_BOOL opj_j2k_end_compress(opj_j2k_t *p_j2k,
++OPJ_BOOL opj_j2k_end_compress(void *j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager)
+ {
++ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
+ /* customization of the encoding */
+ if (! opj_j2k_setup_end_compress(p_j2k, p_manager)) {
+ return OPJ_FALSE;
+@@ -12363,11 +12382,12 @@ OPJ_BOOL opj_j2k_end_compress(opj_j2k_t *p_j2k,
+ return OPJ_TRUE;
+ }
+
+-OPJ_BOOL opj_j2k_start_compress(opj_j2k_t *p_j2k,
++OPJ_BOOL opj_j2k_start_compress(void *j2k,
+ opj_stream_private_t *p_stream,
+ opj_image_t * p_image,
+ opj_event_mgr_t * p_manager)
+ {
++ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
+ /* preconditions */
+ assert(p_j2k != 00);
+ assert(p_stream != 00);
+@@ -13154,13 +13174,14 @@ static OPJ_BOOL opj_j2k_create_tcd(opj_j2k_t *p_j2k,
+ return OPJ_TRUE;
+ }
+
+-OPJ_BOOL opj_j2k_write_tile(opj_j2k_t * p_j2k,
++OPJ_BOOL opj_j2k_write_tile(void * 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_j2k_t* p_j2k = (opj_j2k_t*)j2k;
+ 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);
+diff --git a/third_party/libopenjpeg/j2k.h b/third_party/libopenjpeg/j2k.h
+index 04fba645a..1d824c019 100644
+--- a/third_party/libopenjpeg/j2k.h
++++ b/third_party/libopenjpeg/j2k.h
+@@ -621,15 +621,15 @@ opj_j2k_t;
+
+ /**
+ Setup the decoder decoding parameters using user parameters.
+-Decoding parameters are returned in j2k->cp.
+-@param j2k J2K decompressor handle
++Decoding parameters are returned in p_j2k->cp.
++@param p_j2k J2K decompressor handle
+ @param parameters decompression parameters
+ */
+-void opj_j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters);
++void opj_j2k_setup_decoder(void *p_j2k, opj_dparameters_t *parameters);
+
+-void opj_j2k_decoder_set_strict_mode(opj_j2k_t *j2k, OPJ_BOOL strict);
++void opj_j2k_decoder_set_strict_mode(void *j2k, OPJ_BOOL strict);
+
+-OPJ_BOOL opj_j2k_set_threads(opj_j2k_t *j2k, OPJ_UINT32 num_threads);
++OPJ_BOOL opj_j2k_set_threads(void *j2k, OPJ_UINT32 num_threads);
+
+ /**
+ * Creates a J2K compression structure
+@@ -639,7 +639,7 @@ OPJ_BOOL opj_j2k_set_threads(opj_j2k_t *j2k, OPJ_UINT32 num_threads);
+ opj_j2k_t* opj_j2k_create_compress(void);
+
+
+-OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k,
++OPJ_BOOL opj_j2k_setup_encoder(void *p_j2k,
+ opj_cparameters_t *parameters,
+ opj_image_t *image,
+ opj_event_mgr_t * p_manager);
+@@ -658,7 +658,7 @@ const char *opj_j2k_convert_progression_order(OPJ_PROG_ORDER prg_order);
+ * Ends the decompression procedures and possibiliy add data to be read after the
+ * codestream.
+ */
+-OPJ_BOOL opj_j2k_end_decompress(opj_j2k_t *j2k,
++OPJ_BOOL opj_j2k_end_decompress(void *j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager);
+
+@@ -666,14 +666,14 @@ OPJ_BOOL opj_j2k_end_decompress(opj_j2k_t *j2k,
+ * Reads a jpeg2000 codestream header structure.
+ *
+ * @param p_stream the stream to read data from.
+- * @param p_j2k the jpeg2000 codec.
++ * @param j2k the jpeg2000 codec.
+ * @param p_image FIXME DOC
+ * @param p_manager the user event manager.
+ *
+ * @return true if the box is valid.
+ */
+ OPJ_BOOL opj_j2k_read_header(opj_stream_private_t *p_stream,
+- opj_j2k_t* p_j2k,
++ void* j2k,
+ opj_image_t** p_image,
+ opj_event_mgr_t* p_manager);
+
+@@ -681,9 +681,9 @@ OPJ_BOOL opj_j2k_read_header(opj_stream_private_t *p_stream,
+ /**
+ * Destroys a jpeg2000 codec.
+ *
+- * @param p_j2k the jpeg20000 structure to destroy.
++ * @param j2k the jpeg20000 structure to destroy.
+ */
+-void opj_j2k_destroy(opj_j2k_t *p_j2k);
++void opj_j2k_destroy(void *j2k);
+
+ /**
+ * Destroys a codestream index structure.
+@@ -694,14 +694,14 @@ void j2k_destroy_cstr_index(opj_codestream_index_t *p_cstr_ind);
+
+ /**
+ * Decode tile data.
+- * @param p_j2k the jpeg2000 codec.
++ * @param 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.
+ */
+-OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k,
++OPJ_BOOL opj_j2k_decode_tile(void * j2k,
+ OPJ_UINT32 p_tile_index,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 p_data_size,
+@@ -710,7 +710,7 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k,
+
+ /**
+ * Reads a tile header.
+- * @param p_j2k the jpeg2000 codec.
++ * @param j2k the jpeg2000 codec.
+ * @param p_tile_index FIXME DOC
+ * @param p_data_size FIXME DOC
+ * @param p_tile_x0 FIXME DOC
+@@ -722,7 +722,7 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k,
+ * @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_BOOL opj_j2k_read_tile_header(void * j2k,
+ OPJ_UINT32 * p_tile_index,
+ OPJ_UINT32 * p_data_size,
+ OPJ_INT32 * p_tile_x0,
+@@ -737,7 +737,7 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k,
+
+ /** Sets the indices of the components to decode.
+ *
+- * @param p_j2k the jpeg2000 codec.
++ * @param 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.
+@@ -745,7 +745,7 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k,
+ *
+ * @return OPJ_TRUE in case of success.
+ */
+-OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k,
++OPJ_BOOL opj_j2k_set_decoded_components(void *j2k,
+ OPJ_UINT32 numcomps,
+ const OPJ_UINT32* comps_indices,
+ opj_event_mgr_t * p_manager);
+@@ -753,7 +753,7 @@ OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k,
+ /**
+ * 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 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).
+@@ -763,7 +763,7 @@ OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k,
+ *
+ * @return true if the area could be set.
+ */
+-OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
++OPJ_BOOL opj_j2k_set_decode_area(void *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,
+@@ -780,12 +780,12 @@ opj_j2k_t* opj_j2k_create_decompress(void);
+ /**
+ * Dump some elements from the J2K decompression structure .
+ *
+- *@param p_j2k the jpeg2000 codec.
++ *@param 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(void* j2k, OPJ_INT32 flag, FILE* out_stream);
+
+
+
+@@ -812,20 +812,20 @@ void j2k_dump_image_comp_header(opj_image_comp_t* comp, OPJ_BOOL dev_dump_flag,
+ /**
+ * Get the codestream info from a JPEG2000 codec.
+ *
+- *@param p_j2k the component image header to dump.
++ *@param j2k the component image header to dump.
+ *
+ *@return the codestream information extract from the jpg2000 codec
+ */
+-opj_codestream_info_v2_t* j2k_get_cstr_info(opj_j2k_t* p_j2k);
++opj_codestream_info_v2_t* j2k_get_cstr_info(void* j2k);
+
+ /**
+ * Get the codestream index from a JPEG2000 codec.
+ *
+- *@param p_j2k the component image header to dump.
++ *@param j2k the component image header to dump.
+ *
+ *@return the codestream index extract from the jpg2000 codec
+ */
+-opj_codestream_index_t* j2k_get_cstr_index(opj_j2k_t* p_j2k);
++opj_codestream_index_t* j2k_get_cstr_index(void* j2k);
+
+ /**
+ * Decode an image from a JPEG-2000 codestream
+@@ -835,46 +835,46 @@ opj_codestream_index_t* j2k_get_cstr_index(opj_j2k_t* p_j2k);
+ * @param p_manager FIXME DOC
+ * @return FIXME DOC
+ */
+-OPJ_BOOL opj_j2k_decode(opj_j2k_t *j2k,
++OPJ_BOOL opj_j2k_decode(void *j2k,
+ opj_stream_private_t *p_stream,
+ opj_image_t *p_image,
+ opj_event_mgr_t *p_manager);
+
+
+-OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k,
++OPJ_BOOL opj_j2k_get_tile(void *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_BOOL opj_j2k_set_decoded_resolution_factor(void *j2k,
+ OPJ_UINT32 res_factor,
+ opj_event_mgr_t * p_manager);
+
+ /**
+ * Specify extra options for the encoder.
+ *
+- * @param p_j2k the jpeg2000 codec.
++ * @param j2k the jpeg2000 codec.
+ * @param p_options options
+ * @param p_manager the user event manager
+ *
+ * @see opj_encoder_set_extra_options() for more details.
+ */
+ OPJ_BOOL opj_j2k_encoder_set_extra_options(
+- opj_j2k_t *p_j2k,
++ void *j2k,
+ const char* const* p_options,
+ opj_event_mgr_t * p_manager);
+
+ /**
+ * Writes a tile.
+- * @param p_j2k the jpeg2000 codec.
++ * @param 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.
+ */
+-OPJ_BOOL opj_j2k_write_tile(opj_j2k_t * p_j2k,
++OPJ_BOOL opj_j2k_write_tile(void * j2k,
+ OPJ_UINT32 p_tile_index,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 p_data_size,
+@@ -884,21 +884,21 @@ OPJ_BOOL opj_j2k_write_tile(opj_j2k_t * p_j2k,
+ /**
+ * Encodes an image into a JPEG-2000 codestream
+ */
+-OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
++OPJ_BOOL opj_j2k_encode(void * 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 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_BOOL opj_j2k_start_compress(void *j2k,
+ opj_stream_private_t *p_stream,
+ opj_image_t * p_image,
+ opj_event_mgr_t * p_manager);
+@@ -907,7 +907,7 @@ OPJ_BOOL opj_j2k_start_compress(opj_j2k_t *p_j2k,
+ * 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_BOOL opj_j2k_end_compress(void *j2k,
+ opj_stream_private_t *cio,
+ opj_event_mgr_t * p_manager);
+
+diff --git a/third_party/libopenjpeg/jp2.c b/third_party/libopenjpeg/jp2.c
+index 44d0c98e5..6db728d18 100644
+--- a/third_party/libopenjpeg/jp2.c
++++ b/third_party/libopenjpeg/jp2.c
+@@ -1609,11 +1609,12 @@ static OPJ_BOOL opj_jp2_read_colr(opj_jp2_t *jp2,
+ return OPJ_TRUE;
+ }
+
+-OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2,
++OPJ_BOOL opj_jp2_decode(void *p_jp2,
+ opj_stream_private_t *p_stream,
+ opj_image_t* p_image,
+ opj_event_mgr_t * p_manager)
+ {
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ if (!p_image) {
+ return OPJ_FALSE;
+ }
+@@ -1905,8 +1906,9 @@ static OPJ_BOOL opj_jp2_write_jp(opj_jp2_t *jp2,
+ /* JP2 decoder interface */
+ /* ----------------------------------------------------------------------- */
+
+-void opj_jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters)
++void opj_jp2_setup_decoder(void *p_jp2, opj_dparameters_t *parameters)
+ {
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ /* setup the J2K codec */
+ opj_j2k_setup_decoder(jp2->j2k, parameters);
+
+@@ -1917,13 +1919,15 @@ void opj_jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters)
+ OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG;
+ }
+
+-void opj_jp2_decoder_set_strict_mode(opj_jp2_t *jp2, OPJ_BOOL strict)
++void opj_jp2_decoder_set_strict_mode(void *p_jp2, OPJ_BOOL strict)
+ {
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ opj_j2k_decoder_set_strict_mode(jp2->j2k, strict);
+ }
+
+-OPJ_BOOL opj_jp2_set_threads(opj_jp2_t *jp2, OPJ_UINT32 num_threads)
++OPJ_BOOL opj_jp2_set_threads(void *p_jp2, OPJ_UINT32 num_threads)
+ {
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ return opj_j2k_set_threads(jp2->j2k, num_threads);
+ }
+
+@@ -1931,11 +1935,12 @@ OPJ_BOOL opj_jp2_set_threads(opj_jp2_t *jp2, OPJ_UINT32 num_threads)
+ /* JP2 encoder interface */
+ /* ----------------------------------------------------------------------- */
+
+-OPJ_BOOL opj_jp2_setup_encoder(opj_jp2_t *jp2,
++OPJ_BOOL opj_jp2_setup_encoder(void *p_jp2,
+ opj_cparameters_t *parameters,
+ opj_image_t *image,
+ opj_event_mgr_t * p_manager)
+ {
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ OPJ_UINT32 i;
+ OPJ_UINT32 depth_0;
+ OPJ_UINT32 sign;
+@@ -2118,18 +2123,20 @@ OPJ_BOOL opj_jp2_setup_encoder(opj_jp2_t *jp2,
+ return OPJ_TRUE;
+ }
+
+-OPJ_BOOL opj_jp2_encode(opj_jp2_t *jp2,
++OPJ_BOOL opj_jp2_encode(void *p_jp2,
+ opj_stream_private_t *stream,
+ opj_event_mgr_t * p_manager)
+ {
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ return opj_j2k_encode(jp2->j2k, stream, p_manager);
+ }
+
+-OPJ_BOOL opj_jp2_end_decompress(opj_jp2_t *jp2,
++OPJ_BOOL opj_jp2_end_decompress(void *p_jp2,
+ opj_stream_private_t *cio,
+ opj_event_mgr_t * p_manager
+ )
+ {
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ /* preconditions */
+ assert(jp2 != 00);
+ assert(cio != 00);
+@@ -2148,11 +2155,12 @@ OPJ_BOOL opj_jp2_end_decompress(opj_jp2_t *jp2,
+ return opj_j2k_end_decompress(jp2->j2k, cio, p_manager);
+ }
+
+-OPJ_BOOL opj_jp2_end_compress(opj_jp2_t *jp2,
++OPJ_BOOL opj_jp2_end_compress(void *p_jp2,
+ opj_stream_private_t *cio,
+ opj_event_mgr_t * p_manager
+ )
+ {
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ /* preconditions */
+ assert(jp2 != 00);
+ assert(cio != 00);
+@@ -2476,12 +2484,13 @@ static OPJ_BOOL opj_jp2_exec(opj_jp2_t * jp2,
+ return l_result;
+ }
+
+-OPJ_BOOL opj_jp2_start_compress(opj_jp2_t *jp2,
++OPJ_BOOL opj_jp2_start_compress(void *p_jp2,
+ opj_stream_private_t *stream,
+ opj_image_t * p_image,
+ opj_event_mgr_t * p_manager
+ )
+ {
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ /* preconditions */
+ assert(jp2 != 00);
+ assert(stream != 00);
+@@ -2854,11 +2863,12 @@ static OPJ_BOOL opj_jp2_read_boxhdr_char(opj_jp2_box_t *box,
+ }
+
+ OPJ_BOOL opj_jp2_read_header(opj_stream_private_t *p_stream,
+- opj_jp2_t *jp2,
++ void *p_jp2,
+ opj_image_t ** p_image,
+ opj_event_mgr_t * p_manager
+ )
+ {
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ /* preconditions */
+ assert(jp2 != 00);
+ assert(p_stream != 00);
+@@ -2981,7 +2991,7 @@ static OPJ_BOOL opj_jp2_setup_header_reading(opj_jp2_t *jp2,
+ return OPJ_TRUE;
+ }
+
+-OPJ_BOOL opj_jp2_read_tile_header(opj_jp2_t * p_jp2,
++OPJ_BOOL opj_jp2_read_tile_header(void *p_jp2,
+ OPJ_UINT32 * p_tile_index,
+ OPJ_UINT32 * p_data_size,
+ OPJ_INT32 * p_tile_x0,
+@@ -2994,7 +3004,8 @@ OPJ_BOOL opj_jp2_read_tile_header(opj_jp2_t * p_jp2,
+ opj_event_mgr_t * p_manager
+ )
+ {
+- return opj_j2k_read_tile_header(p_jp2->j2k,
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
++ return opj_j2k_read_tile_header(jp2->j2k,
+ p_tile_index,
+ p_data_size,
+ p_tile_x0, p_tile_y0,
+@@ -3005,7 +3016,7 @@ OPJ_BOOL opj_jp2_read_tile_header(opj_jp2_t * p_jp2,
+ p_manager);
+ }
+
+-OPJ_BOOL opj_jp2_write_tile(opj_jp2_t *p_jp2,
++OPJ_BOOL opj_jp2_write_tile(void *p_jp2,
+ OPJ_UINT32 p_tile_index,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 p_data_size,
+@@ -3014,11 +3025,12 @@ OPJ_BOOL opj_jp2_write_tile(opj_jp2_t *p_jp2,
+ )
+
+ {
+- return opj_j2k_write_tile(p_jp2->j2k, p_tile_index, p_data, p_data_size,
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
++ return opj_j2k_write_tile(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_BOOL opj_jp2_decode_tile(void *p_jp2,
+ OPJ_UINT32 p_tile_index,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 p_data_size,
+@@ -3026,12 +3038,14 @@ OPJ_BOOL opj_jp2_decode_tile(opj_jp2_t * p_jp2,
+ opj_event_mgr_t * p_manager
+ )
+ {
+- return opj_j2k_decode_tile(p_jp2->j2k, p_tile_index, p_data, p_data_size,
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
++ return opj_j2k_decode_tile(jp2->j2k, p_tile_index, p_data, p_data_size,
+ p_stream, p_manager);
+ }
+
+-void opj_jp2_destroy(opj_jp2_t *jp2)
++void opj_jp2_destroy(void *p_jp2)
+ {
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ if (jp2) {
+ /* destroy the J2K codec */
+ opj_j2k_destroy(jp2->j2k);
+@@ -3098,34 +3112,37 @@ void opj_jp2_destroy(opj_jp2_t *jp2)
+ }
+ }
+
+-OPJ_BOOL opj_jp2_set_decoded_components(opj_jp2_t *p_jp2,
++OPJ_BOOL opj_jp2_set_decoded_components(void *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,
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
++ return opj_j2k_set_decoded_components(jp2->j2k,
+ numcomps, comps_indices,
+ p_manager);
+ }
+
+-OPJ_BOOL opj_jp2_set_decode_area(opj_jp2_t *p_jp2,
++OPJ_BOOL opj_jp2_set_decode_area(void *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,
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
++ return opj_j2k_set_decode_area(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_BOOL opj_jp2_get_tile(void *jp2,
+ opj_stream_private_t *p_stream,
+ opj_image_t* p_image,
+ opj_event_mgr_t * p_manager,
+ OPJ_UINT32 tile_index
+ )
+ {
++ opj_jp2_t *p_jp2 = (opj_jp2_t*)jp2;
+ if (!p_image) {
+ return OPJ_FALSE;
+ }
+@@ -3234,41 +3251,46 @@ opj_jp2_t* opj_jp2_create(OPJ_BOOL p_is_decoder)
+ return jp2;
+ }
+
+-void jp2_dump(opj_jp2_t* p_jp2, OPJ_INT32 flag, FILE* out_stream)
++void jp2_dump(void* p_jp2, OPJ_INT32 flag, FILE* out_stream)
+ {
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ /* preconditions */
+ assert(p_jp2 != 00);
+
+- j2k_dump(p_jp2->j2k,
++ j2k_dump(jp2->j2k,
+ flag,
+ out_stream);
+ }
+
+-opj_codestream_index_t* jp2_get_cstr_index(opj_jp2_t* p_jp2)
++opj_codestream_index_t* jp2_get_cstr_index(void* p_jp2)
+ {
+- return j2k_get_cstr_index(p_jp2->j2k);
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
++ return j2k_get_cstr_index(jp2->j2k);
+ }
+
+-opj_codestream_info_v2_t* jp2_get_cstr_info(opj_jp2_t* p_jp2)
++opj_codestream_info_v2_t* jp2_get_cstr_info(void* p_jp2)
+ {
+- return j2k_get_cstr_info(p_jp2->j2k);
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
++ return j2k_get_cstr_info(jp2->j2k);
+ }
+
+-OPJ_BOOL opj_jp2_set_decoded_resolution_factor(opj_jp2_t *p_jp2,
++OPJ_BOOL opj_jp2_set_decoded_resolution_factor(void *p_jp2,
+ OPJ_UINT32 res_factor,
+ opj_event_mgr_t * p_manager)
+ {
+- return opj_j2k_set_decoded_resolution_factor(p_jp2->j2k, res_factor, p_manager);
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
++ return opj_j2k_set_decoded_resolution_factor(jp2->j2k, res_factor, p_manager);
+ }
+
+ /* ----------------------------------------------------------------------- */
+
+ OPJ_BOOL opj_jp2_encoder_set_extra_options(
+- opj_jp2_t *p_jp2,
++ void *p_jp2,
+ const char* const* p_options,
+ opj_event_mgr_t * p_manager)
+ {
+- return opj_j2k_encoder_set_extra_options(p_jp2->j2k, p_options, p_manager);
++ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
++ return opj_j2k_encoder_set_extra_options(jp2->j2k, p_options, p_manager);
+ }
+
+ /* ----------------------------------------------------------------------- */
+diff --git a/third_party/libopenjpeg/jp2.h b/third_party/libopenjpeg/jp2.h
+index 173f25119..fd9175a4e 100644
+--- a/third_party/libopenjpeg/jp2.h
++++ b/third_party/libopenjpeg/jp2.h
+@@ -230,38 +230,38 @@ opj_jp2_img_header_writer_handler_t;
+ /**
+ Setup the decoder decoding parameters using user parameters.
+ Decoding parameters are returned in jp2->j2k->cp.
+-@param jp2 JP2 decompressor handle
++@param p_jp2 JP2 decompressor handle
+ @param parameters decompression parameters
+ */
+-void opj_jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters);
++void opj_jp2_setup_decoder(void *p_jp2, opj_dparameters_t *parameters);
+
+ /**
+ Set the strict mode parameter. When strict mode is enabled, the entire
+ bitstream must be decoded or an error is returned. When it is disabled,
+ the decoder will decode partial bitstreams.
+-@param jp2 JP2 decompressor handle
++@param p_jp2 JP2 decompressor handle
+ @param strict OPJ_TRUE for strict mode
+ */
+-void opj_jp2_decoder_set_strict_mode(opj_jp2_t *jp2, OPJ_BOOL strict);
++void opj_jp2_decoder_set_strict_mode(void *p_jp2, OPJ_BOOL strict);
+
+ /** Allocates worker threads for the compressor/decompressor.
+ *
+- * @param jp2 JP2 decompressor handle
++ * @param p_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);
++OPJ_BOOL opj_jp2_set_threads(void *p_jp2, OPJ_UINT32 num_threads);
+
+ /**
+ * Decode an image from a JPEG-2000 file stream
+- * @param jp2 JP2 decompressor handle
++ * @param p_jp2 JP2 decompressor handle
+ * @param p_stream FIXME DOC
+ * @param p_image FIXME DOC
+ * @param p_manager FIXME DOC
+ *
+ * @return Returns a decoded image if successful, returns NULL otherwise
+ */
+-OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2,
++OPJ_BOOL opj_jp2_decode(void *p_jp2,
+ opj_stream_private_t *p_stream,
+ opj_image_t* p_image,
+ opj_event_mgr_t * p_manager);
+@@ -270,25 +270,25 @@ OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2,
+ * 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 p_jp2 JP2 compressor handle
+ * @param parameters compression parameters
+ * @param image input filled image
+ * @param p_manager FIXME DOC
+ * @return OPJ_TRUE if successful, OPJ_FALSE otherwise
+ */
+-OPJ_BOOL opj_jp2_setup_encoder(opj_jp2_t *jp2,
++OPJ_BOOL opj_jp2_setup_encoder(void *p_jp2,
+ opj_cparameters_t *parameters,
+ opj_image_t *image,
+ opj_event_mgr_t * p_manager);
+
+ /**
+ Encode an image into a JPEG-2000 file stream
+-@param jp2 JP2 compressor handle
++@param p_jp2 JP2 compressor handle
+ @param stream Output buffer stream
+ @param p_manager event manager
+ @return Returns true if successful, returns false otherwise
+ */
+-OPJ_BOOL opj_jp2_encode(opj_jp2_t *jp2,
++OPJ_BOOL opj_jp2_encode(void *p_jp2,
+ opj_stream_private_t *stream,
+ opj_event_mgr_t * p_manager);
+
+@@ -296,14 +296,14 @@ OPJ_BOOL opj_jp2_encode(opj_jp2_t *jp2,
+ /**
+ * Starts a compression scheme, i.e. validates the codec parameters, writes the header.
+ *
+- * @param jp2 the jpeg2000 file codec.
++ * @param p_jp2 the jpeg2000 file codec.
+ * @param stream the stream object.
+ * @param p_image FIXME DOC
+ * @param p_manager FIXME DOC
+ *
+ * @return true if the codec is valid.
+ */
+-OPJ_BOOL opj_jp2_start_compress(opj_jp2_t *jp2,
++OPJ_BOOL opj_jp2_start_compress(void *p_jp2,
+ opj_stream_private_t *stream,
+ opj_image_t * p_image,
+ opj_event_mgr_t * p_manager);
+@@ -313,7 +313,7 @@ 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_BOOL opj_jp2_end_compress(void *p_jp2,
+ opj_stream_private_t *cio,
+ opj_event_mgr_t * p_manager);
+
+@@ -323,7 +323,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(void *p_jp2,
+ opj_stream_private_t *cio,
+ opj_event_mgr_t * p_manager);
+
+@@ -331,20 +331,20 @@ OPJ_BOOL opj_jp2_end_decompress(opj_jp2_t *jp2,
+ * Reads a jpeg2000 file header structure.
+ *
+ * @param p_stream the stream to read data from.
+- * @param jp2 the jpeg2000 file header structure.
++ * @param p_jp2 the jpeg2000 file header structure.
+ * @param p_image FIXME DOC
+ * @param p_manager the user event manager.
+ *
+ * @return true if the box is valid.
+ */
+ OPJ_BOOL opj_jp2_read_header(opj_stream_private_t *p_stream,
+- opj_jp2_t *jp2,
++ void *p_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 p_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.
+@@ -352,7 +352,7 @@ OPJ_BOOL opj_jp2_read_header(opj_stream_private_t *p_stream,
+ *
+ * @return OPJ_TRUE in case of success.
+ */
+-OPJ_BOOL opj_jp2_set_decoded_components(opj_jp2_t *jp2,
++OPJ_BOOL opj_jp2_set_decoded_components(void *p_jp2,
+ OPJ_UINT32 numcomps,
+ const OPJ_UINT32* comps_indices,
+ opj_event_mgr_t * p_manager);
+@@ -371,7 +371,7 @@ OPJ_BOOL opj_jp2_set_decoded_components(opj_jp2_t *jp2,
+ * @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_BOOL opj_jp2_read_tile_header(void * p_jp2,
+ OPJ_UINT32 * p_tile_index,
+ OPJ_UINT32 * p_data_size,
+ OPJ_INT32 * p_tile_x0,
+@@ -393,7 +393,7 @@ 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_BOOL opj_jp2_write_tile(void *p_jp2,
+ OPJ_UINT32 p_tile_index,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 p_data_size,
+@@ -411,7 +411,7 @@ 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_BOOL opj_jp2_decode_tile(void * p_jp2,
+ OPJ_UINT32 p_tile_index,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 p_data_size,
+@@ -427,9 +427,9 @@ opj_jp2_t* opj_jp2_create(OPJ_BOOL p_is_decoder);
+
+ /**
+ Destroy a JP2 decompressor handle
+-@param jp2 JP2 decompressor handle to destroy
++@param p_jp2 JP2 decompressor handle to destroy
+ */
+-void opj_jp2_destroy(opj_jp2_t *jp2);
++void opj_jp2_destroy(void *p_jp2);
+
+
+ /**
+@@ -445,7 +445,7 @@ 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_BOOL opj_jp2_set_decode_area(void *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,
+@@ -454,7 +454,7 @@ OPJ_BOOL opj_jp2_set_decode_area(opj_jp2_t *p_jp2,
+ /**
+ *
+ */
+-OPJ_BOOL opj_jp2_get_tile(opj_jp2_t *p_jp2,
++OPJ_BOOL opj_jp2_get_tile(void *jp2,
+ opj_stream_private_t *p_stream,
+ opj_image_t* p_image,
+ opj_event_mgr_t * p_manager,
+@@ -464,7 +464,7 @@ OPJ_BOOL opj_jp2_get_tile(opj_jp2_t *p_jp2,
+ /**
+ *
+ */
+-OPJ_BOOL opj_jp2_set_decoded_resolution_factor(opj_jp2_t *p_jp2,
++OPJ_BOOL opj_jp2_set_decoded_resolution_factor(void *p_jp2,
+ OPJ_UINT32 res_factor,
+ opj_event_mgr_t * p_manager);
+
+@@ -478,7 +478,7 @@ OPJ_BOOL opj_jp2_set_decoded_resolution_factor(opj_jp2_t *p_jp2,
+ * @see opj_encoder_set_extra_options() for more details.
+ */
+ OPJ_BOOL opj_jp2_encoder_set_extra_options(
+- opj_jp2_t *p_jp2,
++ void *p_jp2,
+ const char* const* p_options,
+ opj_event_mgr_t * p_manager);
+
+@@ -492,7 +492,7 @@ OPJ_BOOL opj_jp2_encoder_set_extra_options(
+ *@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(void* p_jp2, OPJ_INT32 flag, FILE* out_stream);
+
+ /**
+ * Get the codestream info from a JPEG2000 codec.
+@@ -501,7 +501,7 @@ void jp2_dump(opj_jp2_t* p_jp2, OPJ_INT32 flag, FILE* out_stream);
+ *
+ *@return the codestream information extract from the jpg2000 codec
+ */
+-opj_codestream_info_v2_t* jp2_get_cstr_info(opj_jp2_t* p_jp2);
++opj_codestream_info_v2_t* jp2_get_cstr_info(void* p_jp2);
+
+ /**
+ * Get the codestream index from a JPEG2000 codec.
+@@ -510,7 +510,7 @@ opj_codestream_info_v2_t* jp2_get_cstr_info(opj_jp2_t* p_jp2);
+ *
+ *@return the codestream index extract from the jpg2000 codec
+ */
+-opj_codestream_index_t* jp2_get_cstr_index(opj_jp2_t* p_jp2);
++opj_codestream_index_t* jp2_get_cstr_index(void* p_jp2);
+
+
+ /*@}*/
+diff --git a/third_party/libopenjpeg/openjpeg.c b/third_party/libopenjpeg/openjpeg.c
+index 29d3ee528..9dd4256d7 100644
+--- a/third_party/libopenjpeg/openjpeg.c
++++ b/third_party/libopenjpeg/openjpeg.c
+@@ -189,85 +189,48 @@ opj_codec_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT p_format)
+
+ switch (p_format) {
+ case OPJ_CODEC_J2K:
+- l_codec->opj_dump_codec = (void (*)(void*, OPJ_INT32, FILE*)) j2k_dump;
++ l_codec->opj_dump_codec = j2k_dump;
+
+- l_codec->opj_get_codec_info = (opj_codestream_info_v2_t* (*)(
+- void*)) j2k_get_cstr_info;
++ l_codec->opj_get_codec_info = j2k_get_cstr_info;
+
+- l_codec->opj_get_codec_index = (opj_codestream_index_t* (*)(
+- void*)) j2k_get_cstr_index;
++ l_codec->opj_get_codec_index = 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_decode = 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;
++ 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;
++ 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_destroy = opj_j2k_destroy;
+
+ l_codec->m_codec_data.m_decompression.opj_setup_decoder =
+- (void (*)(void *, opj_dparameters_t *)) opj_j2k_setup_decoder;
++ opj_j2k_setup_decoder;
+
+ l_codec->m_codec_data.m_decompression.opj_decoder_set_strict_mode =
+- (void (*)(void *, OPJ_BOOL)) opj_j2k_decoder_set_strict_mode;
++ opj_j2k_decoder_set_strict_mode;
+
+
+ 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;
++ 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;
++ 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;
++ 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;
++ 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;
++ 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;
++ 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->opj_set_threads = opj_j2k_set_threads;
+
+ l_codec->m_codec = opj_j2k_create_decompress();
+
+@@ -280,85 +243,47 @@ opj_codec_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT p_format)
+
+ case OPJ_CODEC_JP2:
+ /* get a JP2 decoder handle */
+- l_codec->opj_dump_codec = (void (*)(void*, OPJ_INT32, FILE*)) jp2_dump;
++ l_codec->opj_dump_codec = jp2_dump;
+
+- l_codec->opj_get_codec_info = (opj_codestream_info_v2_t* (*)(
+- void*)) jp2_get_cstr_info;
++ l_codec->opj_get_codec_info = jp2_get_cstr_info;
+
+- l_codec->opj_get_codec_index = (opj_codestream_index_t* (*)(
+- void*)) jp2_get_cstr_index;
++ l_codec->opj_get_codec_index = 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_decode = 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;
++ 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;
++ 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;
++ 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;
++ 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_destroy = opj_jp2_destroy;
+
+ l_codec->m_codec_data.m_decompression.opj_setup_decoder =
+- (void (*)(void *, opj_dparameters_t *)) opj_jp2_setup_decoder;
++ opj_jp2_setup_decoder;
+
+ l_codec->m_codec_data.m_decompression.opj_decoder_set_strict_mode =
+- (void (*)(void *, OPJ_BOOL)) opj_jp2_decoder_set_strict_mode;
++ opj_jp2_decoder_set_strict_mode;
+
+ 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;
++ 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;
++ 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;
++ 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;
++ 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->opj_set_threads = opj_jp2_set_threads;
+
+ l_codec->m_codec = opj_jp2_create(OPJ_TRUE);
+
+@@ -662,41 +587,25 @@ opj_codec_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT p_format)
+
+ 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_data.m_compression.opj_encoder_set_extra_options = (OPJ_BOOL(
+- *)(void *,
+- const char* const*,
+- struct opj_event_mgr *)) opj_j2k_encoder_set_extra_options;
+-
+- l_codec->opj_set_threads =
+- (OPJ_BOOL(*)(void * p_codec, OPJ_UINT32 num_threads)) opj_j2k_set_threads;
++ l_codec->m_codec_data.m_compression.opj_encode = opj_j2k_encode;
++
++ l_codec->m_codec_data.m_compression.opj_end_compress =
++ opj_j2k_end_compress;
++
++ l_codec->m_codec_data.m_compression.opj_start_compress =
++ opj_j2k_start_compress;
++
++ l_codec->m_codec_data.m_compression.opj_write_tile = opj_j2k_write_tile;
++
++ l_codec->m_codec_data.m_compression.opj_destroy = opj_j2k_destroy;
++
++ l_codec->m_codec_data.m_compression.opj_setup_encoder =
++ opj_j2k_setup_encoder;
++
++ l_codec->m_codec_data.m_compression.opj_encoder_set_extra_options =
++ opj_j2k_encoder_set_extra_options;
++
++ l_codec->opj_set_threads = opj_j2k_set_threads;
+
+ l_codec->m_codec = opj_j2k_create_compress();
+ if (! l_codec->m_codec) {
+@@ -708,41 +617,25 @@ opj_codec_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT p_format)
+
+ 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_data.m_compression.opj_encoder_set_extra_options = (OPJ_BOOL(
+- *)(void *,
+- const char* const*,
+- struct opj_event_mgr *)) opj_jp2_encoder_set_extra_options;
+-
+- l_codec->opj_set_threads =
+- (OPJ_BOOL(*)(void * p_codec, OPJ_UINT32 num_threads)) opj_jp2_set_threads;
++ l_codec->m_codec_data.m_compression.opj_encode = opj_jp2_encode;
++
++ l_codec->m_codec_data.m_compression.opj_end_compress =
++ opj_jp2_end_compress;
++
++ l_codec->m_codec_data.m_compression.opj_start_compress =
++ opj_jp2_start_compress;
++
++ l_codec->m_codec_data.m_compression.opj_write_tile = opj_jp2_write_tile;
++
++ l_codec->m_codec_data.m_compression.opj_destroy = opj_jp2_destroy;
++
++ l_codec->m_codec_data.m_compression.opj_setup_encoder =
++ opj_jp2_setup_encoder;
++
++ l_codec->m_codec_data.m_compression.opj_encoder_set_extra_options =
++ opj_jp2_encoder_set_extra_options;
++
++ l_codec->opj_set_threads = opj_jp2_set_threads;
+
+ l_codec->m_codec = opj_jp2_create(OPJ_FALSE);
+ if (! l_codec->m_codec) {
diff --git a/third_party/libopenjpeg/README.pdfium b/third_party/libopenjpeg/README.pdfium
index 9498b86f2..638c81759 100644
--- a/third_party/libopenjpeg/README.pdfium
+++ b/third_party/libopenjpeg/README.pdfium
@@ -2,6 +2,7 @@ Name: OpenJPEG
URL: http://www.openjpeg.org/
Version: 2.5.0 (also update in opj_config*)
Security Critical: yes
+Shipped: yes
License: 2-clause BSD
CPEPrefix: cpe:/a:uclouvain:openjpeg:2.5.0
@@ -33,3 +34,4 @@ Local Modifications:
0043-mel_init.patch: Backport fix for assertion failure in mel_init().
0044-opj_t1_allocate_buffers.patch: Backport fix for malloc size error in opj_t1_allocate_buffers().
0045-openjp2-j2k-replace-sprintf-calls-with-snprintf.patch: Replace sprintf with snprintf for macOS 13 SDK compatibility, from https://github.com/uclouvain/openjpeg/pull/1450.
+0046-func-ptr-mixup.patch: Prevent mixing up function pointer types.
diff --git a/third_party/libopenjpeg/j2k.c b/third_party/libopenjpeg/j2k.c
index 9b06e7ec8..e2e048760 100644
--- a/third_party/libopenjpeg/j2k.c
+++ b/third_party/libopenjpeg/j2k.c
@@ -6685,8 +6685,9 @@ static OPJ_BOOL opj_j2k_read_cpf(opj_j2k_t *p_j2k,
/* J2K / JPT decoder interface */
/* ----------------------------------------------------------------------- */
-void opj_j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters)
+void opj_j2k_setup_decoder(void *p_j2k, opj_dparameters_t *parameters)
{
+ opj_j2k_t* j2k = (opj_j2k_t*)p_j2k;
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;
@@ -6700,15 +6701,17 @@ void opj_j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters)
}
}
-void opj_j2k_decoder_set_strict_mode(opj_j2k_t *j2k, OPJ_BOOL strict)
+void opj_j2k_decoder_set_strict_mode(void *p_j2k, OPJ_BOOL strict)
{
+ opj_j2k_t* j2k = (opj_j2k_t*)p_j2k;
if (j2k) {
j2k->m_cp.strict = strict;
}
}
-OPJ_BOOL opj_j2k_set_threads(opj_j2k_t *j2k, OPJ_UINT32 num_threads)
+OPJ_BOOL opj_j2k_set_threads(void *p_j2k, OPJ_UINT32 num_threads)
{
+ opj_j2k_t* j2k = (opj_j2k_t*)p_j2k;
/* Currently we pass the thread-pool to the tcd, so we cannot re-set it */
/* afterwards */
if (opj_has_thread_support() && j2k->m_tcd == NULL) {
@@ -7613,11 +7616,12 @@ static OPJ_BOOL opj_j2k_is_imf_compliant(opj_cparameters_t *parameters,
}
-OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k,
+OPJ_BOOL opj_j2k_setup_encoder(void *p_j2k,
opj_cparameters_t *parameters,
opj_image_t *image,
opj_event_mgr_t * p_manager)
{
+ opj_j2k_t* j2k = (opj_j2k_t*)p_j2k;
OPJ_UINT32 i, j, tileno, numpocs_tile;
opj_cp_t *cp = 00;
OPJ_UINT32 cblkw, cblkh;
@@ -7666,10 +7670,10 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k,
return OPJ_FALSE;
}
- p_j2k->m_specific_param.m_encoder.m_nb_comps = image->numcomps;
+ j2k->m_specific_param.m_encoder.m_nb_comps = image->numcomps;
/* keep a link to cp so that we can destroy it later in j2k_destroy_compress */
- cp = &(p_j2k->m_cp);
+ cp = &(j2k->m_cp);
/* set default values for cp */
cp->tw = 1;
@@ -7834,7 +7838,7 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k,
}
if (OPJ_IS_CINEMA(parameters->rsiz) || OPJ_IS_IMF(parameters->rsiz)) {
- p_j2k->m_specific_param.m_encoder.m_TLM = OPJ_TRUE;
+ j2k->m_specific_param.m_encoder.m_TLM = OPJ_TRUE;
}
/* Manage profiles and applications and set RSIZ */
@@ -8379,7 +8383,7 @@ static OPJ_BOOL opj_j2k_add_tlmarker(OPJ_UINT32 tileno,
* -----------------------------------------------------------------------
*/
-OPJ_BOOL opj_j2k_end_decompress(opj_j2k_t *p_j2k,
+OPJ_BOOL opj_j2k_end_decompress(void *p_j2k,
opj_stream_private_t *p_stream,
opj_event_mgr_t * p_manager
)
@@ -8391,10 +8395,11 @@ OPJ_BOOL opj_j2k_end_decompress(opj_j2k_t *p_j2k,
}
OPJ_BOOL opj_j2k_read_header(opj_stream_private_t *p_stream,
- opj_j2k_t* p_j2k,
+ void* j2k,
opj_image_t** p_image,
opj_event_mgr_t* p_manager)
{
+ opj_j2k_t *p_j2k = (opj_j2k_t*)j2k;
/* preconditions */
assert(p_j2k != 00);
assert(p_stream != 00);
@@ -9178,8 +9183,9 @@ static const opj_dec_memory_marker_handler_t * opj_j2k_get_marker_handler(
return e;
}
-void opj_j2k_destroy(opj_j2k_t *p_j2k)
+void opj_j2k_destroy(void *j2k)
{
+ opj_j2k_t *p_j2k = (opj_j2k_t*)j2k;
if (p_j2k == 00) {
return;
}
@@ -9518,7 +9524,7 @@ static OPJ_BOOL opj_j2k_need_nb_tile_parts_correction(opj_stream_private_t
return OPJ_TRUE;
}
-OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k,
+OPJ_BOOL opj_j2k_read_tile_header(void * j2k,
OPJ_UINT32 * p_tile_index,
OPJ_UINT32 * p_data_size,
OPJ_INT32 * p_tile_x0, OPJ_INT32 * p_tile_y0,
@@ -9528,6 +9534,7 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k,
opj_stream_private_t *p_stream,
opj_event_mgr_t * p_manager)
{
+ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
OPJ_UINT32 l_current_marker = J2K_MS_SOT;
OPJ_UINT32 l_marker_size;
const opj_dec_memory_marker_handler_t * l_marker_handler = 00;
@@ -9827,13 +9834,14 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k,
return OPJ_TRUE;
}
-OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k,
+OPJ_BOOL opj_j2k_decode_tile(void * 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_j2k_t* p_j2k = (opj_j2k_t*)j2k;
OPJ_UINT32 l_current_marker;
OPJ_BYTE l_data [2];
opj_tcp_t * l_tcp;
@@ -10200,11 +10208,12 @@ static OPJ_BOOL opj_j2k_update_image_dimensions(opj_image_t* p_image,
return OPJ_TRUE;
}
-OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k,
+OPJ_BOOL opj_j2k_set_decoded_components(void *j2k,
OPJ_UINT32 numcomps,
const OPJ_UINT32* comps_indices,
opj_event_mgr_t * p_manager)
{
+ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
OPJ_UINT32 i;
OPJ_BOOL* already_mapped;
@@ -10260,12 +10269,13 @@ OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k,
}
-OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
+OPJ_BOOL opj_j2k_set_decode_area(void *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_j2k_t* p_j2k = (opj_j2k_t*)j2k;
opj_cp_t * l_cp = &(p_j2k->m_cp);
opj_image_t * l_image = p_j2k->m_private_image;
OPJ_BOOL ret;
@@ -11200,8 +11210,9 @@ static void opj_j2k_dump_tile_info(opj_tcp_t * l_default_tile,
}
}
-void j2k_dump(opj_j2k_t* p_j2k, OPJ_INT32 flag, FILE* out_stream)
+void j2k_dump(void* j2k, OPJ_INT32 flag, FILE* out_stream)
{
+ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
/* Check if the flag is compatible with j2k file*/
if ((flag & OPJ_JP2_INFO) || (flag & OPJ_JP2_IND)) {
fprintf(out_stream, "Wrong flag\n");
@@ -11391,8 +11402,9 @@ void j2k_dump_image_comp_header(opj_image_comp_t* comp_header,
}
}
-opj_codestream_info_v2_t* j2k_get_cstr_info(opj_j2k_t* p_j2k)
+opj_codestream_info_v2_t* j2k_get_cstr_info(void* j2k)
{
+ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
OPJ_UINT32 compno;
OPJ_UINT32 numcomps = p_j2k->m_private_image->numcomps;
opj_tcp_t *l_default_tile;
@@ -11467,8 +11479,9 @@ opj_codestream_info_v2_t* j2k_get_cstr_info(opj_j2k_t* p_j2k)
return cstr_info;
}
-opj_codestream_index_t* j2k_get_cstr_index(opj_j2k_t* p_j2k)
+opj_codestream_index_t* j2k_get_cstr_index(void* j2k)
{
+ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
opj_codestream_index_t* l_cstr_index = (opj_codestream_index_t*)
opj_calloc(1, sizeof(opj_codestream_index_t));
if (!l_cstr_index) {
@@ -11972,11 +11985,12 @@ static OPJ_BOOL opj_j2k_move_data_from_codec_to_output_image(opj_j2k_t * p_j2k,
return OPJ_TRUE;
}
-OPJ_BOOL opj_j2k_decode(opj_j2k_t * p_j2k,
+OPJ_BOOL opj_j2k_decode(void * j2k,
opj_stream_private_t * p_stream,
opj_image_t * p_image,
opj_event_mgr_t * p_manager)
{
+ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
if (!p_image) {
return OPJ_FALSE;
}
@@ -12030,12 +12044,13 @@ OPJ_BOOL opj_j2k_decode(opj_j2k_t * p_j2k,
return opj_j2k_move_data_from_codec_to_output_image(p_j2k, p_image);
}
-OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k,
+OPJ_BOOL opj_j2k_get_tile(void *j2k,
opj_stream_private_t *p_stream,
opj_image_t* p_image,
opj_event_mgr_t * p_manager,
OPJ_UINT32 tile_index)
{
+ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
OPJ_UINT32 compno;
OPJ_UINT32 l_tile_x, l_tile_y;
opj_image_comp_t* l_img_comp;
@@ -12143,10 +12158,11 @@ OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k,
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_BOOL opj_j2k_set_decoded_resolution_factor(void *j2k,
OPJ_UINT32 res_factor,
opj_event_mgr_t * p_manager)
{
+ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
OPJ_UINT32 it_comp;
p_j2k->m_cp.m_specific_param.m_dec.m_reduce = res_factor;
@@ -12177,10 +12193,11 @@ OPJ_BOOL opj_j2k_set_decoded_resolution_factor(opj_j2k_t *p_j2k,
/* ----------------------------------------------------------------------- */
OPJ_BOOL opj_j2k_encoder_set_extra_options(
- opj_j2k_t *p_j2k,
+ void *j2k,
const char* const* p_options,
opj_event_mgr_t * p_manager)
{
+ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
const char* const* p_option_iter;
if (p_options == NULL) {
@@ -12239,10 +12256,11 @@ OPJ_BOOL opj_j2k_encoder_set_extra_options(
/* ----------------------------------------------------------------------- */
-OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
+OPJ_BOOL opj_j2k_encode(void * j2k,
opj_stream_private_t *p_stream,
opj_event_mgr_t * p_manager)
{
+ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
OPJ_UINT32 i, j;
OPJ_UINT32 l_nb_tiles;
OPJ_SIZE_T l_max_tile_size = 0, l_current_tile_size;
@@ -12347,10 +12365,11 @@ OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
return OPJ_TRUE;
}
-OPJ_BOOL opj_j2k_end_compress(opj_j2k_t *p_j2k,
+OPJ_BOOL opj_j2k_end_compress(void *j2k,
opj_stream_private_t *p_stream,
opj_event_mgr_t * p_manager)
{
+ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
/* customization of the encoding */
if (! opj_j2k_setup_end_compress(p_j2k, p_manager)) {
return OPJ_FALSE;
@@ -12363,11 +12382,12 @@ OPJ_BOOL opj_j2k_end_compress(opj_j2k_t *p_j2k,
return OPJ_TRUE;
}
-OPJ_BOOL opj_j2k_start_compress(opj_j2k_t *p_j2k,
+OPJ_BOOL opj_j2k_start_compress(void *j2k,
opj_stream_private_t *p_stream,
opj_image_t * p_image,
opj_event_mgr_t * p_manager)
{
+ opj_j2k_t* p_j2k = (opj_j2k_t*)j2k;
/* preconditions */
assert(p_j2k != 00);
assert(p_stream != 00);
@@ -13154,13 +13174,14 @@ static OPJ_BOOL opj_j2k_create_tcd(opj_j2k_t *p_j2k,
return OPJ_TRUE;
}
-OPJ_BOOL opj_j2k_write_tile(opj_j2k_t * p_j2k,
+OPJ_BOOL opj_j2k_write_tile(void * 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_j2k_t* p_j2k = (opj_j2k_t*)j2k;
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);
diff --git a/third_party/libopenjpeg/j2k.h b/third_party/libopenjpeg/j2k.h
index 04fba645a..1d824c019 100644
--- a/third_party/libopenjpeg/j2k.h
+++ b/third_party/libopenjpeg/j2k.h
@@ -621,15 +621,15 @@ opj_j2k_t;
/**
Setup the decoder decoding parameters using user parameters.
-Decoding parameters are returned in j2k->cp.
-@param j2k J2K decompressor handle
+Decoding parameters are returned in p_j2k->cp.
+@param p_j2k J2K decompressor handle
@param parameters decompression parameters
*/
-void opj_j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters);
+void opj_j2k_setup_decoder(void *p_j2k, opj_dparameters_t *parameters);
-void opj_j2k_decoder_set_strict_mode(opj_j2k_t *j2k, OPJ_BOOL strict);
+void opj_j2k_decoder_set_strict_mode(void *j2k, OPJ_BOOL strict);
-OPJ_BOOL opj_j2k_set_threads(opj_j2k_t *j2k, OPJ_UINT32 num_threads);
+OPJ_BOOL opj_j2k_set_threads(void *j2k, OPJ_UINT32 num_threads);
/**
* Creates a J2K compression structure
@@ -639,7 +639,7 @@ OPJ_BOOL opj_j2k_set_threads(opj_j2k_t *j2k, OPJ_UINT32 num_threads);
opj_j2k_t* opj_j2k_create_compress(void);
-OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k,
+OPJ_BOOL opj_j2k_setup_encoder(void *p_j2k,
opj_cparameters_t *parameters,
opj_image_t *image,
opj_event_mgr_t * p_manager);
@@ -658,7 +658,7 @@ const char *opj_j2k_convert_progression_order(OPJ_PROG_ORDER prg_order);
* Ends the decompression procedures and possibiliy add data to be read after the
* codestream.
*/
-OPJ_BOOL opj_j2k_end_decompress(opj_j2k_t *j2k,
+OPJ_BOOL opj_j2k_end_decompress(void *j2k,
opj_stream_private_t *p_stream,
opj_event_mgr_t * p_manager);
@@ -666,14 +666,14 @@ OPJ_BOOL opj_j2k_end_decompress(opj_j2k_t *j2k,
* Reads a jpeg2000 codestream header structure.
*
* @param p_stream the stream to read data from.
- * @param p_j2k the jpeg2000 codec.
+ * @param j2k the jpeg2000 codec.
* @param p_image FIXME DOC
* @param p_manager the user event manager.
*
* @return true if the box is valid.
*/
OPJ_BOOL opj_j2k_read_header(opj_stream_private_t *p_stream,
- opj_j2k_t* p_j2k,
+ void* j2k,
opj_image_t** p_image,
opj_event_mgr_t* p_manager);
@@ -681,9 +681,9 @@ OPJ_BOOL opj_j2k_read_header(opj_stream_private_t *p_stream,
/**
* Destroys a jpeg2000 codec.
*
- * @param p_j2k the jpeg20000 structure to destroy.
+ * @param j2k the jpeg20000 structure to destroy.
*/
-void opj_j2k_destroy(opj_j2k_t *p_j2k);
+void opj_j2k_destroy(void *j2k);
/**
* Destroys a codestream index structure.
@@ -694,14 +694,14 @@ void j2k_destroy_cstr_index(opj_codestream_index_t *p_cstr_ind);
/**
* Decode tile data.
- * @param p_j2k the jpeg2000 codec.
+ * @param 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.
*/
-OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k,
+OPJ_BOOL opj_j2k_decode_tile(void * j2k,
OPJ_UINT32 p_tile_index,
OPJ_BYTE * p_data,
OPJ_UINT32 p_data_size,
@@ -710,7 +710,7 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k,
/**
* Reads a tile header.
- * @param p_j2k the jpeg2000 codec.
+ * @param j2k the jpeg2000 codec.
* @param p_tile_index FIXME DOC
* @param p_data_size FIXME DOC
* @param p_tile_x0 FIXME DOC
@@ -722,7 +722,7 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k,
* @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_BOOL opj_j2k_read_tile_header(void * j2k,
OPJ_UINT32 * p_tile_index,
OPJ_UINT32 * p_data_size,
OPJ_INT32 * p_tile_x0,
@@ -737,7 +737,7 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k,
/** Sets the indices of the components to decode.
*
- * @param p_j2k the jpeg2000 codec.
+ * @param 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.
@@ -745,7 +745,7 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k,
*
* @return OPJ_TRUE in case of success.
*/
-OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k,
+OPJ_BOOL opj_j2k_set_decoded_components(void *j2k,
OPJ_UINT32 numcomps,
const OPJ_UINT32* comps_indices,
opj_event_mgr_t * p_manager);
@@ -753,7 +753,7 @@ OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k,
/**
* 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 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).
@@ -763,7 +763,7 @@ OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k,
*
* @return true if the area could be set.
*/
-OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
+OPJ_BOOL opj_j2k_set_decode_area(void *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,
@@ -780,12 +780,12 @@ opj_j2k_t* opj_j2k_create_decompress(void);
/**
* Dump some elements from the J2K decompression structure .
*
- *@param p_j2k the jpeg2000 codec.
+ *@param 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(void* j2k, OPJ_INT32 flag, FILE* out_stream);
@@ -812,20 +812,20 @@ void j2k_dump_image_comp_header(opj_image_comp_t* comp, OPJ_BOOL dev_dump_flag,
/**
* Get the codestream info from a JPEG2000 codec.
*
- *@param p_j2k the component image header to dump.
+ *@param j2k the component image header to dump.
*
*@return the codestream information extract from the jpg2000 codec
*/
-opj_codestream_info_v2_t* j2k_get_cstr_info(opj_j2k_t* p_j2k);
+opj_codestream_info_v2_t* j2k_get_cstr_info(void* j2k);
/**
* Get the codestream index from a JPEG2000 codec.
*
- *@param p_j2k the component image header to dump.
+ *@param j2k the component image header to dump.
*
*@return the codestream index extract from the jpg2000 codec
*/
-opj_codestream_index_t* j2k_get_cstr_index(opj_j2k_t* p_j2k);
+opj_codestream_index_t* j2k_get_cstr_index(void* j2k);
/**
* Decode an image from a JPEG-2000 codestream
@@ -835,46 +835,46 @@ opj_codestream_index_t* j2k_get_cstr_index(opj_j2k_t* p_j2k);
* @param p_manager FIXME DOC
* @return FIXME DOC
*/
-OPJ_BOOL opj_j2k_decode(opj_j2k_t *j2k,
+OPJ_BOOL opj_j2k_decode(void *j2k,
opj_stream_private_t *p_stream,
opj_image_t *p_image,
opj_event_mgr_t *p_manager);
-OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k,
+OPJ_BOOL opj_j2k_get_tile(void *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_BOOL opj_j2k_set_decoded_resolution_factor(void *j2k,
OPJ_UINT32 res_factor,
opj_event_mgr_t * p_manager);
/**
* Specify extra options for the encoder.
*
- * @param p_j2k the jpeg2000 codec.
+ * @param j2k the jpeg2000 codec.
* @param p_options options
* @param p_manager the user event manager
*
* @see opj_encoder_set_extra_options() for more details.
*/
OPJ_BOOL opj_j2k_encoder_set_extra_options(
- opj_j2k_t *p_j2k,
+ void *j2k,
const char* const* p_options,
opj_event_mgr_t * p_manager);
/**
* Writes a tile.
- * @param p_j2k the jpeg2000 codec.
+ * @param 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.
*/
-OPJ_BOOL opj_j2k_write_tile(opj_j2k_t * p_j2k,
+OPJ_BOOL opj_j2k_write_tile(void * j2k,
OPJ_UINT32 p_tile_index,
OPJ_BYTE * p_data,
OPJ_UINT32 p_data_size,
@@ -884,21 +884,21 @@ OPJ_BOOL opj_j2k_write_tile(opj_j2k_t * p_j2k,
/**
* Encodes an image into a JPEG-2000 codestream
*/
-OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
+OPJ_BOOL opj_j2k_encode(void * 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 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_BOOL opj_j2k_start_compress(void *j2k,
opj_stream_private_t *p_stream,
opj_image_t * p_image,
opj_event_mgr_t * p_manager);
@@ -907,7 +907,7 @@ OPJ_BOOL opj_j2k_start_compress(opj_j2k_t *p_j2k,
* 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_BOOL opj_j2k_end_compress(void *j2k,
opj_stream_private_t *cio,
opj_event_mgr_t * p_manager);
diff --git a/third_party/libopenjpeg/jp2.c b/third_party/libopenjpeg/jp2.c
index 44d0c98e5..6db728d18 100644
--- a/third_party/libopenjpeg/jp2.c
+++ b/third_party/libopenjpeg/jp2.c
@@ -1609,11 +1609,12 @@ static OPJ_BOOL opj_jp2_read_colr(opj_jp2_t *jp2,
return OPJ_TRUE;
}
-OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2,
+OPJ_BOOL opj_jp2_decode(void *p_jp2,
opj_stream_private_t *p_stream,
opj_image_t* p_image,
opj_event_mgr_t * p_manager)
{
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
if (!p_image) {
return OPJ_FALSE;
}
@@ -1905,8 +1906,9 @@ static OPJ_BOOL opj_jp2_write_jp(opj_jp2_t *jp2,
/* JP2 decoder interface */
/* ----------------------------------------------------------------------- */
-void opj_jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters)
+void opj_jp2_setup_decoder(void *p_jp2, opj_dparameters_t *parameters)
{
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
/* setup the J2K codec */
opj_j2k_setup_decoder(jp2->j2k, parameters);
@@ -1917,13 +1919,15 @@ void opj_jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters)
OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG;
}
-void opj_jp2_decoder_set_strict_mode(opj_jp2_t *jp2, OPJ_BOOL strict)
+void opj_jp2_decoder_set_strict_mode(void *p_jp2, OPJ_BOOL strict)
{
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
opj_j2k_decoder_set_strict_mode(jp2->j2k, strict);
}
-OPJ_BOOL opj_jp2_set_threads(opj_jp2_t *jp2, OPJ_UINT32 num_threads)
+OPJ_BOOL opj_jp2_set_threads(void *p_jp2, OPJ_UINT32 num_threads)
{
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
return opj_j2k_set_threads(jp2->j2k, num_threads);
}
@@ -1931,11 +1935,12 @@ OPJ_BOOL opj_jp2_set_threads(opj_jp2_t *jp2, OPJ_UINT32 num_threads)
/* JP2 encoder interface */
/* ----------------------------------------------------------------------- */
-OPJ_BOOL opj_jp2_setup_encoder(opj_jp2_t *jp2,
+OPJ_BOOL opj_jp2_setup_encoder(void *p_jp2,
opj_cparameters_t *parameters,
opj_image_t *image,
opj_event_mgr_t * p_manager)
{
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
OPJ_UINT32 i;
OPJ_UINT32 depth_0;
OPJ_UINT32 sign;
@@ -2118,18 +2123,20 @@ OPJ_BOOL opj_jp2_setup_encoder(opj_jp2_t *jp2,
return OPJ_TRUE;
}
-OPJ_BOOL opj_jp2_encode(opj_jp2_t *jp2,
+OPJ_BOOL opj_jp2_encode(void *p_jp2,
opj_stream_private_t *stream,
opj_event_mgr_t * p_manager)
{
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
return opj_j2k_encode(jp2->j2k, stream, p_manager);
}
-OPJ_BOOL opj_jp2_end_decompress(opj_jp2_t *jp2,
+OPJ_BOOL opj_jp2_end_decompress(void *p_jp2,
opj_stream_private_t *cio,
opj_event_mgr_t * p_manager
)
{
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
/* preconditions */
assert(jp2 != 00);
assert(cio != 00);
@@ -2148,11 +2155,12 @@ OPJ_BOOL opj_jp2_end_decompress(opj_jp2_t *jp2,
return opj_j2k_end_decompress(jp2->j2k, cio, p_manager);
}
-OPJ_BOOL opj_jp2_end_compress(opj_jp2_t *jp2,
+OPJ_BOOL opj_jp2_end_compress(void *p_jp2,
opj_stream_private_t *cio,
opj_event_mgr_t * p_manager
)
{
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
/* preconditions */
assert(jp2 != 00);
assert(cio != 00);
@@ -2476,12 +2484,13 @@ static OPJ_BOOL opj_jp2_exec(opj_jp2_t * jp2,
return l_result;
}
-OPJ_BOOL opj_jp2_start_compress(opj_jp2_t *jp2,
+OPJ_BOOL opj_jp2_start_compress(void *p_jp2,
opj_stream_private_t *stream,
opj_image_t * p_image,
opj_event_mgr_t * p_manager
)
{
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
/* preconditions */
assert(jp2 != 00);
assert(stream != 00);
@@ -2854,11 +2863,12 @@ static OPJ_BOOL opj_jp2_read_boxhdr_char(opj_jp2_box_t *box,
}
OPJ_BOOL opj_jp2_read_header(opj_stream_private_t *p_stream,
- opj_jp2_t *jp2,
+ void *p_jp2,
opj_image_t ** p_image,
opj_event_mgr_t * p_manager
)
{
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
/* preconditions */
assert(jp2 != 00);
assert(p_stream != 00);
@@ -2981,7 +2991,7 @@ static OPJ_BOOL opj_jp2_setup_header_reading(opj_jp2_t *jp2,
return OPJ_TRUE;
}
-OPJ_BOOL opj_jp2_read_tile_header(opj_jp2_t * p_jp2,
+OPJ_BOOL opj_jp2_read_tile_header(void *p_jp2,
OPJ_UINT32 * p_tile_index,
OPJ_UINT32 * p_data_size,
OPJ_INT32 * p_tile_x0,
@@ -2994,7 +3004,8 @@ OPJ_BOOL opj_jp2_read_tile_header(opj_jp2_t * p_jp2,
opj_event_mgr_t * p_manager
)
{
- return opj_j2k_read_tile_header(p_jp2->j2k,
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ return opj_j2k_read_tile_header(jp2->j2k,
p_tile_index,
p_data_size,
p_tile_x0, p_tile_y0,
@@ -3005,7 +3016,7 @@ OPJ_BOOL opj_jp2_read_tile_header(opj_jp2_t * p_jp2,
p_manager);
}
-OPJ_BOOL opj_jp2_write_tile(opj_jp2_t *p_jp2,
+OPJ_BOOL opj_jp2_write_tile(void *p_jp2,
OPJ_UINT32 p_tile_index,
OPJ_BYTE * p_data,
OPJ_UINT32 p_data_size,
@@ -3014,11 +3025,12 @@ OPJ_BOOL opj_jp2_write_tile(opj_jp2_t *p_jp2,
)
{
- return opj_j2k_write_tile(p_jp2->j2k, p_tile_index, p_data, p_data_size,
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ return opj_j2k_write_tile(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_BOOL opj_jp2_decode_tile(void *p_jp2,
OPJ_UINT32 p_tile_index,
OPJ_BYTE * p_data,
OPJ_UINT32 p_data_size,
@@ -3026,12 +3038,14 @@ OPJ_BOOL opj_jp2_decode_tile(opj_jp2_t * p_jp2,
opj_event_mgr_t * p_manager
)
{
- return opj_j2k_decode_tile(p_jp2->j2k, p_tile_index, p_data, p_data_size,
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ return opj_j2k_decode_tile(jp2->j2k, p_tile_index, p_data, p_data_size,
p_stream, p_manager);
}
-void opj_jp2_destroy(opj_jp2_t *jp2)
+void opj_jp2_destroy(void *p_jp2)
{
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
if (jp2) {
/* destroy the J2K codec */
opj_j2k_destroy(jp2->j2k);
@@ -3098,34 +3112,37 @@ void opj_jp2_destroy(opj_jp2_t *jp2)
}
}
-OPJ_BOOL opj_jp2_set_decoded_components(opj_jp2_t *p_jp2,
+OPJ_BOOL opj_jp2_set_decoded_components(void *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,
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ return opj_j2k_set_decoded_components(jp2->j2k,
numcomps, comps_indices,
p_manager);
}
-OPJ_BOOL opj_jp2_set_decode_area(opj_jp2_t *p_jp2,
+OPJ_BOOL opj_jp2_set_decode_area(void *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,
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ return opj_j2k_set_decode_area(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_BOOL opj_jp2_get_tile(void *jp2,
opj_stream_private_t *p_stream,
opj_image_t* p_image,
opj_event_mgr_t * p_manager,
OPJ_UINT32 tile_index
)
{
+ opj_jp2_t *p_jp2 = (opj_jp2_t*)jp2;
if (!p_image) {
return OPJ_FALSE;
}
@@ -3234,41 +3251,46 @@ opj_jp2_t* opj_jp2_create(OPJ_BOOL p_is_decoder)
return jp2;
}
-void jp2_dump(opj_jp2_t* p_jp2, OPJ_INT32 flag, FILE* out_stream)
+void jp2_dump(void* p_jp2, OPJ_INT32 flag, FILE* out_stream)
{
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
/* preconditions */
assert(p_jp2 != 00);
- j2k_dump(p_jp2->j2k,
+ j2k_dump(jp2->j2k,
flag,
out_stream);
}
-opj_codestream_index_t* jp2_get_cstr_index(opj_jp2_t* p_jp2)
+opj_codestream_index_t* jp2_get_cstr_index(void* p_jp2)
{
- return j2k_get_cstr_index(p_jp2->j2k);
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ return j2k_get_cstr_index(jp2->j2k);
}
-opj_codestream_info_v2_t* jp2_get_cstr_info(opj_jp2_t* p_jp2)
+opj_codestream_info_v2_t* jp2_get_cstr_info(void* p_jp2)
{
- return j2k_get_cstr_info(p_jp2->j2k);
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ return j2k_get_cstr_info(jp2->j2k);
}
-OPJ_BOOL opj_jp2_set_decoded_resolution_factor(opj_jp2_t *p_jp2,
+OPJ_BOOL opj_jp2_set_decoded_resolution_factor(void *p_jp2,
OPJ_UINT32 res_factor,
opj_event_mgr_t * p_manager)
{
- return opj_j2k_set_decoded_resolution_factor(p_jp2->j2k, res_factor, p_manager);
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ return opj_j2k_set_decoded_resolution_factor(jp2->j2k, res_factor, p_manager);
}
/* ----------------------------------------------------------------------- */
OPJ_BOOL opj_jp2_encoder_set_extra_options(
- opj_jp2_t *p_jp2,
+ void *p_jp2,
const char* const* p_options,
opj_event_mgr_t * p_manager)
{
- return opj_j2k_encoder_set_extra_options(p_jp2->j2k, p_options, p_manager);
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ return opj_j2k_encoder_set_extra_options(jp2->j2k, p_options, p_manager);
}
/* ----------------------------------------------------------------------- */
diff --git a/third_party/libopenjpeg/jp2.h b/third_party/libopenjpeg/jp2.h
index 173f25119..fd9175a4e 100644
--- a/third_party/libopenjpeg/jp2.h
+++ b/third_party/libopenjpeg/jp2.h
@@ -230,38 +230,38 @@ opj_jp2_img_header_writer_handler_t;
/**
Setup the decoder decoding parameters using user parameters.
Decoding parameters are returned in jp2->j2k->cp.
-@param jp2 JP2 decompressor handle
+@param p_jp2 JP2 decompressor handle
@param parameters decompression parameters
*/
-void opj_jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters);
+void opj_jp2_setup_decoder(void *p_jp2, opj_dparameters_t *parameters);
/**
Set the strict mode parameter. When strict mode is enabled, the entire
bitstream must be decoded or an error is returned. When it is disabled,
the decoder will decode partial bitstreams.
-@param jp2 JP2 decompressor handle
+@param p_jp2 JP2 decompressor handle
@param strict OPJ_TRUE for strict mode
*/
-void opj_jp2_decoder_set_strict_mode(opj_jp2_t *jp2, OPJ_BOOL strict);
+void opj_jp2_decoder_set_strict_mode(void *p_jp2, OPJ_BOOL strict);
/** Allocates worker threads for the compressor/decompressor.
*
- * @param jp2 JP2 decompressor handle
+ * @param p_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);
+OPJ_BOOL opj_jp2_set_threads(void *p_jp2, OPJ_UINT32 num_threads);
/**
* Decode an image from a JPEG-2000 file stream
- * @param jp2 JP2 decompressor handle
+ * @param p_jp2 JP2 decompressor handle
* @param p_stream FIXME DOC
* @param p_image FIXME DOC
* @param p_manager FIXME DOC
*
* @return Returns a decoded image if successful, returns NULL otherwise
*/
-OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2,
+OPJ_BOOL opj_jp2_decode(void *p_jp2,
opj_stream_private_t *p_stream,
opj_image_t* p_image,
opj_event_mgr_t * p_manager);
@@ -270,25 +270,25 @@ OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2,
* 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 p_jp2 JP2 compressor handle
* @param parameters compression parameters
* @param image input filled image
* @param p_manager FIXME DOC
* @return OPJ_TRUE if successful, OPJ_FALSE otherwise
*/
-OPJ_BOOL opj_jp2_setup_encoder(opj_jp2_t *jp2,
+OPJ_BOOL opj_jp2_setup_encoder(void *p_jp2,
opj_cparameters_t *parameters,
opj_image_t *image,
opj_event_mgr_t * p_manager);
/**
Encode an image into a JPEG-2000 file stream
-@param jp2 JP2 compressor handle
+@param p_jp2 JP2 compressor handle
@param stream Output buffer stream
@param p_manager event manager
@return Returns true if successful, returns false otherwise
*/
-OPJ_BOOL opj_jp2_encode(opj_jp2_t *jp2,
+OPJ_BOOL opj_jp2_encode(void *p_jp2,
opj_stream_private_t *stream,
opj_event_mgr_t * p_manager);
@@ -296,14 +296,14 @@ OPJ_BOOL opj_jp2_encode(opj_jp2_t *jp2,
/**
* Starts a compression scheme, i.e. validates the codec parameters, writes the header.
*
- * @param jp2 the jpeg2000 file codec.
+ * @param p_jp2 the jpeg2000 file codec.
* @param stream the stream object.
* @param p_image FIXME DOC
* @param p_manager FIXME DOC
*
* @return true if the codec is valid.
*/
-OPJ_BOOL opj_jp2_start_compress(opj_jp2_t *jp2,
+OPJ_BOOL opj_jp2_start_compress(void *p_jp2,
opj_stream_private_t *stream,
opj_image_t * p_image,
opj_event_mgr_t * p_manager);
@@ -313,7 +313,7 @@ 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_BOOL opj_jp2_end_compress(void *p_jp2,
opj_stream_private_t *cio,
opj_event_mgr_t * p_manager);
@@ -323,7 +323,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(void *p_jp2,
opj_stream_private_t *cio,
opj_event_mgr_t * p_manager);
@@ -331,20 +331,20 @@ OPJ_BOOL opj_jp2_end_decompress(opj_jp2_t *jp2,
* Reads a jpeg2000 file header structure.
*
* @param p_stream the stream to read data from.
- * @param jp2 the jpeg2000 file header structure.
+ * @param p_jp2 the jpeg2000 file header structure.
* @param p_image FIXME DOC
* @param p_manager the user event manager.
*
* @return true if the box is valid.
*/
OPJ_BOOL opj_jp2_read_header(opj_stream_private_t *p_stream,
- opj_jp2_t *jp2,
+ void *p_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 p_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.
@@ -352,7 +352,7 @@ OPJ_BOOL opj_jp2_read_header(opj_stream_private_t *p_stream,
*
* @return OPJ_TRUE in case of success.
*/
-OPJ_BOOL opj_jp2_set_decoded_components(opj_jp2_t *jp2,
+OPJ_BOOL opj_jp2_set_decoded_components(void *p_jp2,
OPJ_UINT32 numcomps,
const OPJ_UINT32* comps_indices,
opj_event_mgr_t * p_manager);
@@ -371,7 +371,7 @@ OPJ_BOOL opj_jp2_set_decoded_components(opj_jp2_t *jp2,
* @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_BOOL opj_jp2_read_tile_header(void * p_jp2,
OPJ_UINT32 * p_tile_index,
OPJ_UINT32 * p_data_size,
OPJ_INT32 * p_tile_x0,
@@ -393,7 +393,7 @@ 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_BOOL opj_jp2_write_tile(void *p_jp2,
OPJ_UINT32 p_tile_index,
OPJ_BYTE * p_data,
OPJ_UINT32 p_data_size,
@@ -411,7 +411,7 @@ 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_BOOL opj_jp2_decode_tile(void * p_jp2,
OPJ_UINT32 p_tile_index,
OPJ_BYTE * p_data,
OPJ_UINT32 p_data_size,
@@ -427,9 +427,9 @@ opj_jp2_t* opj_jp2_create(OPJ_BOOL p_is_decoder);
/**
Destroy a JP2 decompressor handle
-@param jp2 JP2 decompressor handle to destroy
+@param p_jp2 JP2 decompressor handle to destroy
*/
-void opj_jp2_destroy(opj_jp2_t *jp2);
+void opj_jp2_destroy(void *p_jp2);
/**
@@ -445,7 +445,7 @@ 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_BOOL opj_jp2_set_decode_area(void *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,
@@ -454,7 +454,7 @@ OPJ_BOOL opj_jp2_set_decode_area(opj_jp2_t *p_jp2,
/**
*
*/
-OPJ_BOOL opj_jp2_get_tile(opj_jp2_t *p_jp2,
+OPJ_BOOL opj_jp2_get_tile(void *jp2,
opj_stream_private_t *p_stream,
opj_image_t* p_image,
opj_event_mgr_t * p_manager,
@@ -464,7 +464,7 @@ OPJ_BOOL opj_jp2_get_tile(opj_jp2_t *p_jp2,
/**
*
*/
-OPJ_BOOL opj_jp2_set_decoded_resolution_factor(opj_jp2_t *p_jp2,
+OPJ_BOOL opj_jp2_set_decoded_resolution_factor(void *p_jp2,
OPJ_UINT32 res_factor,
opj_event_mgr_t * p_manager);
@@ -478,7 +478,7 @@ OPJ_BOOL opj_jp2_set_decoded_resolution_factor(opj_jp2_t *p_jp2,
* @see opj_encoder_set_extra_options() for more details.
*/
OPJ_BOOL opj_jp2_encoder_set_extra_options(
- opj_jp2_t *p_jp2,
+ void *p_jp2,
const char* const* p_options,
opj_event_mgr_t * p_manager);
@@ -492,7 +492,7 @@ OPJ_BOOL opj_jp2_encoder_set_extra_options(
*@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(void* p_jp2, OPJ_INT32 flag, FILE* out_stream);
/**
* Get the codestream info from a JPEG2000 codec.
@@ -501,7 +501,7 @@ void jp2_dump(opj_jp2_t* p_jp2, OPJ_INT32 flag, FILE* out_stream);
*
*@return the codestream information extract from the jpg2000 codec
*/
-opj_codestream_info_v2_t* jp2_get_cstr_info(opj_jp2_t* p_jp2);
+opj_codestream_info_v2_t* jp2_get_cstr_info(void* p_jp2);
/**
* Get the codestream index from a JPEG2000 codec.
@@ -510,7 +510,7 @@ opj_codestream_info_v2_t* jp2_get_cstr_info(opj_jp2_t* p_jp2);
*
*@return the codestream index extract from the jpg2000 codec
*/
-opj_codestream_index_t* jp2_get_cstr_index(opj_jp2_t* p_jp2);
+opj_codestream_index_t* jp2_get_cstr_index(void* p_jp2);
/*@}*/
diff --git a/third_party/libopenjpeg/openjpeg.c b/third_party/libopenjpeg/openjpeg.c
index 29d3ee528..9dd4256d7 100644
--- a/third_party/libopenjpeg/openjpeg.c
+++ b/third_party/libopenjpeg/openjpeg.c
@@ -189,85 +189,48 @@ opj_codec_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT p_format)
switch (p_format) {
case OPJ_CODEC_J2K:
- l_codec->opj_dump_codec = (void (*)(void*, OPJ_INT32, FILE*)) j2k_dump;
+ l_codec->opj_dump_codec = j2k_dump;
- l_codec->opj_get_codec_info = (opj_codestream_info_v2_t* (*)(
- void*)) j2k_get_cstr_info;
+ l_codec->opj_get_codec_info = j2k_get_cstr_info;
- l_codec->opj_get_codec_index = (opj_codestream_index_t* (*)(
- void*)) j2k_get_cstr_index;
+ l_codec->opj_get_codec_index = 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_decode = 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;
+ 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;
+ 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_destroy = opj_j2k_destroy;
l_codec->m_codec_data.m_decompression.opj_setup_decoder =
- (void (*)(void *, opj_dparameters_t *)) opj_j2k_setup_decoder;
+ opj_j2k_setup_decoder;
l_codec->m_codec_data.m_decompression.opj_decoder_set_strict_mode =
- (void (*)(void *, OPJ_BOOL)) opj_j2k_decoder_set_strict_mode;
+ opj_j2k_decoder_set_strict_mode;
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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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->opj_set_threads = opj_j2k_set_threads;
l_codec->m_codec = opj_j2k_create_decompress();
@@ -280,85 +243,47 @@ opj_codec_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT p_format)
case OPJ_CODEC_JP2:
/* get a JP2 decoder handle */
- l_codec->opj_dump_codec = (void (*)(void*, OPJ_INT32, FILE*)) jp2_dump;
+ l_codec->opj_dump_codec = jp2_dump;
- l_codec->opj_get_codec_info = (opj_codestream_info_v2_t* (*)(
- void*)) jp2_get_cstr_info;
+ l_codec->opj_get_codec_info = jp2_get_cstr_info;
- l_codec->opj_get_codec_index = (opj_codestream_index_t* (*)(
- void*)) jp2_get_cstr_index;
+ l_codec->opj_get_codec_index = 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_decode = 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;
+ 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;
+ 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;
+ 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;
+ 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_destroy = opj_jp2_destroy;
l_codec->m_codec_data.m_decompression.opj_setup_decoder =
- (void (*)(void *, opj_dparameters_t *)) opj_jp2_setup_decoder;
+ opj_jp2_setup_decoder;
l_codec->m_codec_data.m_decompression.opj_decoder_set_strict_mode =
- (void (*)(void *, OPJ_BOOL)) opj_jp2_decoder_set_strict_mode;
+ opj_jp2_decoder_set_strict_mode;
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;
+ 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;
+ 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;
+ 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;
+ 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->opj_set_threads = opj_jp2_set_threads;
l_codec->m_codec = opj_jp2_create(OPJ_TRUE);
@@ -662,41 +587,25 @@ opj_codec_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT p_format)
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_data.m_compression.opj_encoder_set_extra_options = (OPJ_BOOL(
- *)(void *,
- const char* const*,
- struct opj_event_mgr *)) opj_j2k_encoder_set_extra_options;
-
- l_codec->opj_set_threads =
- (OPJ_BOOL(*)(void * p_codec, OPJ_UINT32 num_threads)) opj_j2k_set_threads;
+ l_codec->m_codec_data.m_compression.opj_encode = opj_j2k_encode;
+
+ l_codec->m_codec_data.m_compression.opj_end_compress =
+ opj_j2k_end_compress;
+
+ l_codec->m_codec_data.m_compression.opj_start_compress =
+ opj_j2k_start_compress;
+
+ l_codec->m_codec_data.m_compression.opj_write_tile = opj_j2k_write_tile;
+
+ l_codec->m_codec_data.m_compression.opj_destroy = opj_j2k_destroy;
+
+ l_codec->m_codec_data.m_compression.opj_setup_encoder =
+ opj_j2k_setup_encoder;
+
+ l_codec->m_codec_data.m_compression.opj_encoder_set_extra_options =
+ opj_j2k_encoder_set_extra_options;
+
+ l_codec->opj_set_threads = opj_j2k_set_threads;
l_codec->m_codec = opj_j2k_create_compress();
if (! l_codec->m_codec) {
@@ -708,41 +617,25 @@ opj_codec_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT p_format)
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_data.m_compression.opj_encoder_set_extra_options = (OPJ_BOOL(
- *)(void *,
- const char* const*,
- struct opj_event_mgr *)) opj_jp2_encoder_set_extra_options;
-
- l_codec->opj_set_threads =
- (OPJ_BOOL(*)(void * p_codec, OPJ_UINT32 num_threads)) opj_jp2_set_threads;
+ l_codec->m_codec_data.m_compression.opj_encode = opj_jp2_encode;
+
+ l_codec->m_codec_data.m_compression.opj_end_compress =
+ opj_jp2_end_compress;
+
+ l_codec->m_codec_data.m_compression.opj_start_compress =
+ opj_jp2_start_compress;
+
+ l_codec->m_codec_data.m_compression.opj_write_tile = opj_jp2_write_tile;
+
+ l_codec->m_codec_data.m_compression.opj_destroy = opj_jp2_destroy;
+
+ l_codec->m_codec_data.m_compression.opj_setup_encoder =
+ opj_jp2_setup_encoder;
+
+ l_codec->m_codec_data.m_compression.opj_encoder_set_extra_options =
+ opj_jp2_encoder_set_extra_options;
+
+ l_codec->opj_set_threads = opj_jp2_set_threads;
l_codec->m_codec = opj_jp2_create(OPJ_FALSE);
if (! l_codec->m_codec) {
diff --git a/third_party/libtiff/0000-build-config.patch b/third_party/libtiff/0000-build-config.patch
index f66235abf..c3925b0f0 100644
--- a/third_party/libtiff/0000-build-config.patch
+++ b/third_party/libtiff/0000-build-config.patch
@@ -280,3 +280,15 @@ diff a/third_party/libtiff/tiffconf.h b/third_party/libtiff/tiffconf.h
+#define IPTC_SUPPORT
+
+#endif /* _TIFFCONF_ */
+diff --git a/third_party/libtiff/tif_hash_set.c b/third_party/libtiff/tif_hash_set.c
+--- a/third_party/libtiff/tif_hash_set.c
++++ b/third_party/libtiff/tif_hash_set.c
+@@ -26,7 +26,7 @@
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+-#include "tif_config.h"
++#include "tiffconf.h"
+
+ #include "tif_hash_set.h"
+
diff --git a/third_party/libtiff/METADATA b/third_party/libtiff/METADATA
new file mode 100644
index 000000000..35e01b99a
--- /dev/null
+++ b/third_party/libtiff/METADATA
@@ -0,0 +1,17 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Metadata for CVEs that are fixed or don't affect libtiff.
+
+third_party {
+ security {
+ # PDFium's copy of libtiff does not ship tools like tiffcrop.
+ mitigated_security_patch: "CVE-2022-48281"
+ mitigated_security_patch: "CVE-2023-1916"
+ mitigated_security_patch: "CVE-2023-25433"
+ mitigated_security_patch: "CVE-2023-25434"
+ mitigated_security_patch: "CVE-2023-25435"
+ mitigated_security_patch: "CVE-2023-26965"
+ }
+} \ No newline at end of file
diff --git a/third_party/libtiff/README.pdfium b/third_party/libtiff/README.pdfium
index a66a69211..9eec6dc5f 100644
--- a/third_party/libtiff/README.pdfium
+++ b/third_party/libtiff/README.pdfium
@@ -1,8 +1,9 @@
Name: LibTIFF
URL: http://www.simplesystems.org/libtiff/
-Version: 4.5.0
-CPEPrefix: cpe:/a:libtiff:libtiff:4.5.0
+Version: 4.5.1
+CPEPrefix: cpe:/a:libtiff:libtiff:4.5.1
Security Critical: yes
+Shipped: yes
License: BSD
Description:
diff --git a/third_party/libtiff/tif_close.c b/third_party/libtiff/tif_close.c
index 06aa29f56..907d7f139 100644
--- a/third_party/libtiff/tif_close.c
+++ b/third_party/libtiff/tif_close.c
@@ -51,8 +51,7 @@ void TIFFCleanup(TIFF *tif)
(*tif->tif_cleanup)(tif);
TIFFFreeDirectory(tif);
- TIFFHashSetDestroy(tif->tif_map_dir_offset_to_number);
- TIFFHashSetDestroy(tif->tif_map_dir_number_to_offset);
+ _TIFFCleanupIFDOffsetAndNumberMaps(tif);
/*
* Clean up client info links.
@@ -115,6 +114,24 @@ void TIFFCleanup(TIFF *tif)
}
/************************************************************************/
+/* _TIFFCleanupIFDOffsetAndNumberMaps() */
+/************************************************************************/
+
+void _TIFFCleanupIFDOffsetAndNumberMaps(TIFF *tif)
+{
+ if (tif->tif_map_dir_offset_to_number)
+ {
+ TIFFHashSetDestroy(tif->tif_map_dir_offset_to_number);
+ tif->tif_map_dir_offset_to_number = NULL;
+ }
+ if (tif->tif_map_dir_number_to_offset)
+ {
+ TIFFHashSetDestroy(tif->tif_map_dir_number_to_offset);
+ tif->tif_map_dir_number_to_offset = NULL;
+ }
+}
+
+/************************************************************************/
/* TIFFClose() */
/************************************************************************/
@@ -130,9 +147,12 @@ void TIFFCleanup(TIFF *tif)
void TIFFClose(TIFF *tif)
{
- TIFFCloseProc closeproc = tif->tif_closeproc;
- thandle_t fd = tif->tif_clientdata;
+ if (tif != NULL)
+ {
+ TIFFCloseProc closeproc = tif->tif_closeproc;
+ thandle_t fd = tif->tif_clientdata;
- TIFFCleanup(tif);
- (void)(*closeproc)(fd);
+ TIFFCleanup(tif);
+ (void)(*closeproc)(fd);
+ }
}
diff --git a/third_party/libtiff/tif_dir.c b/third_party/libtiff/tif_dir.c
index 4a3665453..850062183 100644
--- a/third_party/libtiff/tif_dir.c
+++ b/third_party/libtiff/tif_dir.c
@@ -192,11 +192,11 @@ static int setExtraSamples(TIFF *tif, va_list ap, uint32_t *v)
static uint16_t countInkNamesString(TIFF *tif, uint32_t slen, const char *s)
{
uint16_t i = 0;
- const char *ep = s + slen;
- const char *cp = s;
if (slen > 0)
{
+ const char *ep = s + slen;
+ const char *cp = s;
do
{
for (; cp < ep && *cp != '\0'; cp++)
@@ -1621,7 +1621,7 @@ void TIFFFreeDirectory(TIFF *tif)
TIFFDirectory *td = &tif->tif_dir;
int i;
- _TIFFmemset(td->td_fieldsset, 0, FIELD_SETLONGS);
+ _TIFFmemset(td->td_fieldsset, 0, sizeof(td->td_fieldsset));
CleanupField(td_sminsamplevalue);
CleanupField(td_smaxsamplevalue);
CleanupField(td_colormap[0]);
@@ -1702,6 +1702,12 @@ int TIFFCreateCustomDirectory(TIFF *tif, const TIFFFieldArray *infoarray)
tif->tif_curoff = 0;
tif->tif_row = (uint32_t)-1;
tif->tif_curstrip = (uint32_t)-1;
+ /* invalidate directory index */
+ tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
+ /* invalidate IFD loop lists */
+ _TIFFCleanupIFDOffsetAndNumberMaps(tif);
+ /* To be able to return from SubIFD or custom-IFD to main-IFD */
+ tif->tif_setdirectory_force_absolute = TRUE;
return 0;
}
@@ -2022,29 +2028,78 @@ tdir_t TIFFNumberOfDirectories(TIFF *tif)
int TIFFSetDirectory(TIFF *tif, tdir_t dirn)
{
uint64_t nextdiroff;
- tdir_t nextdirnum;
+ tdir_t nextdirnum = 0;
tdir_t n;
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- nextdiroff = tif->tif_header.classic.tiff_diroff;
+ if (tif->tif_setdirectory_force_absolute)
+ {
+ /* tif_setdirectory_force_absolute=1 will force parsing the main IFD
+ * chain from the beginning, thus IFD directory list needs to be cleared
+ * from possible SubIFD offsets.
+ */
+ _TIFFCleanupIFDOffsetAndNumberMaps(tif); /* invalidate IFD loop lists */
+ }
+
+ /* Even faster path, if offset is available within IFD loop hash list. */
+ if (!tif->tif_setdirectory_force_absolute &&
+ _TIFFGetOffsetFromDirNumber(tif, dirn, &nextdiroff))
+ {
+ /* Set parameters for following TIFFReadDirectory() below. */
+ tif->tif_nextdiroff = nextdiroff;
+ tif->tif_curdir = dirn;
+ /* Reset to relative stepping */
+ tif->tif_setdirectory_force_absolute = FALSE;
+ }
else
- nextdiroff = tif->tif_header.big.tiff_diroff;
- nextdirnum = 0;
- for (n = dirn; n > 0 && nextdiroff != 0; n--)
- if (!TIFFAdvanceDirectory(tif, &nextdiroff, NULL, &nextdirnum))
+ {
+
+ /* Fast path when we just advance relative to the current directory:
+ * start at the current dir offset and continue to seek from there.
+ * Check special cases when relative is not allowed:
+ * - jump back from SubIFD or custom directory
+ * - right after TIFFWriteDirectory() jump back to that directory
+ * using TIFFSetDirectory() */
+ const int relative = (dirn >= tif->tif_curdir) &&
+ (tif->tif_diroff != 0) &&
+ !tif->tif_setdirectory_force_absolute;
+
+ if (relative)
+ {
+ nextdiroff = tif->tif_diroff;
+ dirn -= tif->tif_curdir;
+ nextdirnum = tif->tif_curdir;
+ }
+ else if (!(tif->tif_flags & TIFF_BIGTIFF))
+ nextdiroff = tif->tif_header.classic.tiff_diroff;
+ else
+ nextdiroff = tif->tif_header.big.tiff_diroff;
+
+ /* Reset to relative stepping */
+ tif->tif_setdirectory_force_absolute = FALSE;
+
+ for (n = dirn; n > 0 && nextdiroff != 0; n--)
+ if (!TIFFAdvanceDirectory(tif, &nextdiroff, NULL, &nextdirnum))
+ return (0);
+ /* If the n-th directory could not be reached (does not exist),
+ * return here without touching anything further. */
+ if (nextdiroff == 0 || n > 0)
return (0);
- /* If the n-th directory could not be reached (does not exist),
- * return here without touching anything further. */
- if (nextdiroff == 0 || n > 0)
- return (0);
- tif->tif_nextdiroff = nextdiroff;
- /*
- * Set curdir to the actual directory index. The
- * -1 is because TIFFReadDirectory will increment
- * tif_curdir after successfully reading the directory.
- */
- tif->tif_curdir = (dirn - n) - 1;
+ tif->tif_nextdiroff = nextdiroff;
+
+ /* Set curdir to the actual directory index. */
+ if (relative)
+ tif->tif_curdir += dirn - n;
+ else
+ tif->tif_curdir = dirn - n;
+ }
+
+ /* The -1 decrement is because TIFFReadDirectory will increment
+ * tif_curdir after successfully reading the directory. */
+ if (tif->tif_curdir == 0)
+ tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
+ else
+ tif->tif_curdir--;
return (TIFFReadDirectory(tif));
}
@@ -2088,8 +2143,8 @@ int TIFFSetSubDirectory(TIFF *tif, uint64_t diroff)
tif->tif_nextdiroff = diroff;
retval = TIFFReadDirectory(tif);
/* If failed, curdir was not incremented in TIFFReadDirectory(), so set it
- * back. */
- if (!retval)
+ * back, but leave it for diroff==0. */
+ if (!retval && diroff != 0)
{
if (tif->tif_curdir == TIFF_NON_EXISTENT_DIR_NUMBER)
tif->tif_curdir = 0;
@@ -2100,10 +2155,12 @@ int TIFFSetSubDirectory(TIFF *tif, uint64_t diroff)
{
/* Reset IFD list to start new one for SubIFD chain and also start
* SubIFD chain with tif_curdir=0. */
- tif->tif_dirnumber = 0;
+ _TIFFCleanupIFDOffsetAndNumberMaps(tif); /* invalidate IFD loop lists */
tif->tif_curdir = 0; /* first directory of new chain */
/* add this offset to new IFD list */
_TIFFCheckDirNumberAndOffset(tif, tif->tif_curdir, diroff);
+ /* To be able to return from SubIFD or custom-IFD to main-IFD */
+ tif->tif_setdirectory_force_absolute = TRUE;
}
return (retval);
}
@@ -2139,6 +2196,13 @@ int TIFFUnlinkDirectory(TIFF *tif, tdir_t dirn)
"Can not unlink directory in read-only file");
return (0);
}
+ if (dirn == 0)
+ {
+ TIFFErrorExtR(tif, module,
+ "For TIFFUnlinkDirectory() first directory starts with "
+ "number 1 and not 0");
+ return (0);
+ }
/*
* Go to the directory before the one we want
* to unlink and nab the offset of the link
@@ -2201,6 +2265,17 @@ int TIFFUnlinkDirectory(TIFF *tif, tdir_t dirn)
return (0);
}
}
+
+ /* For dirn=1 (first directory) also update the libtiff internal
+ * base offset variables. */
+ if (dirn == 1)
+ {
+ if (!(tif->tif_flags & TIFF_BIGTIFF))
+ tif->tif_header.classic.tiff_diroff = (uint32_t)nextdir;
+ else
+ tif->tif_header.big.tiff_diroff = nextdir;
+ }
+
/*
* Leave directory state setup safely. We don't have
* facilities for doing inserting and removing directories,
@@ -2227,5 +2302,7 @@ int TIFFUnlinkDirectory(TIFF *tif, tdir_t dirn)
tif->tif_curoff = 0;
tif->tif_row = (uint32_t)-1;
tif->tif_curstrip = (uint32_t)-1;
+ tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
+ _TIFFCleanupIFDOffsetAndNumberMaps(tif); /* invalidate IFD loop lists */
return (1);
}
diff --git a/third_party/libtiff/tif_dir.h b/third_party/libtiff/tif_dir.h
index fad1eb02e..9eaf22f8e 100644
--- a/third_party/libtiff/tif_dir.h
+++ b/third_party/libtiff/tif_dir.h
@@ -70,9 +70,9 @@ typedef struct
*/
typedef struct
{
-#define FIELD_SETLONGS 4
+#define FIELDSET_ITEMS 4
/* bit vector of fields that are set */
- unsigned long td_fieldsset[FIELD_SETLONGS];
+ uint32_t td_fieldsset[FIELDSET_ITEMS];
uint32_t td_imagewidth, td_imagelength, td_imagedepth;
uint32_t td_tilewidth, td_tilelength, td_tiledepth;
@@ -202,9 +202,9 @@ typedef struct
*/
#define FIELD_PSEUDO 0
-#define FIELD_LAST (32 * FIELD_SETLONGS - 1)
+#define FIELD_LAST (32 * FIELDSET_ITEMS - 1)
-#define BITn(n) (((unsigned long)1L) << ((n)&0x1f))
+#define BITn(n) (((uint32_t)1L) << ((n)&0x1f))
#define BITFIELDn(tif, n) ((tif)->tif_dir.td_fieldsset[(n) / 32])
#define TIFFFieldSet(tif, field) (BITFIELDn(tif, field) & BITn(field))
#define TIFFSetFieldBit(tif, field) (BITFIELDn(tif, field) |= BITn(field))
@@ -329,6 +329,10 @@ extern "C"
uint64_t diroff);
extern int _TIFFGetDirNumberFromOffset(TIFF *tif, uint64_t diroff,
tdir_t *dirn);
+ extern int _TIFFGetOffsetFromDirNumber(TIFF *tif, tdir_t dirn,
+ uint64_t *diroff);
+ extern int _TIFFRemoveEntryFromDirectoryListByOffset(TIFF *tif,
+ uint64_t diroff);
#if defined(__cplusplus)
}
diff --git a/third_party/libtiff/tif_dirinfo.c b/third_party/libtiff/tif_dirinfo.c
index 6a15c766a..0e705e81e 100644
--- a/third_party/libtiff/tif_dirinfo.c
+++ b/third_party/libtiff/tif_dirinfo.c
@@ -63,351 +63,283 @@ static const TIFFFieldArray gpsFieldArray;
*
*/
+/* clang-format off */ /* for better readability of tag comments */
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_IGNORE, 1, 0, "OldSubfileType", NULL},
- {TIFFTAG_IMAGEWIDTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_IMAGEDIMENSIONS, 0, 0, "ImageWidth", NULL},
- {TIFFTAG_IMAGELENGTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_IMAGEDIMENSIONS, 1, 0, "ImageLength", NULL},
- {TIFFTAG_BITSPERSAMPLE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_BITSPERSAMPLE, 0, 0, "BitsPerSample", NULL},
- {TIFFTAG_COMPRESSION, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_COMPRESSION, 0, 0, "Compression", NULL},
- {TIFFTAG_PHOTOMETRIC, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_PHOTOMETRIC, 0, 0,
- "PhotometricInterpretation", NULL},
- {TIFFTAG_THRESHHOLDING, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_THRESHHOLDING, 1, 0, "Threshholding", NULL},
- {TIFFTAG_CELLWIDTH, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CellWidth", NULL},
- {TIFFTAG_CELLLENGTH, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CellLength", NULL},
- {TIFFTAG_FILLORDER, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_FILLORDER, 0, 0, "FillOrder", NULL},
- {TIFFTAG_DOCUMENTNAME, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DocumentName", NULL},
- {TIFFTAG_IMAGEDESCRIPTION, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageDescription", NULL},
- {TIFFTAG_MAKE, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Make", NULL},
- {TIFFTAG_MODEL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Model", NULL},
- {TIFFTAG_STRIPOFFSETS, -1, -1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED,
- TIFF_SETGET_UNDEFINED, FIELD_STRIPOFFSETS, 0, 0, "StripOffsets", NULL},
- {TIFFTAG_ORIENTATION, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_ORIENTATION, 0, 0, "Orientation", NULL},
- {TIFFTAG_SAMPLESPERPIXEL, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_SAMPLESPERPIXEL, 0, 0, "SamplesPerPixel",
- NULL},
- {TIFFTAG_ROWSPERSTRIP, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_ROWSPERSTRIP, 0, 0, "RowsPerStrip", NULL},
- {TIFFTAG_STRIPBYTECOUNTS, -1, -1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED,
- TIFF_SETGET_UNDEFINED, FIELD_STRIPBYTECOUNTS, 0, 0, "StripByteCounts",
- NULL},
- {TIFFTAG_MINSAMPLEVALUE, -2, -1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_MINSAMPLEVALUE, 1, 0, "MinSampleValue", NULL},
- {TIFFTAG_MAXSAMPLEVALUE, -2, -1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_MAXSAMPLEVALUE, 1, 0, "MaxSampleValue", NULL},
- {TIFFTAG_XRESOLUTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_RESOLUTION, 1, 0, "XResolution", NULL},
- {TIFFTAG_YRESOLUTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_RESOLUTION, 1, 0, "YResolution", NULL},
- {TIFFTAG_PLANARCONFIG, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_PLANARCONFIG, 0, 0, "PlanarConfiguration",
- NULL},
- {TIFFTAG_PAGENAME, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PageName", NULL},
- {TIFFTAG_XPOSITION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_POSITION, 1, 0, "XPosition", NULL},
- {TIFFTAG_YPOSITION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_POSITION, 1, 0, "YPosition", NULL},
- {TIFFTAG_FREEOFFSETS, -1, -1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED,
- TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 0, 0, "FreeOffsets", NULL},
- {TIFFTAG_FREEBYTECOUNTS, -1, -1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED,
- TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 0, 0, "FreeByteCounts", NULL},
- {TIFFTAG_GRAYRESPONSEUNIT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED,
- TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 1, 0, "GrayResponseUnit", NULL},
- {TIFFTAG_GRAYRESPONSECURVE, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED,
- TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 1, 0, "GrayResponseCurve", NULL},
- {TIFFTAG_RESOLUTIONUNIT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_RESOLUTIONUNIT, 1, 0, "ResolutionUnit", NULL},
- {TIFFTAG_PAGENUMBER, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR,
- TIFF_SETGET_UNDEFINED, FIELD_PAGENUMBER, 1, 0, "PageNumber", NULL},
- {TIFFTAG_COLORRESPONSEUNIT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED,
- TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 1, 0, "ColorResponseUnit", NULL},
- {TIFFTAG_TRANSFERFUNCTION, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_OTHER,
- TIFF_SETGET_UNDEFINED, FIELD_TRANSFERFUNCTION, 1, 0, "TransferFunction",
- NULL},
- {TIFFTAG_SOFTWARE, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Software", NULL},
- {TIFFTAG_DATETIME, 20, 20, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DateTime", NULL},
- {TIFFTAG_ARTIST, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Artist", NULL},
- {TIFFTAG_HOSTCOMPUTER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "HostComputer", NULL},
- {TIFFTAG_WHITEPOINT, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "WhitePoint", NULL},
- {TIFFTAG_PRIMARYCHROMATICITIES, 6, 6, TIFF_RATIONAL, 0,
- TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0,
- "PrimaryChromaticities", NULL},
- {TIFFTAG_COLORMAP, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_OTHER,
- TIFF_SETGET_UNDEFINED, FIELD_COLORMAP, 1, 0, "ColorMap", NULL},
- {TIFFTAG_HALFTONEHINTS, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR,
- TIFF_SETGET_UNDEFINED, FIELD_HALFTONEHINTS, 1, 0, "HalftoneHints", NULL},
- {TIFFTAG_TILEWIDTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_TILEDIMENSIONS, 0, 0, "TileWidth", NULL},
- {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 *)&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_NUMBEROFINKS, 1, 0, "NumberOfInks", NULL},
- {TIFFTAG_DOTRANGE, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DotRange", NULL},
- {TIFFTAG_TARGETPRINTER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "TargetPrinter", NULL},
- {TIFFTAG_EXTRASAMPLES, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_EXTRASAMPLES, 0, 1, "ExtraSamples", NULL},
- {TIFFTAG_SAMPLEFORMAT, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_SAMPLEFORMAT, 0, 0, "SampleFormat", NULL},
- {TIFFTAG_SMINSAMPLEVALUE, -2, -1, TIFF_ANY, 0, TIFF_SETGET_DOUBLE,
- TIFF_SETGET_UNDEFINED, FIELD_SMINSAMPLEVALUE, 1, 0, "SMinSampleValue",
- NULL},
- {TIFFTAG_SMAXSAMPLEVALUE, -2, -1, TIFF_ANY, 0, TIFF_SETGET_DOUBLE,
- TIFF_SETGET_UNDEFINED, FIELD_SMAXSAMPLEVALUE, 1, 0, "SMaxSampleValue",
- NULL},
- {TIFFTAG_CLIPPATH, -3, -3, TIFF_BYTE, 0, TIFF_SETGET_C32_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ClipPath", NULL},
- {TIFFTAG_XCLIPPATHUNITS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "XClipPathUnits", NULL},
- {TIFFTAG_YCLIPPATHUNITS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "YClipPathUnits", NULL},
- {TIFFTAG_YCBCRCOEFFICIENTS, 3, 3, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "YCbCrCoefficients", NULL},
- {TIFFTAG_YCBCRSUBSAMPLING, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR,
- TIFF_SETGET_UNDEFINED, FIELD_YCBCRSUBSAMPLING, 0, 0, "YCbCrSubsampling",
- NULL},
- {TIFFTAG_YCBCRPOSITIONING, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_YCBCRPOSITIONING, 0, 0, "YCbCrPositioning",
- NULL},
- {TIFFTAG_REFERENCEBLACKWHITE, 6, 6, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_REFBLACKWHITE, 1, 0, "ReferenceBlackWhite",
- NULL},
- {TIFFTAG_XMLPACKET, -3, -3, TIFF_BYTE, 0, TIFF_SETGET_C32_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "XMLPacket", NULL},
+ {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_IGNORE, 1, 0, "OldSubfileType", NULL},
+ {TIFFTAG_IMAGEWIDTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_IMAGEDIMENSIONS, 0, 0, "ImageWidth", NULL},
+ {TIFFTAG_IMAGELENGTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_IMAGEDIMENSIONS, 1, 0, "ImageLength", NULL},
+ {TIFFTAG_BITSPERSAMPLE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_BITSPERSAMPLE, 0, 0, "BitsPerSample", NULL},
+ {TIFFTAG_COMPRESSION, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_COMPRESSION, 0, 0, "Compression", NULL},
+ {TIFFTAG_PHOTOMETRIC, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_PHOTOMETRIC, 0, 0, "PhotometricInterpretation", NULL},
+ {TIFFTAG_THRESHHOLDING, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_THRESHHOLDING, 1, 0, "Threshholding", NULL},
+ {TIFFTAG_CELLWIDTH, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CellWidth", NULL},
+ {TIFFTAG_CELLLENGTH, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CellLength", NULL},
+ {TIFFTAG_FILLORDER, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_FILLORDER, 0, 0, "FillOrder", NULL},
+ {TIFFTAG_DOCUMENTNAME, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DocumentName", NULL},
+ {TIFFTAG_IMAGEDESCRIPTION, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageDescription", NULL},
+ {TIFFTAG_MAKE, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Make", NULL},
+ {TIFFTAG_MODEL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Model", NULL},
+ {TIFFTAG_STRIPOFFSETS, -1, -1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_STRIPOFFSETS, 0, 0, "StripOffsets", NULL},
+ {TIFFTAG_ORIENTATION, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_ORIENTATION, 0, 0, "Orientation", NULL},
+ {TIFFTAG_SAMPLESPERPIXEL, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_SAMPLESPERPIXEL, 0, 0, "SamplesPerPixel", NULL},
+ {TIFFTAG_ROWSPERSTRIP, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_ROWSPERSTRIP, 0, 0, "RowsPerStrip", NULL},
+ {TIFFTAG_STRIPBYTECOUNTS, -1, -1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_STRIPBYTECOUNTS, 0, 0, "StripByteCounts", NULL},
+ {TIFFTAG_MINSAMPLEVALUE, -2, -1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_MINSAMPLEVALUE, 1, 0, "MinSampleValue", NULL},
+ {TIFFTAG_MAXSAMPLEVALUE, -2, -1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_MAXSAMPLEVALUE, 1, 0, "MaxSampleValue", NULL},
+ {TIFFTAG_XRESOLUTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_RESOLUTION, 1, 0, "XResolution", NULL},
+ {TIFFTAG_YRESOLUTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_RESOLUTION, 1, 0, "YResolution", NULL},
+ {TIFFTAG_PLANARCONFIG, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_PLANARCONFIG, 0, 0, "PlanarConfiguration", NULL},
+ {TIFFTAG_PAGENAME, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PageName", NULL},
+ {TIFFTAG_XPOSITION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_POSITION, 1, 0, "XPosition", NULL},
+ {TIFFTAG_YPOSITION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_POSITION, 1, 0, "YPosition", NULL},
+ {TIFFTAG_FREEOFFSETS, -1, -1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 0, 0, "FreeOffsets", NULL},
+ {TIFFTAG_FREEBYTECOUNTS, -1, -1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 0, 0, "FreeByteCounts", NULL},
+ {TIFFTAG_GRAYRESPONSEUNIT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 1, 0, "GrayResponseUnit", NULL},
+ {TIFFTAG_GRAYRESPONSECURVE, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 1, 0, "GrayResponseCurve", NULL},
+ {TIFFTAG_RESOLUTIONUNIT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_RESOLUTIONUNIT, 1, 0, "ResolutionUnit", NULL},
+ {TIFFTAG_PAGENUMBER, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR, TIFF_SETGET_UNDEFINED, FIELD_PAGENUMBER, 1, 0, "PageNumber", NULL},
+ {TIFFTAG_COLORRESPONSEUNIT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 1, 0, "ColorResponseUnit", NULL},
+ {TIFFTAG_TRANSFERFUNCTION, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_OTHER, TIFF_SETGET_UNDEFINED, FIELD_TRANSFERFUNCTION, 1, 0, "TransferFunction", NULL},
+ {TIFFTAG_SOFTWARE, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Software", NULL},
+ {TIFFTAG_DATETIME, 20, 20, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DateTime", NULL},
+ {TIFFTAG_ARTIST, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Artist", NULL},
+ {TIFFTAG_HOSTCOMPUTER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "HostComputer", NULL},
+ {TIFFTAG_WHITEPOINT, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "WhitePoint", NULL},
+ {TIFFTAG_PRIMARYCHROMATICITIES, 6, 6, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PrimaryChromaticities", NULL},
+ {TIFFTAG_COLORMAP, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_OTHER, TIFF_SETGET_UNDEFINED, FIELD_COLORMAP, 1, 0, "ColorMap", NULL},
+ {TIFFTAG_HALFTONEHINTS, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR, TIFF_SETGET_UNDEFINED, FIELD_HALFTONEHINTS, 1, 0, "HalftoneHints", NULL},
+ {TIFFTAG_TILEWIDTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_TILEDIMENSIONS, 0, 0, "TileWidth", NULL},
+ {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 *)&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_NUMBEROFINKS, 1, 0, "NumberOfInks", NULL},
+ {TIFFTAG_DOTRANGE, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DotRange", NULL},
+ {TIFFTAG_TARGETPRINTER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "TargetPrinter", NULL},
+ {TIFFTAG_EXTRASAMPLES, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_EXTRASAMPLES, 0, 1, "ExtraSamples", NULL},
+ {TIFFTAG_SAMPLEFORMAT, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_SAMPLEFORMAT, 0, 0, "SampleFormat", NULL},
+ {TIFFTAG_SMINSAMPLEVALUE, -2, -1, TIFF_ANY, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_SMINSAMPLEVALUE, 1, 0, "SMinSampleValue", NULL},
+ {TIFFTAG_SMAXSAMPLEVALUE, -2, -1, TIFF_ANY, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_SMAXSAMPLEVALUE, 1, 0, "SMaxSampleValue", NULL},
+ {TIFFTAG_CLIPPATH, -3, -3, TIFF_BYTE, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ClipPath", NULL},
+ {TIFFTAG_XCLIPPATHUNITS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "XClipPathUnits", NULL},
+ {TIFFTAG_YCLIPPATHUNITS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "YClipPathUnits", NULL},
+ {TIFFTAG_YCBCRCOEFFICIENTS, 3, 3, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "YCbCrCoefficients", NULL},
+ {TIFFTAG_YCBCRSUBSAMPLING, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR, TIFF_SETGET_UNDEFINED, FIELD_YCBCRSUBSAMPLING, 0, 0, "YCbCrSubsampling", NULL},
+ {TIFFTAG_YCBCRPOSITIONING, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_YCBCRPOSITIONING, 0, 0, "YCbCrPositioning", NULL},
+ {TIFFTAG_REFERENCEBLACKWHITE, 6, 6, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_REFBLACKWHITE, 1, 0, "ReferenceBlackWhite", NULL},
+ {TIFFTAG_XMLPACKET, -3, -3, TIFF_BYTE, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "XMLPacket", NULL},
/* begin SGI tags */
- {TIFFTAG_MATTEING, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_EXTRASAMPLES, 0, 0, "Matteing", NULL},
- {TIFFTAG_DATATYPE, -2, -1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_SAMPLEFORMAT, 0, 0, "DataType", NULL},
- {TIFFTAG_IMAGEDEPTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_IMAGEDEPTH, 0, 0, "ImageDepth", NULL},
- {TIFFTAG_TILEDEPTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_TILEDEPTH, 0, 0, "TileDepth", NULL},
+ {TIFFTAG_MATTEING, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_EXTRASAMPLES, 0, 0, "Matteing", NULL},
+ {TIFFTAG_DATATYPE, -2, -1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_SAMPLEFORMAT, 0, 0, "DataType", NULL},
+ {TIFFTAG_IMAGEDEPTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_IMAGEDEPTH, 0, 0, "ImageDepth", NULL},
+ {TIFFTAG_TILEDEPTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_TILEDEPTH, 0, 0, "TileDepth", NULL},
/* end SGI tags */
/* begin Pixar tags */
- {TIFFTAG_PIXAR_IMAGEFULLWIDTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageFullWidth", NULL},
- {TIFFTAG_PIXAR_IMAGEFULLLENGTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageFullLength", NULL},
- {TIFFTAG_PIXAR_TEXTUREFORMAT, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "TextureFormat", NULL},
- {TIFFTAG_PIXAR_WRAPMODES, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "TextureWrapModes", NULL},
- {TIFFTAG_PIXAR_FOVCOT, 1, 1, TIFF_FLOAT, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FieldOfViewCotangent", NULL},
- {TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN, 16, 16, TIFF_FLOAT, 0,
- TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0,
- "MatrixWorldToScreen", NULL},
- {TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA, 16, 16, TIFF_FLOAT, 0,
- TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0,
- "MatrixWorldToCamera", NULL},
- {TIFFTAG_CFAREPEATPATTERNDIM, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_C0_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "CFARepeatPatternDim", NULL},
- {TIFFTAG_CFAPATTERN, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "CFAPattern", NULL},
- {TIFFTAG_COPYRIGHT, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Copyright", NULL},
+ {TIFFTAG_PIXAR_IMAGEFULLWIDTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageFullWidth", NULL},
+ {TIFFTAG_PIXAR_IMAGEFULLLENGTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageFullLength", NULL},
+ {TIFFTAG_PIXAR_TEXTUREFORMAT, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "TextureFormat", NULL},
+ {TIFFTAG_PIXAR_WRAPMODES, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "TextureWrapModes", NULL},
+ {TIFFTAG_PIXAR_FOVCOT, 1, 1, TIFF_FLOAT, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FieldOfViewCotangent", NULL},
+ {TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN, 16, 16, TIFF_FLOAT, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MatrixWorldToScreen", NULL},
+ {TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA, 16, 16, TIFF_FLOAT, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MatrixWorldToCamera", NULL},
+ {TIFFTAG_COPYRIGHT, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Copyright", NULL},
/* end Pixar tags */
- {TIFFTAG_RICHTIFFIPTC, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8,
- 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, 1, 1, "Photoshop", NULL},
- /*--: EXIFIFD and GPSIFD specified as TIFF_LONG by Aware-Systems and not
- * TIFF_IFD8 as in original LibTiff. However, for IFD-like tags, libtiff
- * uses the data type TIFF_IFD8 in tiffFields[]-tag definition combined with
- * a special handling procedure in order to write either a 32-bit value
- * and the TIFF_IFD type-id into ClassicTIFF files or a 64-bit value and the
- * TIFF_IFD8 type-id into BigTIFF files. */
- {TIFFTAG_EXIFIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 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, 1, 0, "GPSIFDOffset",
- (TIFFFieldArray *)&gpsFieldArray},
- {TIFFTAG_FAXRECVPARAMS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UINT32, FIELD_CUSTOM, TRUE, FALSE, "FaxRecvParams", NULL},
- {TIFFTAG_FAXSUBADDRESS, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_ASCII, FIELD_CUSTOM, TRUE, FALSE, "FaxSubAddress", NULL},
- {TIFFTAG_FAXRECVTIME, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UINT32, FIELD_CUSTOM, TRUE, FALSE, "FaxRecvTime", NULL},
- {TIFFTAG_FAXDCS, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_ASCII, FIELD_CUSTOM, TRUE, FALSE, "FaxDcs", NULL},
- {TIFFTAG_STONITS, 1, 1, TIFF_DOUBLE, 0, TIFF_SETGET_DOUBLE,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "StoNits", NULL},
- {TIFFTAG_IMAGESOURCEDATA, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1,
- "Adobe Photoshop Document Data Block", NULL},
- {TIFFTAG_INTEROPERABILITYIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "InteroperabilityIFDOffset",
- NULL},
+ {TIFFTAG_RICHTIFFIPTC, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "RichTIFFIPTC", NULL},
+ {TIFFTAG_PHOTOSHOP, -3, -3, TIFF_BYTE, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "Photoshop", NULL},
+ /*--: EXIFIFD and GPSIFD specified as TIFF_LONG by Aware-Systems and not TIFF_IFD8 as in original LibTiff. However, for IFD-like tags,
+ * libtiff uses the data type TIFF_IFD8 in tiffFields[]-tag definition combined with a special handling procedure in order to write either
+ * a 32-bit value and the TIFF_IFD type-id into ClassicTIFF files or a 64-bit value and the TIFF_IFD8 type-id into BigTIFF files. */
+ {TIFFTAG_EXIFIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EXIFIFDOffset", (TIFFFieldArray *)&exifFieldArray},
+ {TIFFTAG_ICCPROFILE, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ICC Profile", NULL},
+ {TIFFTAG_GPSIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "GPSIFDOffset", (TIFFFieldArray *)&gpsFieldArray},
+ {TIFFTAG_FAXRECVPARAMS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UINT32, FIELD_CUSTOM, TRUE, FALSE, "FaxRecvParams", NULL},
+ {TIFFTAG_FAXSUBADDRESS, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_ASCII, FIELD_CUSTOM, TRUE, FALSE, "FaxSubAddress", NULL},
+ {TIFFTAG_FAXRECVTIME, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UINT32, FIELD_CUSTOM, TRUE, FALSE, "FaxRecvTime", NULL},
+ {TIFFTAG_FAXDCS, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_ASCII, FIELD_CUSTOM, TRUE, FALSE, "FaxDcs", NULL},
+ {TIFFTAG_STONITS, 1, 1, TIFF_DOUBLE, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "StoNits", NULL},
+ {TIFFTAG_IMAGESOURCEDATA, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "Adobe Photoshop Document Data Block", NULL},
+ {TIFFTAG_INTEROPERABILITYIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "InteroperabilityIFDOffset", NULL},
/* begin DNG tags */
- {TIFFTAG_DNGVERSION, 4, 4, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DNGVersion", NULL},
- {TIFFTAG_DNGBACKWARDVERSION, 4, 4, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DNGBackwardVersion", NULL},
- {TIFFTAG_UNIQUECAMERAMODEL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "UniqueCameraModel", NULL},
- {TIFFTAG_LOCALIZEDCAMERAMODEL, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "LocalizedCameraModel", NULL},
- {TIFFTAG_CFAPLANECOLOR, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "CFAPlaneColor", NULL},
- {TIFFTAG_CFALAYOUT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "CFALayout", NULL},
- {TIFFTAG_LINEARIZATIONTABLE, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "LinearizationTable", NULL},
- {TIFFTAG_BLACKLEVELREPEATDIM, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_C0_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "BlackLevelRepeatDim", NULL},
- {TIFFTAG_BLACKLEVEL, -1, -1, TIFF_RATIONAL, 0, TIFF_SETGET_C16_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "BlackLevel", NULL},
- {TIFFTAG_BLACKLEVELDELTAH, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "BlackLevelDeltaH", NULL},
- {TIFFTAG_BLACKLEVELDELTAV, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "BlackLevelDeltaV", NULL},
- {TIFFTAG_WHITELEVEL, -1, -1, TIFF_LONG, 0, TIFF_SETGET_C16_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "WhiteLevel", NULL},
- {TIFFTAG_DEFAULTSCALE, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DefaultScale", NULL},
- {TIFFTAG_BESTQUALITYSCALE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "BestQualityScale", NULL},
- {TIFFTAG_DEFAULTCROPORIGIN, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DefaultCropOrigin", NULL},
- {TIFFTAG_DEFAULTCROPSIZE, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DefaultCropSize", NULL},
- {TIFFTAG_COLORMATRIX1, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ColorMatrix1", NULL},
- {TIFFTAG_COLORMATRIX2, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ColorMatrix2", NULL},
- {TIFFTAG_CAMERACALIBRATION1, -1, -1, TIFF_SRATIONAL, 0,
- TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1,
- "CameraCalibration1", NULL},
- {TIFFTAG_CAMERACALIBRATION2, -1, -1, TIFF_SRATIONAL, 0,
- TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1,
- "CameraCalibration2", NULL},
- {TIFFTAG_REDUCTIONMATRIX1, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ReductionMatrix1", NULL},
- {TIFFTAG_REDUCTIONMATRIX2, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ReductionMatrix2", NULL},
- {TIFFTAG_ANALOGBALANCE, -1, -1, TIFF_RATIONAL, 0, TIFF_SETGET_C16_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "AnalogBalance", NULL},
- {TIFFTAG_ASSHOTNEUTRAL, -1, -1, TIFF_RATIONAL, 0, TIFF_SETGET_C16_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "AsShotNeutral", NULL},
- {TIFFTAG_ASSHOTWHITEXY, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "AsShotWhiteXY", NULL},
- {TIFFTAG_BASELINEEXPOSURE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "BaselineExposure", NULL},
- {TIFFTAG_BASELINENOISE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "BaselineNoise", NULL},
- {TIFFTAG_BASELINESHARPNESS, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "BaselineSharpness", NULL},
- {TIFFTAG_BAYERGREENSPLIT, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "BayerGreenSplit", NULL},
- {TIFFTAG_LINEARRESPONSELIMIT, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "LinearResponseLimit", NULL},
- {TIFFTAG_CAMERASERIALNUMBER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CameraSerialNumber", NULL},
- {TIFFTAG_LENSINFO, 4, 4, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "LensInfo", NULL},
- {TIFFTAG_CHROMABLURRADIUS, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "ChromaBlurRadius", NULL},
- {TIFFTAG_ANTIALIASSTRENGTH, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "AntiAliasStrength", NULL},
- {TIFFTAG_SHADOWSCALE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "ShadowScale", NULL},
- {TIFFTAG_DNGPRIVATEDATA, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "DNGPrivateData", NULL},
- {TIFFTAG_MAKERNOTESAFETY, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "MakerNoteSafety", NULL},
- {TIFFTAG_CALIBRATIONILLUMINANT1, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "CalibrationIlluminant1", NULL},
- {TIFFTAG_CALIBRATIONILLUMINANT2, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "CalibrationIlluminant2", NULL},
- {TIFFTAG_RAWDATAUNIQUEID, 16, 16, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "RawDataUniqueID", NULL},
- {TIFFTAG_ORIGINALRAWFILENAME, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "OriginalRawFileName", NULL},
- {TIFFTAG_ORIGINALRAWFILEDATA, -1, -1, TIFF_UNDEFINED, 0,
- TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1,
- "OriginalRawFileData", NULL},
- {TIFFTAG_ACTIVEAREA, 4, 4, TIFF_LONG, 0, TIFF_SETGET_C0_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "ActiveArea", NULL},
- {TIFFTAG_MASKEDAREAS, -1, -1, TIFF_LONG, 0, TIFF_SETGET_C16_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "MaskedAreas", NULL},
- {TIFFTAG_ASSHOTICCPROFILE, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "AsShotICCProfile", NULL},
- {TIFFTAG_ASSHOTPREPROFILEMATRIX, -1, -1, TIFF_SRATIONAL, 0,
- TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1,
- "AsShotPreProfileMatrix", NULL},
- {TIFFTAG_CURRENTICCPROFILE, -1, -1, TIFF_UNDEFINED, 0,
- TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1,
- "CurrentICCProfile", NULL},
- {TIFFTAG_CURRENTPREPROFILEMATRIX, -1, -1, TIFF_SRATIONAL, 0,
- TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1,
- "CurrentPreProfileMatrix", NULL},
- {TIFFTAG_PERSAMPLE, 0, 0, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED,
- TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "PerSample", NULL},
+ {TIFFTAG_DNGVERSION, 4, 4, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DNGVersion", NULL},
+ {TIFFTAG_DNGBACKWARDVERSION, 4, 4, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DNGBackwardVersion", NULL},
+ {TIFFTAG_UNIQUECAMERAMODEL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "UniqueCameraModel", NULL},
+ {TIFFTAG_LOCALIZEDCAMERAMODEL, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "LocalizedCameraModel", NULL},
+ {TIFFTAG_CFAPLANECOLOR, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CFAPlaneColor", NULL},
+ {TIFFTAG_CFALAYOUT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CFALayout", NULL},
+ {TIFFTAG_LINEARIZATIONTABLE, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "LinearizationTable", NULL},
+ {TIFFTAG_BLACKLEVELREPEATDIM, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_C0_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "BlackLevelRepeatDim", NULL},
+ {TIFFTAG_BLACKLEVEL, -1, -1, TIFF_RATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "BlackLevel", NULL},
+ {TIFFTAG_BLACKLEVELDELTAH, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "BlackLevelDeltaH", NULL},
+ {TIFFTAG_BLACKLEVELDELTAV, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "BlackLevelDeltaV", NULL},
+ {TIFFTAG_WHITELEVEL, -1, -1, TIFF_LONG, 0, TIFF_SETGET_C16_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "WhiteLevel", NULL},
+ {TIFFTAG_DEFAULTSCALE, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DefaultScale", NULL},
+ {TIFFTAG_BESTQUALITYSCALE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "BestQualityScale", NULL},
+ {TIFFTAG_DEFAULTCROPORIGIN, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DefaultCropOrigin", NULL},
+ {TIFFTAG_DEFAULTCROPSIZE, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DefaultCropSize", NULL},
+ {TIFFTAG_COLORMATRIX1, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ColorMatrix1", NULL},
+ {TIFFTAG_COLORMATRIX2, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ColorMatrix2", NULL},
+ {TIFFTAG_CAMERACALIBRATION1, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CameraCalibration1", NULL},
+ {TIFFTAG_CAMERACALIBRATION2, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CameraCalibration2", NULL},
+ {TIFFTAG_REDUCTIONMATRIX1, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ReductionMatrix1", NULL},
+ {TIFFTAG_REDUCTIONMATRIX2, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ReductionMatrix2", NULL},
+ {TIFFTAG_ANALOGBALANCE, -1, -1, TIFF_RATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "AnalogBalance", NULL},
+ {TIFFTAG_ASSHOTNEUTRAL, -1, -1, TIFF_RATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "AsShotNeutral", NULL},
+ {TIFFTAG_ASSHOTWHITEXY, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "AsShotWhiteXY", NULL},
+ {TIFFTAG_BASELINEEXPOSURE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "BaselineExposure", NULL},
+ {TIFFTAG_BASELINENOISE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "BaselineNoise", NULL},
+ {TIFFTAG_BASELINESHARPNESS, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "BaselineSharpness", NULL},
+ {TIFFTAG_BAYERGREENSPLIT, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "BayerGreenSplit", NULL},
+ {TIFFTAG_LINEARRESPONSELIMIT, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "LinearResponseLimit", NULL},
+ {TIFFTAG_CAMERASERIALNUMBER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CameraSerialNumber", NULL},
+ {TIFFTAG_LENSINFO, 4, 4, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "LensInfo", NULL},
+ {TIFFTAG_CHROMABLURRADIUS, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ChromaBlurRadius", NULL},
+ {TIFFTAG_ANTIALIASSTRENGTH, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "AntiAliasStrength", NULL},
+ {TIFFTAG_SHADOWSCALE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ShadowScale", NULL},
+ {TIFFTAG_DNGPRIVATEDATA, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "DNGPrivateData", NULL},
+ {TIFFTAG_MAKERNOTESAFETY, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MakerNoteSafety", NULL},
+ {TIFFTAG_CALIBRATIONILLUMINANT1, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CalibrationIlluminant1", NULL},
+ {TIFFTAG_CALIBRATIONILLUMINANT2, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CalibrationIlluminant2", NULL},
+ {TIFFTAG_RAWDATAUNIQUEID, 16, 16, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "RawDataUniqueID", NULL},
+ {TIFFTAG_ORIGINALRAWFILENAME, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "OriginalRawFileName", NULL},
+ {TIFFTAG_ORIGINALRAWFILEDATA, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "OriginalRawFileData", NULL},
+ {TIFFTAG_ACTIVEAREA, 4, 4, TIFF_LONG, 0, TIFF_SETGET_C0_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ActiveArea", NULL},
+ {TIFFTAG_MASKEDAREAS, -1, -1, TIFF_LONG, 0, TIFF_SETGET_C16_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "MaskedAreas", NULL},
+ {TIFFTAG_ASSHOTICCPROFILE, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "AsShotICCProfile", NULL},
+ {TIFFTAG_ASSHOTPREPROFILEMATRIX, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "AsShotPreProfileMatrix", NULL},
+ {TIFFTAG_CURRENTICCPROFILE, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CurrentICCProfile", NULL},
+ {TIFFTAG_CURRENTPREPROFILEMATRIX, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CurrentPreProfileMatrix", NULL},
+ {TIFFTAG_PERSAMPLE, 0, 0, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "PerSample", NULL},
+#if 0
+ /* TODO: revert above #if 0 for TIFF 4.6.0 */
+
+ /* begin DNG 1.2.0.0 tags */
+ {TIFFTAG_COLORIMETRICREFERENCE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ColorimetricReference", NULL},
+ {TIFFTAG_CAMERACALIBRATIONSIGNATURE, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CameraCalibrationSignature", NULL},
+ {TIFFTAG_PROFILECALIBRATIONSIGNATURE, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ProfileCalibrationSignature", NULL},
+ {TIFFTAG_EXTRACAMERAPROFILES, -1, -1, TIFF_IFD8, 0, TIFF_SETGET_C16_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ExtraCameraProfiles", NULL},
+ {TIFFTAG_ASSHOTPROFILENAME, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "AsShotProfileName", NULL},
+ {TIFFTAG_NOISEREDUCTIONAPPLIED, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "NoiseReductionApplied", NULL},
+ {TIFFTAG_PROFILENAME, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ProfileName", NULL},
+ {TIFFTAG_PROFILEHUESATMAPDIMS, 3, 3, TIFF_LONG, 0, TIFF_SETGET_C0_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ProfileHueSatMapDims", NULL},
+ {TIFFTAG_PROFILEHUESATMAPDATA1, -1, -1, TIFF_FLOAT, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ProfileHueSatMapData1", NULL},
+ {TIFFTAG_PROFILEHUESATMAPDATA2, -1, -1, TIFF_FLOAT, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ProfileHueSatMapData2", NULL},
+ {TIFFTAG_PROFILETONECURVE, -1, -1, TIFF_FLOAT, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ProfileToneCurve", NULL},
+ {TIFFTAG_PROFILEEMBEDPOLICY, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ProfileEmbedPolicy", NULL},
+ {TIFFTAG_PROFILECOPYRIGHT, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ProfileCopyright", NULL},
+ {TIFFTAG_FORWARDMATRIX1, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ForwardMatrix1", NULL},
+ {TIFFTAG_FORWARDMATRIX2, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ForwardMatrix2", NULL},
+ {TIFFTAG_PREVIEWAPPLICATIONNAME, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "PreviewApplicationName", NULL},
+ {TIFFTAG_PREVIEWAPPLICATIONVERSION, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "PreviewApplicationVersion", NULL},
+ {TIFFTAG_PREVIEWSETTINGSNAME, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "PreviewSettingsName", NULL},
+ {TIFFTAG_PREVIEWSETTINGSDIGEST, 16, 16, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PreviewSettingsDigest", NULL},
+ {TIFFTAG_PREVIEWCOLORSPACE, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PreviewColorSpace", NULL},
+ {TIFFTAG_PREVIEWDATETIME, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PreviewDateTime", NULL},
+ {TIFFTAG_RAWIMAGEDIGEST, 16, 16, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "RawImageDigest", NULL},
+ {TIFFTAG_ORIGINALRAWFILEDIGEST, 16, 16, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "OriginalRawFileDigest", NULL},
+ {TIFFTAG_SUBTILEBLOCKSIZE, 2, 2, TIFF_LONG, 0, TIFF_SETGET_C0_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubTileBlockSize", NULL},
+ {TIFFTAG_ROWINTERLEAVEFACTOR, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "RowInterleaveFactor", NULL},
+ {TIFFTAG_PROFILELOOKTABLEDIMS, 3, 3, TIFF_LONG, 0, TIFF_SETGET_C0_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ProfileLookTableDims", NULL},
+ {TIFFTAG_PROFILELOOKTABLEDATA, -1, -1, TIFF_FLOAT, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ProfileLookTableData", NULL},
+ /* begin DNG 1.3.0.0 tags */
+ {TIFFTAG_OPCODELIST1, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "OpcodeList1", NULL},
+ {TIFFTAG_OPCODELIST2, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "OpcodeList2", NULL},
+ {TIFFTAG_OPCODELIST3, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "OpcodeList3", NULL},
+ {TIFFTAG_NOISEPROFILE, -1, -1, TIFF_DOUBLE, 0, TIFF_SETGET_C16_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "NoiseProfile", NULL},
+ /* begin DNG 1.4.0.0 tags */
+ {TIFFTAG_DEFAULTUSERCROP, 4, 4, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DefaultUserCrop", NULL},
+ {TIFFTAG_DEFAULTBLACKRENDER, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DefaultBlackRender", NULL},
+ {TIFFTAG_BASELINEEXPOSUREOFFSET, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "BaselineExposureOffset", NULL},
+ {TIFFTAG_PROFILELOOKTABLEENCODING, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ProfileLookTableEncoding", NULL},
+ {TIFFTAG_PROFILEHUESATMAPENCODING, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ProfileHueSatMapEncoding", NULL},
+ {TIFFTAG_ORIGINALDEFAULTFINALSIZE, 2, 2, TIFF_LONG, 0, TIFF_SETGET_C0_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "OriginalDefaultFinalSize", NULL},
+ {TIFFTAG_ORIGINALBESTQUALITYFINALSIZE, 2, 2, TIFF_LONG, 0, TIFF_SETGET_C0_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "OriginalBestQualityFinalSize", NULL},
+ {TIFFTAG_ORIGINALDEFAULTCROPSIZE, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "OriginalDefaultCropSize", NULL}, /* could also be rational */
+ {TIFFTAG_NEWRAWIMAGEDIGEST, 16, 16, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "NewRawImageDigest", NULL},
+ {TIFFTAG_RAWTOPREVIEWGAIN, 1, 1, TIFF_DOUBLE, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "RawToPreviewGain", NULL},
+ /* begin DNG 1.5.0.0 tags */
+ {TIFFTAG_DEPTHFORMAT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DepthFormat", NULL},
+ {TIFFTAG_DEPTHNEAR, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DepthNear", NULL},
+ {TIFFTAG_DEPTHFAR, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DepthFar", NULL},
+ {TIFFTAG_DEPTHUNITS, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DepthUnits", NULL},
+ {TIFFTAG_DEPTHMEASURETYPE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DepthMeasureType", NULL},
+ {TIFFTAG_ENHANCEPARAMS, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EnhanceParams", NULL},
+ /* begin DNG 1.6.0.0 tags */
+ {TIFFTAG_PROFILEGAINTABLEMAP, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ProfileGainTableMap", NULL},
+ {TIFFTAG_SEMANTICNAME, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SemanticName", NULL},
+ {TIFFTAG_SEMANTICINSTANCEID, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SemanticInstanceID", NULL},
+ {TIFFTAG_MASKSUBAREA, 4, 4, TIFF_LONG, 0, TIFF_SETGET_C0_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MaskSubArea", NULL},
+ {TIFFTAG_RGBTABLES, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "RGBTables", NULL},
+ {TIFFTAG_CALIBRATIONILLUMINANT3, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CalibrationIlluminant3", NULL},
+ {TIFFTAG_COLORMATRIX3, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ColorMatrix3", NULL},
+ {TIFFTAG_CAMERACALIBRATION3, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CameraCalibration3", NULL},
+ {TIFFTAG_REDUCTIONMATRIX3, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ReductionMatrix3", NULL},
+ {TIFFTAG_PROFILEHUESATMAPDATA3, -1, -1, TIFF_FLOAT, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ProfileHueSatMapData3", NULL},
+ {TIFFTAG_FORWARDMATRIX3, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ForwardMatrix3", NULL},
+ {TIFFTAG_ILLUMINANTDATA1, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "IlluminantData1", NULL},
+ {TIFFTAG_ILLUMINANTDATA2, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "IlluminantData2", NULL},
+ {TIFFTAG_ILLUMINANTDATA3, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "IlluminantData3", NULL},
/* end DNG tags */
+ /* begin TIFF/EP tags */
+ {TIFFTAG_EP_CFAREPEATPATTERNDIM, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_C0_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP CFARepeatPatternDim", NULL},
+ {TIFFTAG_EP_CFAPATTERN, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "EP CFAPattern", NULL},
+ /* TIFFTAG_EP_BATTERYLEVEL can be RATIONAL or ASCII.
+ * LibTiff defines it as ASCII and converts RATIONAL to an ASCII string. */
+ {TIFFTAG_EP_BATTERYLEVEL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP BatteryLevel", NULL},
+ {TIFFTAG_EP_INTERLACE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP Interlace", NULL},
+ /* TIFFTAG_EP_IPTC_NAA and TIFFTAG_RICHTIFFIPTC share the same tag number (33723)
+ * LibTIFF type is UNDEFINED or BYTE, but often times incorrectly specified as LONG, because TIFF/EP (ISO/DIS 12234-2) specifies type LONG or ASCII. */
+ {TIFFTAG_EP_TIMEZONEOFFSET, -1, -1, TIFF_SSHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "EP TimeZoneOffset", NULL},
+ {TIFFTAG_EP_SELFTIMERMODE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP SelfTimerMode", NULL},
+ {TIFFTAG_EP_FLASHENERGY, -1, -1, TIFF_RATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "EP FlashEnergy", NULL},
+ {TIFFTAG_EP_SPATIALFREQUENCYRESPONSE, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "EP SpatialFrequencyResponse", NULL},
+ {TIFFTAG_EP_NOISE, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "EP Noise", NULL},
+ {TIFFTAG_EP_FOCALPLANEXRESOLUTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP FocalPlaneXResolution", NULL},
+ {TIFFTAG_EP_FOCALPLANEYRESOLUTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP FocalPlaneYResolution", NULL},
+ {TIFFTAG_EP_FOCALPLANERESOLUTIONUNIT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP FocalPlaneResolutionUnit", NULL},
+ {TIFFTAG_EP_IMAGENUMBER, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP ImageNumber", NULL}, /* or SHORT */
+ {TIFFTAG_EP_SECURITYCLASSIFICATION, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP SecurityClassification", NULL},
+ {TIFFTAG_EP_IMAGEHISTORY, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP ImageHistory", NULL},
+ {TIFFTAG_EP_EXPOSUREINDEX, -1, -1, TIFF_RATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "EP ExposureIndex", NULL},
+ {TIFFTAG_EP_STANDARDID, 4, 4, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP StandardId", NULL},
+ {TIFFTAG_EP_SENSINGMETHOD, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP SensingMethod", NULL},
+ /* TIFF/EP tags equivalent to EXIF tags, sometimes defined differently. */
+ {TIFFTAG_EP_EXPOSURETIME, -1, -1, TIFF_RATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "EP ExposureTime", NULL}, /*N=1 or 2 */
+ {TIFFTAG_EP_FNUMBER, -1, -1, TIFF_RATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "EP FNumber", NULL},
+ {TIFFTAG_EP_EXPOSUREPROGRAM, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP ExposureProgram", NULL},
+ {TIFFTAG_EP_SPECTRALSENSITIVITY, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP SpectralSensitivity", NULL},
+ {TIFFTAG_EP_ISOSPEEDRATINGS, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP ISOSpeedRatings", NULL},
+ {TIFFTAG_EP_OECF, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "EP OptoelectricConversionFactor", NULL},
+ {TIFFTAG_EP_DATETIMEORIGINAL, 20, 20, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP DateTimeOriginal", NULL},
+ {TIFFTAG_EP_COMPRESSEDBITSPERPIXEL, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP CompressedBitsPerPixel", NULL},
+ {TIFFTAG_EP_SHUTTERSPEEDVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP ShutterSpeedValue", NULL},
+ {TIFFTAG_EP_APERTUREVALUE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP ApertureValue", NULL},
+ {TIFFTAG_EP_BRIGHTNESSVALUE, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "EP BrightnessValue", NULL},
+ {TIFFTAG_EP_EXPOSUREBIASVALUE, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "EP ExposureBiasValue", NULL}, /*N=1 or 2 */
+ {TIFFTAG_EP_MAXAPERTUREVALUE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP MaxApertureValue", NULL},
+ {TIFFTAG_EP_SUBJECTDISTANCE, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "EP SubjectDistance", NULL},
+ {TIFFTAG_EP_METERINGMODE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP MeteringMode", NULL},
+ {TIFFTAG_EP_LIGHTSOURCE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP LightSource", NULL},
+ {TIFFTAG_EP_FLASH, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP Flash", NULL},
+ {TIFFTAG_EP_FOCALLENGTH, -1, -1, TIFF_RATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "EP FocalLength", NULL},
+ {TIFFTAG_EP_SUBJECTLOCATION, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "EP SubjectLocation", NULL},
+ /* end TIFF/EP tags */
+#endif
/* begin TIFF/FX tags */
- {TIFFTAG_INDEXED, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "Indexed", NULL},
- {TIFFTAG_GLOBALPARAMETERSIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "GlobalParametersIFD", NULL},
- {TIFFTAG_PROFILETYPE, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "ProfileType", NULL},
- {TIFFTAG_FAXPROFILE, 1, 1, TIFF_BYTE, 0, TIFF_SETGET_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "FaxProfile", NULL},
- {TIFFTAG_CODINGMETHODS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "CodingMethods", NULL},
- {TIFFTAG_VERSIONYEAR, 4, 4, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "VersionYear", NULL},
- {TIFFTAG_MODENUMBER, 1, 1, TIFF_BYTE, 0, TIFF_SETGET_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "ModeNumber", NULL},
- {TIFFTAG_DECODE, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "Decode", NULL},
- {TIFFTAG_IMAGEBASECOLOR, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ImageBaseColor", NULL},
- {TIFFTAG_T82OPTIONS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "T82Options", NULL},
- {TIFFTAG_STRIPROWCOUNTS, -1, -1, TIFF_LONG, 0, TIFF_SETGET_C16_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "StripRowCounts", NULL},
- {TIFFTAG_IMAGELAYER, 2, 2, TIFF_LONG, 0, TIFF_SETGET_C0_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "ImageLayer", NULL},
+ {TIFFTAG_INDEXED, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Indexed", NULL},
+ {TIFFTAG_GLOBALPARAMETERSIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "GlobalParametersIFD", NULL},
+ {TIFFTAG_PROFILETYPE, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ProfileType", NULL},
+ {TIFFTAG_FAXPROFILE, 1, 1, TIFF_BYTE, 0, TIFF_SETGET_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FaxProfile", NULL},
+ {TIFFTAG_CODINGMETHODS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CodingMethods", NULL},
+ {TIFFTAG_VERSIONYEAR, 4, 4, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "VersionYear", NULL},
+ {TIFFTAG_MODENUMBER, 1, 1, TIFF_BYTE, 0, TIFF_SETGET_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ModeNumber", NULL},
+ {TIFFTAG_DECODE, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "Decode", NULL},
+ {TIFFTAG_IMAGEBASECOLOR, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ImageBaseColor", NULL},
+ {TIFFTAG_T82OPTIONS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "T82Options", NULL},
+ {TIFFTAG_STRIPROWCOUNTS, -1, -1, TIFF_LONG, 0, TIFF_SETGET_C16_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "StripRowCounts", NULL},
+ {TIFFTAG_IMAGELAYER, 2, 2, TIFF_LONG, 0, TIFF_SETGET_C0_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageLayer", NULL},
/* end TIFF/FX tags */
/* begin pseudo tags */
};
@@ -416,181 +348,91 @@ static const TIFFField tiffFields[] = {
* EXIF tags (Version 2.31, July 2016 plus version 2.32 May 2019)
*/
static const TIFFField exifFields[] = {
- {EXIFTAG_EXPOSURETIME, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureTime", NULL},
- {EXIFTAG_FNUMBER, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FNumber", NULL},
- {EXIFTAG_EXPOSUREPROGRAM, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureProgram", NULL},
- {EXIFTAG_SPECTRALSENSITIVITY, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SpectralSensitivity", NULL},
- {EXIFTAG_ISOSPEEDRATINGS, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ISOSpeedRatings", NULL},
- {EXIFTAG_OECF, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "OptoelectricConversionFactor",
- NULL},
- {EXIFTAG_SENSITIVITYTYPE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SensitivityType", NULL},
- {EXIFTAG_STANDARDOUTPUTSENSITIVITY, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "StandardOutputSensitivity",
- NULL},
- {EXIFTAG_RECOMMENDEDEXPOSUREINDEX, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "RecommendedExposureIndex",
- NULL},
- {EXIFTAG_ISOSPEED, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ISOSpeed", NULL},
- {EXIFTAG_ISOSPEEDLATITUDEYYY, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ISOSpeedLatitudeyyy", NULL},
- {EXIFTAG_ISOSPEEDLATITUDEZZZ, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ISOSpeedLatitudezzz", NULL},
- {EXIFTAG_EXIFVERSION, 4, 4, TIFF_UNDEFINED, 0, TIFF_SETGET_C0_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExifVersion", NULL},
- {EXIFTAG_DATETIMEORIGINAL, 20, 20, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DateTimeOriginal", NULL},
- {EXIFTAG_DATETIMEDIGITIZED, 20, 20, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DateTimeDigitized", NULL},
- {EXIFTAG_OFFSETTIME, 7, 7, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "OffsetTime", NULL},
- {EXIFTAG_OFFSETTIMEORIGINAL, 7, 7, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "OffsetTimeOriginal", NULL},
- {EXIFTAG_OFFSETTIMEDIGITIZED, 7, 7, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "OffsetTimeDigitized", NULL},
- {EXIFTAG_COMPONENTSCONFIGURATION, 4, 4, TIFF_UNDEFINED, 0,
- TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0,
- "ComponentsConfiguration", NULL},
- {EXIFTAG_COMPRESSEDBITSPERPIXEL, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CompressedBitsPerPixel", NULL},
- {EXIFTAG_SHUTTERSPEEDVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ShutterSpeedValue", NULL},
- {EXIFTAG_APERTUREVALUE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ApertureValue", NULL},
- {EXIFTAG_BRIGHTNESSVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "BrightnessValue", NULL},
- {EXIFTAG_EXPOSUREBIASVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureBiasValue", NULL},
- {EXIFTAG_MAXAPERTUREVALUE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MaxApertureValue", NULL},
- /*--: EXIFTAG_SUBJECTDISTANCE: LibTiff returns value of "-1" if numerator
- * equals 4294967295 (0xFFFFFFFF) to indicate infinite distance! However,
- * there are two other EXIF tags where numerator indicates a special value
- * and six other cases where the denominator indicates special values, which
- * are not treated within LibTiff!! */
- {EXIFTAG_SUBJECTDISTANCE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubjectDistance", NULL},
- {EXIFTAG_METERINGMODE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MeteringMode", NULL},
- {EXIFTAG_LIGHTSOURCE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "LightSource", NULL},
- {EXIFTAG_FLASH, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Flash", NULL},
- {EXIFTAG_FOCALLENGTH, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalLength", NULL},
- {EXIFTAG_SUBJECTAREA, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "SubjectArea", NULL},
- {EXIFTAG_MAKERNOTE, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "MakerNote", NULL},
- {EXIFTAG_USERCOMMENT, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "UserComment", NULL},
- {EXIFTAG_SUBSECTIME, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubSecTime", NULL},
- {EXIFTAG_SUBSECTIMEORIGINAL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubSecTimeOriginal", NULL},
- {EXIFTAG_SUBSECTIMEDIGITIZED, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubSecTimeDigitized", NULL},
- {EXIFTAG_TEMPERATURE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Temperature", NULL},
- {EXIFTAG_HUMIDITY, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Humidity", NULL},
- {EXIFTAG_PRESSURE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Pressure", NULL},
- {EXIFTAG_WATERDEPTH, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "WaterDepth", NULL},
- {EXIFTAG_ACCELERATION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Acceleration", NULL},
- {EXIFTAG_CAMERAELEVATIONANGLE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CameraElevationAngle", NULL},
- {EXIFTAG_FLASHPIXVERSION, 4, 4, TIFF_UNDEFINED, 0, TIFF_SETGET_C0_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FlashpixVersion", NULL},
- {EXIFTAG_COLORSPACE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ColorSpace", NULL},
- {EXIFTAG_PIXELXDIMENSION, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PixelXDimension", NULL},
- {EXIFTAG_PIXELYDIMENSION, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PixelYDimension", NULL},
- {EXIFTAG_RELATEDSOUNDFILE, 13, 13, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "RelatedSoundFile", NULL},
- {EXIFTAG_FLASHENERGY, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FlashEnergy", NULL},
- {EXIFTAG_SPATIALFREQUENCYRESPONSE, -1, -1, TIFF_UNDEFINED, 0,
- TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1,
- "SpatialFrequencyResponse", NULL},
- {EXIFTAG_FOCALPLANEXRESOLUTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalPlaneXResolution", NULL},
- {EXIFTAG_FOCALPLANEYRESOLUTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalPlaneYResolution", NULL},
- {EXIFTAG_FOCALPLANERESOLUTIONUNIT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalPlaneResolutionUnit",
- NULL},
- {EXIFTAG_SUBJECTLOCATION, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_C0_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubjectLocation", NULL},
- {EXIFTAG_EXPOSUREINDEX, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureIndex", NULL},
- {EXIFTAG_SENSINGMETHOD, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SensingMethod", NULL},
- {EXIFTAG_FILESOURCE, 1, 1, TIFF_UNDEFINED, 0, TIFF_SETGET_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FileSource", NULL},
- {EXIFTAG_SCENETYPE, 1, 1, TIFF_UNDEFINED, 0, TIFF_SETGET_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SceneType", NULL},
- {EXIFTAG_CFAPATTERN, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CFAPattern", NULL},
- {EXIFTAG_CUSTOMRENDERED, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CustomRendered", NULL},
- {EXIFTAG_EXPOSUREMODE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureMode", NULL},
- {EXIFTAG_WHITEBALANCE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "WhiteBalance", NULL},
- {EXIFTAG_DIGITALZOOMRATIO, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DigitalZoomRatio", NULL},
- {EXIFTAG_FOCALLENGTHIN35MMFILM, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalLengthIn35mmFilm", NULL},
- {EXIFTAG_SCENECAPTURETYPE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SceneCaptureType", NULL},
- {EXIFTAG_GAINCONTROL, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "GainControl", NULL},
- {EXIFTAG_CONTRAST, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Contrast", NULL},
- {EXIFTAG_SATURATION, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Saturation", NULL},
- {EXIFTAG_SHARPNESS, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Sharpness", NULL},
- {EXIFTAG_DEVICESETTINGDESCRIPTION, -1, -1, TIFF_UNDEFINED, 0,
- TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1,
- "DeviceSettingDescription", NULL},
- {EXIFTAG_SUBJECTDISTANCERANGE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubjectDistanceRange", NULL},
- {EXIFTAG_IMAGEUNIQUEID, 33, 33, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageUniqueID", NULL},
- {EXIFTAG_CAMERAOWNERNAME, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CameraOwnerName", NULL},
- {EXIFTAG_BODYSERIALNUMBER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "BodySerialNumber", NULL},
- {EXIFTAG_LENSSPECIFICATION, 4, 4, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "LensSpecification", NULL},
- {EXIFTAG_LENSMAKE, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "LensMake", NULL},
- {EXIFTAG_LENSMODEL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "LensModel", NULL},
- {EXIFTAG_LENSSERIALNUMBER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "LensSerialNumber", NULL},
- {EXIFTAG_GAMMA, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Gamma", NULL},
- {EXIFTAG_COMPOSITEIMAGE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CompositeImage", NULL},
- {EXIFTAG_SOURCEIMAGENUMBEROFCOMPOSITEIMAGE, 2, 2, TIFF_SHORT, 0,
- TIFF_SETGET_C0_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0,
- "SourceImageNumberOfCompositeImage", NULL},
- {EXIFTAG_SOURCEEXPOSURETIMESOFCOMPOSITEIMAGE, -1, -1, TIFF_UNDEFINED, 0,
- TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1,
+ {EXIFTAG_EXPOSURETIME, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureTime", NULL},
+ {EXIFTAG_FNUMBER, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FNumber", NULL},
+ {EXIFTAG_EXPOSUREPROGRAM, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureProgram", NULL},
+ {EXIFTAG_SPECTRALSENSITIVITY, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SpectralSensitivity", NULL},
+ /* After EXIF 2.2.1 ISOSpeedRatings is named PhotographicSensitivity. In addition, while "Count=Any", only 1 count should be used. */
+ {EXIFTAG_ISOSPEEDRATINGS, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ISOSpeedRatings", NULL},
+ {EXIFTAG_OECF, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "OptoelectricConversionFactor", NULL},
+ {EXIFTAG_SENSITIVITYTYPE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SensitivityType", NULL},
+ {EXIFTAG_STANDARDOUTPUTSENSITIVITY, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "StandardOutputSensitivity", NULL},
+ {EXIFTAG_RECOMMENDEDEXPOSUREINDEX, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "RecommendedExposureIndex", NULL},
+ {EXIFTAG_ISOSPEED, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ISOSpeed", NULL},
+ {EXIFTAG_ISOSPEEDLATITUDEYYY, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ISOSpeedLatitudeyyy", NULL},
+ {EXIFTAG_ISOSPEEDLATITUDEZZZ, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ISOSpeedLatitudezzz", NULL},
+ {EXIFTAG_EXIFVERSION, 4, 4, TIFF_UNDEFINED, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExifVersion", NULL},
+ {EXIFTAG_DATETIMEORIGINAL, 20, 20, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DateTimeOriginal", NULL},
+ {EXIFTAG_DATETIMEDIGITIZED, 20, 20, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DateTimeDigitized", NULL},
+ {EXIFTAG_OFFSETTIME, 7, 7, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "OffsetTime", NULL},
+ {EXIFTAG_OFFSETTIMEORIGINAL, 7, 7, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "OffsetTimeOriginal", NULL},
+ {EXIFTAG_OFFSETTIMEDIGITIZED, 7, 7, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "OffsetTimeDigitized", NULL},
+ {EXIFTAG_COMPONENTSCONFIGURATION, 4, 4, TIFF_UNDEFINED, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ComponentsConfiguration", NULL},
+ {EXIFTAG_COMPRESSEDBITSPERPIXEL, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CompressedBitsPerPixel", NULL},
+ {EXIFTAG_SHUTTERSPEEDVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ShutterSpeedValue", NULL},
+ {EXIFTAG_APERTUREVALUE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ApertureValue", NULL},
+ {EXIFTAG_BRIGHTNESSVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "BrightnessValue", NULL},
+ {EXIFTAG_EXPOSUREBIASVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureBiasValue", NULL},
+ {EXIFTAG_MAXAPERTUREVALUE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MaxApertureValue", NULL},
+ /*--: EXIFTAG_SUBJECTDISTANCE: LibTiff returns value of "-1" if numerator equals 4294967295 (0xFFFFFFFF) to indicate infinite distance!
+ * However, there are two other EXIF tags where numerator indicates a special value and six other cases where the denominator indicates special values,
+ * which are not treated within LibTiff!! */
+ {EXIFTAG_SUBJECTDISTANCE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubjectDistance", NULL},
+ {EXIFTAG_METERINGMODE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MeteringMode", NULL},
+ {EXIFTAG_LIGHTSOURCE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "LightSource", NULL},
+ {EXIFTAG_FLASH, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Flash", NULL},
+ {EXIFTAG_FOCALLENGTH, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalLength", NULL},
+ {EXIFTAG_SUBJECTAREA, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "SubjectArea", NULL},
+ {EXIFTAG_MAKERNOTE, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "MakerNote", NULL},
+ {EXIFTAG_USERCOMMENT, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "UserComment", NULL},
+ {EXIFTAG_SUBSECTIME, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubSecTime", NULL},
+ {EXIFTAG_SUBSECTIMEORIGINAL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubSecTimeOriginal", NULL},
+ {EXIFTAG_SUBSECTIMEDIGITIZED, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubSecTimeDigitized", NULL},
+ {EXIFTAG_TEMPERATURE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Temperature", NULL},
+ {EXIFTAG_HUMIDITY, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Humidity", NULL},
+ {EXIFTAG_PRESSURE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Pressure", NULL},
+ {EXIFTAG_WATERDEPTH, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "WaterDepth", NULL},
+ {EXIFTAG_ACCELERATION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Acceleration", NULL},
+ {EXIFTAG_CAMERAELEVATIONANGLE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CameraElevationAngle", NULL},
+ {EXIFTAG_FLASHPIXVERSION, 4, 4, TIFF_UNDEFINED, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FlashpixVersion", NULL},
+ {EXIFTAG_COLORSPACE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ColorSpace", NULL},
+ {EXIFTAG_PIXELXDIMENSION, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PixelXDimension", NULL},
+ {EXIFTAG_PIXELYDIMENSION, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PixelYDimension", NULL},
+ {EXIFTAG_RELATEDSOUNDFILE, 13, 13, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "RelatedSoundFile", NULL},
+ {EXIFTAG_FLASHENERGY, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FlashEnergy", NULL},
+ {EXIFTAG_SPATIALFREQUENCYRESPONSE, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "SpatialFrequencyResponse", NULL},
+ {EXIFTAG_FOCALPLANEXRESOLUTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalPlaneXResolution", NULL},
+ {EXIFTAG_FOCALPLANEYRESOLUTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalPlaneYResolution", NULL},
+ {EXIFTAG_FOCALPLANERESOLUTIONUNIT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalPlaneResolutionUnit", NULL},
+ {EXIFTAG_SUBJECTLOCATION, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_C0_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubjectLocation", NULL},
+ {EXIFTAG_EXPOSUREINDEX, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureIndex", NULL},
+ {EXIFTAG_SENSINGMETHOD, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SensingMethod", NULL},
+ {EXIFTAG_FILESOURCE, 1, 1, TIFF_UNDEFINED, 0, TIFF_SETGET_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FileSource", NULL},
+ {EXIFTAG_SCENETYPE, 1, 1, TIFF_UNDEFINED, 0, TIFF_SETGET_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SceneType", NULL},
+ {EXIFTAG_CFAPATTERN, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CFAPattern", NULL},
+ {EXIFTAG_CUSTOMRENDERED, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CustomRendered", NULL},
+ {EXIFTAG_EXPOSUREMODE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureMode", NULL},
+ {EXIFTAG_WHITEBALANCE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "WhiteBalance", NULL},
+ {EXIFTAG_DIGITALZOOMRATIO, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DigitalZoomRatio", NULL},
+ {EXIFTAG_FOCALLENGTHIN35MMFILM, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalLengthIn35mmFilm", NULL},
+ {EXIFTAG_SCENECAPTURETYPE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SceneCaptureType", NULL},
+ {EXIFTAG_GAINCONTROL, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "GainControl", NULL},
+ {EXIFTAG_CONTRAST, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Contrast", NULL},
+ {EXIFTAG_SATURATION, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Saturation", NULL},
+ {EXIFTAG_SHARPNESS, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Sharpness", NULL},
+ {EXIFTAG_DEVICESETTINGDESCRIPTION, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "DeviceSettingDescription", NULL},
+ {EXIFTAG_SUBJECTDISTANCERANGE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubjectDistanceRange", NULL},
+ {EXIFTAG_IMAGEUNIQUEID, 33, 33, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageUniqueID", NULL},
+ {EXIFTAG_CAMERAOWNERNAME, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CameraOwnerName", NULL},
+ {EXIFTAG_BODYSERIALNUMBER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "BodySerialNumber", NULL},
+ {EXIFTAG_LENSSPECIFICATION, 4, 4, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "LensSpecification", NULL},
+ {EXIFTAG_LENSMAKE, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "LensMake", NULL},
+ {EXIFTAG_LENSMODEL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "LensModel", NULL},
+ {EXIFTAG_LENSSERIALNUMBER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "LensSerialNumber", NULL},
+ {EXIFTAG_GAMMA, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Gamma", NULL},
+ {EXIFTAG_COMPOSITEIMAGE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CompositeImage", NULL},
+ {EXIFTAG_SOURCEIMAGENUMBEROFCOMPOSITEIMAGE, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_C0_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SourceImageNumberOfCompositeImage", NULL},
+ {EXIFTAG_SOURCEEXPOSURETIMESOFCOMPOSITEIMAGE, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1,
"SourceExposureTimesOfCompositeImage", NULL}};
/*
* EXIF-GPS tags (Version 2.31, July 2016; nothing changed for version 2.32 May
@@ -598,79 +440,44 @@ static const TIFFField exifFields[] = {
*/
static const TIFFField gpsFields[] = {
- /* For the GPS tag definitions in gpsFields[] the standard definition for
- *Rationals is TIFF_SETGET_DOUBLE and TIFF_SETGET_C0_FLOAT.
- *-- ATTENTION: After the upgrade with Rational2Double, the GPSTAG values
- *can now be written and also read in double precision! In order to achieve
- *double precision for GPS tags: Standard definitions for GPSTAG is kept to
- *TIFF_SETGET_DOUBLE and TIFF_SETGET_C0_FLOAT is changed to
- *TIFF_SETGET_C0_DOUBLE.
+ /* For the GPS tag definitions in gpsFields[] the standard definition for Rationals is TIFF_SETGET_DOUBLE and TIFF_SETGET_C0_FLOAT.
+ *-- ATTENTION: After the upgrade with Rational2Double, the GPSTAG values can now be written and also read in double precision!
+ * In order to achieve double precision for GPS tags: Standard definitions for GPSTAG is kept to TIFF_SETGET_DOUBLE
+ * and TIFF_SETGET_C0_FLOAT is changed to TIFF_SETGET_C0_DOUBLE.
*/
- {GPSTAG_VERSIONID, 4, 4, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8,
- TIFF_SETGET_UINT8, FIELD_CUSTOM, 1, 0, "VersionID", NULL},
- {GPSTAG_LATITUDEREF, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "LatitudeRef", NULL},
- {GPSTAG_LATITUDE, 3, 3, TIFF_RATIONAL, 0, TIFF_SETGET_C0_DOUBLE,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Latitude", NULL},
- {GPSTAG_LONGITUDEREF, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "LongitudeRef", NULL},
- {GPSTAG_LONGITUDE, 3, 3, TIFF_RATIONAL, 0, TIFF_SETGET_C0_DOUBLE,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Longitude", NULL},
- {GPSTAG_ALTITUDEREF, 1, 1, TIFF_BYTE, 0, TIFF_SETGET_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "AltitudeRef", NULL},
- {GPSTAG_ALTITUDE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Altitude", NULL},
- {GPSTAG_TIMESTAMP, 3, 3, TIFF_RATIONAL, 0, TIFF_SETGET_C0_DOUBLE,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "TimeStamp", NULL},
- {GPSTAG_SATELLITES, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Satellites", NULL},
- {GPSTAG_STATUS, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Status", NULL},
- {GPSTAG_MEASUREMODE, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MeasureMode", NULL},
- {GPSTAG_DOP, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DOP", NULL},
- {GPSTAG_SPEEDREF, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SpeedRef", NULL},
- {GPSTAG_SPEED, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Speed", NULL},
- {GPSTAG_TRACKREF, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "TrackRef", NULL},
- {GPSTAG_TRACK, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Track", NULL},
- {GPSTAG_IMGDIRECTIONREF, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImgDirectionRef", NULL},
- {GPSTAG_IMGDIRECTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImgDirection", NULL},
- {GPSTAG_MAPDATUM, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MapDatum", NULL},
- {GPSTAG_DESTLATITUDEREF, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DestLatitudeRef", NULL},
- {GPSTAG_DESTLATITUDE, 3, 3, TIFF_RATIONAL, 0, TIFF_SETGET_C0_DOUBLE,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DestLatitude", NULL},
- {GPSTAG_DESTLONGITUDEREF, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DestLongitudeRef", NULL},
- {GPSTAG_DESTLONGITUDE, 3, 3, TIFF_RATIONAL, 0, TIFF_SETGET_C0_DOUBLE,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DestLongitude", NULL},
- {GPSTAG_DESTBEARINGREF, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DestBearingRef", NULL},
- {GPSTAG_DESTBEARING, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DestBearing", NULL},
- {GPSTAG_DESTDISTANCEREF, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DestDistanceRef", NULL},
- {GPSTAG_DESTDISTANCE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DestDistance", NULL},
- {GPSTAG_PROCESSINGMETHOD, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ProcessingMethod", NULL},
- {GPSTAG_AREAINFORMATION, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "AreaInformation", NULL},
- {GPSTAG_DATESTAMP, 11, 11, TIFF_ASCII, 0, TIFF_SETGET_ASCII,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DateStamp", NULL},
- {GPSTAG_DIFFERENTIAL, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Differential", NULL},
- {GPSTAG_GPSHPOSITIONINGERROR, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE,
- TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "HorizontalPositioningError",
- NULL}};
+ {GPSTAG_VERSIONID, 4, 4, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UINT8, FIELD_CUSTOM, 1, 0, "VersionID", NULL},
+ {GPSTAG_LATITUDEREF, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "LatitudeRef", NULL},
+ {GPSTAG_LATITUDE, 3, 3, TIFF_RATIONAL, 0, TIFF_SETGET_C0_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Latitude", NULL},
+ {GPSTAG_LONGITUDEREF, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "LongitudeRef", NULL},
+ {GPSTAG_LONGITUDE, 3, 3, TIFF_RATIONAL, 0, TIFF_SETGET_C0_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Longitude", NULL},
+ {GPSTAG_ALTITUDEREF, 1, 1, TIFF_BYTE, 0, TIFF_SETGET_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "AltitudeRef", NULL},
+ {GPSTAG_ALTITUDE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Altitude", NULL},
+ {GPSTAG_TIMESTAMP, 3, 3, TIFF_RATIONAL, 0, TIFF_SETGET_C0_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "TimeStamp", NULL},
+ {GPSTAG_SATELLITES, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Satellites", NULL},
+ {GPSTAG_STATUS, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Status", NULL},
+ {GPSTAG_MEASUREMODE, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MeasureMode", NULL},
+ {GPSTAG_DOP, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DOP", NULL},
+ {GPSTAG_SPEEDREF, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SpeedRef", NULL},
+ {GPSTAG_SPEED, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Speed", NULL},
+ {GPSTAG_TRACKREF, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "TrackRef", NULL},
+ {GPSTAG_TRACK, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Track", NULL},
+ {GPSTAG_IMGDIRECTIONREF, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImgDirectionRef", NULL},
+ {GPSTAG_IMGDIRECTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImgDirection", NULL},
+ {GPSTAG_MAPDATUM, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MapDatum", NULL},
+ {GPSTAG_DESTLATITUDEREF, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DestLatitudeRef", NULL},
+ {GPSTAG_DESTLATITUDE, 3, 3, TIFF_RATIONAL, 0, TIFF_SETGET_C0_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DestLatitude", NULL},
+ {GPSTAG_DESTLONGITUDEREF, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DestLongitudeRef", NULL},
+ {GPSTAG_DESTLONGITUDE, 3, 3, TIFF_RATIONAL, 0, TIFF_SETGET_C0_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DestLongitude", NULL},
+ {GPSTAG_DESTBEARINGREF, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DestBearingRef", NULL},
+ {GPSTAG_DESTBEARING, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DestBearing", NULL},
+ {GPSTAG_DESTDISTANCEREF, 2, 2, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DestDistanceRef", NULL},
+ {GPSTAG_DESTDISTANCE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DestDistance", NULL},
+ {GPSTAG_PROCESSINGMETHOD, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ProcessingMethod", NULL},
+ {GPSTAG_AREAINFORMATION, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "AreaInformation", NULL},
+ {GPSTAG_DATESTAMP, 11, 11, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DateStamp", NULL},
+ {GPSTAG_DIFFERENTIAL, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Differential", NULL},
+ {GPSTAG_GPSHPOSITIONINGERROR, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "HorizontalPositioningError", NULL}};
+/* clang-format on */ /* was off for better readability of tag comments */
static const TIFFFieldArray tiffFieldArray = {
tfiatImage, 0, TIFFArrayCount(tiffFields), (TIFFField *)tiffFields};
@@ -1039,8 +846,8 @@ const TIFFField *TIFFFieldWithTag(TIFF *tif, uint32_t tag)
const TIFFField *fip = TIFFFindField(tif, tag, TIFF_ANY);
if (!fip)
{
- TIFFErrorExtR(tif, "TIFFFieldWithTag",
- "Internal error, unknown tag 0x%x", (unsigned int)tag);
+ TIFFWarningExtR(tif, "TIFFFieldWithTag", "Warning, unknown tag 0x%x",
+ (unsigned int)tag);
}
return (fip);
}
@@ -1050,8 +857,8 @@ const TIFFField *TIFFFieldWithName(TIFF *tif, const char *field_name)
const TIFFField *fip = _TIFFFindFieldByName(tif, field_name, TIFF_ANY);
if (!fip)
{
- TIFFErrorExtR(tif, "TIFFFieldWithName",
- "Internal error, unknown tag %s", field_name);
+ TIFFWarningExtR(tif, "TIFFFieldWithName", "Warning, unknown tag %s",
+ field_name);
}
return (fip);
}
diff --git a/third_party/libtiff/tif_dirread.c b/third_party/libtiff/tif_dirread.c
index 4c3b75603..838f64db8 100644
--- a/third_party/libtiff/tif_dirread.c
+++ b/third_party/libtiff/tif_dirread.c
@@ -144,7 +144,11 @@ static void TIFFReadDirEntryCheckedFloat(TIFF *tif, TIFFDirEntry *direntry,
float *value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckedDouble(TIFF *tif, TIFFDirEntry *direntry, double *value);
-
+#if 0
+static enum TIFFReadDirEntryErr
+TIFFReadDirEntryCheckedRationalDirect(TIFF *tif, TIFFDirEntry *direntry,
+ TIFFRational_t *value);
+#endif
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeByteSbyte(int8_t value);
static enum TIFFReadDirEntryErr
@@ -3469,6 +3473,49 @@ TIFFReadDirEntryCheckedSrational(TIFF *tif, TIFFDirEntry *direntry,
return (TIFFReadDirEntryErrOk);
}
+#if 0
+static enum TIFFReadDirEntryErr
+TIFFReadDirEntryCheckedRationalDirect(TIFF *tif, TIFFDirEntry *direntry,
+ TIFFRational_t *value)
+{ /*--: SetGetRATIONAL_directly:_CustomTag: Read rational (and signed rationals)
+ directly --*/
+ UInt64Aligned_t m;
+
+ assert(sizeof(double) == 8);
+ assert(sizeof(uint64_t) == 8);
+ assert(sizeof(uint32_t) == 4);
+
+ if (direntry->tdir_count != 1)
+ return (TIFFReadDirEntryErrCount);
+
+ if (direntry->tdir_type != TIFF_RATIONAL &&
+ direntry->tdir_type != TIFF_SRATIONAL)
+ return (TIFFReadDirEntryErrType);
+
+ if (!(tif->tif_flags & TIFF_BIGTIFF))
+ {
+ enum TIFFReadDirEntryErr err;
+ uint32_t offset = direntry->tdir_offset.toff_long;
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong(&offset);
+ err = TIFFReadDirEntryData(tif, offset, 8, m.i);
+ if (err != TIFFReadDirEntryErrOk)
+ return (err);
+ }
+ else
+ {
+ m.l = direntry->tdir_offset.toff_long8;
+ }
+
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabArrayOfLong(m.i, 2);
+
+ value->uNum = m.i[0];
+ value->uDenom = m.i[1];
+ return (TIFFReadDirEntryErrOk);
+} /*-- TIFFReadDirEntryCheckedRationalDirect() --*/
+#endif
+
static void TIFFReadDirEntryCheckedFloat(TIFF *tif, TIFFDirEntry *direntry,
float *value)
{
@@ -4067,9 +4114,11 @@ int TIFFReadDirectory(TIFF *tif)
if (tif->tif_nextdiroff == 0)
{
- /* In this special case, tif_diroff needs also to be set to 0. */
+ /* In this special case, tif_diroff needs also to be set to 0.
+ * This is behind the last IFD, thus no checking or reading necessary.
+ */
tif->tif_diroff = tif->tif_nextdiroff;
- return 0; /* last offset, thus no checking necessary */
+ return 0;
}
nextdiroff = tif->tif_nextdiroff;
@@ -4523,7 +4572,52 @@ int TIFFReadDirectory(TIFF *tif)
}
}
break;
- /* END REV 4.0 COMPATIBILITY */
+ /* END REV 4.0 COMPATIBILITY */
+#if 0
+ case TIFFTAG_EP_BATTERYLEVEL:
+ /* TIFFTAG_EP_BATTERYLEVEL can be RATIONAL or ASCII.
+ * LibTiff defines it as ASCII and converts RATIONAL to an
+ * ASCII string. */
+ switch (dp->tdir_type)
+ {
+ case TIFF_RATIONAL:
+ {
+ /* Read rational and convert to ASCII*/
+ enum TIFFReadDirEntryErr err;
+ TIFFRational_t rValue;
+ err = TIFFReadDirEntryCheckedRationalDirect(
+ tif, dp, &rValue);
+ if (err != TIFFReadDirEntryErrOk)
+ {
+ fip = TIFFFieldWithTag(tif, dp->tdir_tag);
+ TIFFReadDirEntryOutputErr(
+ tif, err, module,
+ fip ? fip->field_name : "unknown tagname",
+ 1);
+ }
+ else
+ {
+ char szAux[32];
+ snprintf(szAux, sizeof(szAux) - 1, "%d/%d",
+ rValue.uNum, rValue.uDenom);
+ TIFFSetField(tif, dp->tdir_tag, szAux);
+ }
+ }
+ break;
+ case TIFF_ASCII:
+ (void)TIFFFetchNormalTag(tif, dp, TRUE);
+ break;
+ default:
+ fip = TIFFFieldWithTag(tif, dp->tdir_tag);
+ TIFFWarningExtR(tif, module,
+ "Invalid data type for tag %s. "
+ "ASCII or RATIONAL expected",
+ fip ? fip->field_name
+ : "unknown tagname");
+ break;
+ }
+ break;
+#endif
default:
(void)TIFFFetchNormalTag(tif, dp, TRUE);
break;
@@ -5139,6 +5233,8 @@ int TIFFReadCustomDirectory(TIFF *tif, toff_t diroff,
} /*-- if (!dp->tdir_ignore) */
}
}
+ /* To be able to return from SubIFD or custom-IFD to main-IFD */
+ tif->tif_setdirectory_force_absolute = TRUE;
if (dir)
_TIFFfreeExt(tif, dir);
return 1;
@@ -5456,7 +5552,8 @@ int _TIFFCheckDirNumberAndOffset(TIFF *tif, tdir_t dirn, uint64_t diroff)
}
/* Arbitrary (hopefully big enough) limit */
- if (tif->tif_dirnumber >= TIFF_MAX_DIR_COUNT)
+ if (TIFFHashSetSize(tif->tif_map_dir_offset_to_number) >=
+ TIFF_MAX_DIR_COUNT)
{
TIFFErrorExtR(tif, "_TIFFCheckDirNumberAndOffset",
"Cannot handle more than %u TIFF directories",
@@ -5489,8 +5586,6 @@ int _TIFFCheckDirNumberAndOffset(TIFF *tif, tdir_t dirn, uint64_t diroff)
return 0;
}
- tif->tif_dirnumber++;
-
return 1;
} /* --- _TIFFCheckDirNumberAndOffset() ---*/
@@ -5505,13 +5600,6 @@ int _TIFFGetDirNumberFromOffset(TIFF *tif, uint64_t diroff, tdir_t *dirn)
{
if (diroff == 0) /* no more directories */
return 0;
- if (tif->tif_dirnumber >= TIFF_MAX_DIR_COUNT)
- {
- TIFFErrorExtR(tif, "_TIFFGetDirNumberFromOffset",
- "Cannot handle more than %u TIFF directories",
- TIFF_MAX_DIR_COUNT);
- return 0;
- }
/* Check if offset is already in the list and return matching directory
* number. Otherwise update IFD list using TIFFNumberOfDirectories() and
@@ -5532,6 +5620,7 @@ int _TIFFGetDirNumberFromOffset(TIFF *tif, uint64_t diroff, tdir_t *dirn)
return 1;
}
+ /* This updates the directory list for all main-IFDs in the file. */
TIFFNumberOfDirectories(tif);
foundEntry = (TIFFOffsetAndDirNumber *)TIFFHashSetLookup(
@@ -5546,6 +5635,83 @@ int _TIFFGetDirNumberFromOffset(TIFF *tif, uint64_t diroff, tdir_t *dirn)
} /*--- _TIFFGetDirNumberFromOffset() ---*/
/*
+ * Retrieve the matching IFD directory offset of a given IFD number
+ * from the list of directories already seen.
+ * Returns 1 if the offset was in the list of already seen IFDs and the
+ * directory offset can be returned. The directory list is not updated.
+ * Otherwise returns 0 or if an error occurred.
+ */
+int _TIFFGetOffsetFromDirNumber(TIFF *tif, tdir_t dirn, uint64_t *diroff)
+{
+
+ if (tif->tif_map_dir_number_to_offset == NULL)
+ return 0;
+ TIFFOffsetAndDirNumber entry;
+ entry.offset = 0; /* not used */
+ entry.dirNumber = dirn;
+
+ TIFFOffsetAndDirNumber *foundEntry =
+ (TIFFOffsetAndDirNumber *)TIFFHashSetLookup(
+ tif->tif_map_dir_number_to_offset, &entry);
+ if (foundEntry)
+ {
+ *diroff = foundEntry->offset;
+ return 1;
+ }
+
+ return 0;
+} /*--- _TIFFGetOffsetFromDirNumber() ---*/
+
+/*
+ * Remove an entry from the directory list of already seen directories
+ * by directory offset.
+ * If an entry is to be removed from the list, it is also okay if the entry
+ * is not in the list or the list does not exist.
+ */
+int _TIFFRemoveEntryFromDirectoryListByOffset(TIFF *tif, uint64_t diroff)
+{
+ if (tif->tif_map_dir_offset_to_number == NULL)
+ return 1;
+
+ TIFFOffsetAndDirNumber entryOld;
+ entryOld.offset = diroff;
+ entryOld.dirNumber = 0;
+ /* We must remove first from tif_map_dir_number_to_offset as the
+ * entry is owned (and thus freed) by tif_map_dir_offset_to_number.
+ * However, we need firstly to find the directory number from offset. */
+
+ TIFFOffsetAndDirNumber *foundEntryOldOff =
+ (TIFFOffsetAndDirNumber *)TIFFHashSetLookup(
+ tif->tif_map_dir_offset_to_number, &entryOld);
+ if (foundEntryOldOff)
+ {
+ entryOld.dirNumber = foundEntryOldOff->dirNumber;
+ if (tif->tif_map_dir_number_to_offset != NULL)
+ {
+ TIFFOffsetAndDirNumber *foundEntryOldDir =
+ (TIFFOffsetAndDirNumber *)TIFFHashSetLookup(
+ tif->tif_map_dir_number_to_offset, &entryOld);
+ if (foundEntryOldDir)
+ {
+ TIFFHashSetRemove(tif->tif_map_dir_number_to_offset,
+ foundEntryOldDir);
+ TIFFHashSetRemove(tif->tif_map_dir_offset_to_number,
+ foundEntryOldOff);
+ return 1;
+ }
+ }
+ else
+ {
+ TIFFErrorExtR(tif, "_TIFFRemoveEntryFromDirectoryListByOffset",
+ "Unexpectedly tif_map_dir_number_to_offset is "
+ "missing but tif_map_dir_offset_to_number exists.");
+ return 0;
+ }
+ }
+ return 1;
+} /*--- _TIFFRemoveEntryFromDirectoryListByOffset() ---*/
+
+/*
* Check the count field of a directory entry against a known value. The
* caller is expected to skip/ignore the tag if there is a mismatch.
*/
diff --git a/third_party/libtiff/tif_dirwrite.c b/third_party/libtiff/tif_dirwrite.c
index beebd1160..a6a485f86 100644
--- a/third_party/libtiff/tif_dirwrite.c
+++ b/third_party/libtiff/tif_dirwrite.c
@@ -320,6 +320,7 @@ int TIFFRewriteDirectory(TIFF *tif)
* Find and zero the pointer to this directory, so that TIFFLinkDirectory
* will cause it to be added after this directories current pre-link.
*/
+ uint64_t torewritediroff = tif->tif_diroff;
if (!(tif->tif_flags & TIFF_BIGTIFF))
{
@@ -387,6 +388,8 @@ int TIFFRewriteDirectory(TIFF *tif)
nextdir = nextnextdir;
}
}
+ /* Remove skipped offset from IFD loop directory list. */
+ _TIFFRemoveEntryFromDirectoryListByOffset(tif, torewritediroff);
}
else
{
@@ -456,6 +459,8 @@ int TIFFRewriteDirectory(TIFF *tif)
nextdir = nextnextdir;
}
}
+ /* Remove skipped offset from IFD loop directory list. */
+ _TIFFRemoveEntryFromDirectoryListByOffset(tif, torewritediroff);
}
/*
@@ -1114,7 +1119,12 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
if (tif->tif_dataoff & 1)
tif->tif_dataoff++;
if (isimage)
- tif->tif_curdir++;
+ {
+ if (tif->tif_curdir == TIFF_NON_EXISTENT_DIR_NUMBER)
+ tif->tif_curdir = 0;
+ else
+ tif->tif_curdir++;
+ }
}
if (isimage)
{
diff --git a/third_party/libtiff/tif_fax3.c b/third_party/libtiff/tif_fax3.c
index 9d66fc0ec..a3c645cb6 100644
--- a/third_party/libtiff/tif_fax3.c
+++ b/third_party/libtiff/tif_fax3.c
@@ -537,7 +537,7 @@ static int Fax3SetupState(TIFF *tif)
TIFFroundup and TIFFSafeMultiply return zero on integer overflow
*/
dsp->runs = (uint32_t *)NULL;
- dsp->nruns = TIFFroundup_32(rowpixels, 32);
+ dsp->nruns = TIFFroundup_32(rowpixels + 1, 32);
if (needsRefLine)
{
dsp->nruns = TIFFSafeMultiply(uint32_t, dsp->nruns, 2);
diff --git a/third_party/libtiff/tif_hash_set.c b/third_party/libtiff/tif_hash_set.c
index 49718ce25..cec22ab6a 100644
--- a/third_party/libtiff/tif_hash_set.c
+++ b/third_party/libtiff/tif_hash_set.c
@@ -26,6 +26,8 @@
* DEALINGS IN THE SOFTWARE.
****************************************************************************/
+#include "tiffconf.h"
+
#include "tif_hash_set.h"
#include <assert.h>
@@ -161,7 +163,6 @@ TIFFHashSet *TIFFHashSetNew(TIFFHashSetHashFunc fnHashFunc,
return set;
}
-#ifdef notdef
/************************************************************************/
/* TIFFHashSetSize() */
/************************************************************************/
@@ -181,7 +182,6 @@ int TIFFHashSetSize(const TIFFHashSet *set)
assert(set != NULL);
return set->nSize;
}
-#endif
/************************************************************************/
/* TIFFHashSetGetNewListElt() */
diff --git a/third_party/libtiff/tif_hash_set.h b/third_party/libtiff/tif_hash_set.h
index 1a3f8da69..f60e2c675 100644
--- a/third_party/libtiff/tif_hash_set.h
+++ b/third_party/libtiff/tif_hash_set.h
@@ -71,11 +71,11 @@ extern "C"
void TIFFHashSetDestroy(TIFFHashSet *set);
+ int TIFFHashSetSize(const TIFFHashSet *set);
+
#ifdef notused
void TIFFHashSetClear(TIFFHashSet *set);
- int TIFFHashSetSize(const TIFFHashSet *set);
-
/** TIFFHashSetIterEltFunc */
typedef int (*TIFFHashSetIterEltFunc)(void *elt, void *user_data);
diff --git a/third_party/libtiff/tif_luv.c b/third_party/libtiff/tif_luv.c
index 051721e82..021756d5d 100644
--- a/third_party/libtiff/tif_luv.c
+++ b/third_party/libtiff/tif_luv.c
@@ -953,6 +953,13 @@ static
{
register int vi, ui;
+ /* check for NaN */
+ if (u != u || v != v)
+ {
+ u = U_NEU;
+ v = V_NEU;
+ }
+
if (v < UV_VSTART)
return oog_encode(u, v);
vi = tiff_itrunc((v - UV_VSTART) * (1. / UV_SQSIZ), em);
diff --git a/third_party/libtiff/tif_lzw.c b/third_party/libtiff/tif_lzw.c
index ba75a07ed..d631fa104 100644
--- a/third_party/libtiff/tif_lzw.c
+++ b/third_party/libtiff/tif_lzw.c
@@ -423,6 +423,10 @@ static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
if (sp->read_error)
{
+ TIFFErrorExtR(tif, module,
+ "LZWDecode: Scanline %" PRIu32 " cannot be read due to "
+ "previous error",
+ tif->tif_row);
return 0;
}
@@ -742,6 +746,7 @@ after_loop:
return (1);
no_eoi:
+ sp->read_error = 1;
TIFFErrorExtR(tif, module,
"LZWDecode: Strip %" PRIu32 " not terminated with EOI code",
tif->tif_curstrip);
diff --git a/third_party/libtiff/tif_open.c b/third_party/libtiff/tif_open.c
index 8a86a269d..23fcf81c4 100644
--- a/third_party/libtiff/tif_open.c
+++ b/third_party/libtiff/tif_open.c
@@ -365,8 +365,12 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
(tif->tif_flags & ~TIFF_FILLORDER) | FILLORDER_LSB2MSB;
break;
case 'H':
+ TIFFWarningExtR(tif, name,
+ "H(ost) mode is deprecated. Since "
+ "libtiff 4.5.1, it is an alias of 'B' / "
+ "FILLORDER_MSB2LSB.");
tif->tif_flags =
- (tif->tif_flags & ~TIFF_FILLORDER) | HOST_FILLORDER;
+ (tif->tif_flags & ~TIFF_FILLORDER) | FILLORDER_MSB2LSB;
break;
case 'M':
if (m == O_RDONLY)
@@ -485,7 +489,7 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
goto bad;
tif->tif_diroff = 0;
tif->tif_lastdiroff = 0;
- tif->tif_dirnumber = 0;
+ tif->tif_setdirectory_force_absolute = FALSE;
return (tif);
}
/*
diff --git a/third_party/libtiff/tiff.h b/third_party/libtiff/tiff.h
index 285a968a6..b2d118668 100644
--- a/third_party/libtiff/tiff.h
+++ b/third_party/libtiff/tiff.h
@@ -166,30 +166,30 @@ typedef enum
/*
* TIFF Tag Definitions.
*/
-#define TIFFTAG_SUBFILETYPE 254 /* subfile data descriptor */
-#define FILETYPE_REDUCEDIMAGE 0x1 /* reduced resolution version */
-#define FILETYPE_PAGE 0x2 /* one page of many */
-#define FILETYPE_MASK 0x4 /* transparency mask */
-#define TIFFTAG_OSUBFILETYPE 255 /* +kind of data in subfile */
-#define OFILETYPE_IMAGE 1 /* full resolution image data */
-#define OFILETYPE_REDUCEDIMAGE 2 /* reduced size image data */
-#define OFILETYPE_PAGE 3 /* one page of many */
-#define TIFFTAG_IMAGEWIDTH 256 /* image width in pixels */
-#define TIFFTAG_IMAGELENGTH 257 /* image height in pixels */
-#define TIFFTAG_BITSPERSAMPLE 258 /* bits per channel (sample) */
-#define TIFFTAG_COMPRESSION 259 /* data compression technique */
-#define COMPRESSION_NONE 1 /* dump mode */
-#define COMPRESSION_CCITTRLE 2 /* CCITT modified Huffman RLE */
-#define COMPRESSION_CCITTFAX3 3 /* CCITT Group 3 fax encoding */
-#define COMPRESSION_CCITT_T4 3 /* CCITT T.4 (TIFF 6 name) */
-#define COMPRESSION_CCITTFAX4 4 /* CCITT Group 4 fax encoding */
-#define COMPRESSION_CCITT_T6 4 /* CCITT T.6 (TIFF 6 name) */
-#define COMPRESSION_LZW 5 /* Lempel-Ziv & Welch */
-#define COMPRESSION_OJPEG 6 /* !6.0 JPEG */
-#define COMPRESSION_JPEG 7 /* %JPEG DCT compression */
-#define COMPRESSION_T85 9 /* !TIFF/FX T.85 JBIG compression */
-#define COMPRESSION_T43 \
- 10 /* !TIFF/FX T.43 colour by layered JBIG compression */
+/* clang-format off */ /* for better readability of tag comments */
+#define TIFFTAG_SUBFILETYPE 254 /* subfile data descriptor */
+#define FILETYPE_REDUCEDIMAGE 0x1 /* reduced resolution version */
+#define FILETYPE_PAGE 0x2 /* one page of many */
+#define FILETYPE_MASK 0x4 /* transparency mask */
+#define TIFFTAG_OSUBFILETYPE 255 /* +kind of data in subfile */
+#define OFILETYPE_IMAGE 1 /* full resolution image data */
+#define OFILETYPE_REDUCEDIMAGE 2 /* reduced size image data */
+#define OFILETYPE_PAGE 3 /* one page of many */
+#define TIFFTAG_IMAGEWIDTH 256 /* image width in pixels */
+#define TIFFTAG_IMAGELENGTH 257 /* image height in pixels */
+#define TIFFTAG_BITSPERSAMPLE 258 /* bits per channel (sample) */
+#define TIFFTAG_COMPRESSION 259 /* data compression technique */
+#define COMPRESSION_NONE 1 /* dump mode */
+#define COMPRESSION_CCITTRLE 2 /* CCITT modified Huffman RLE */
+#define COMPRESSION_CCITTFAX3 3 /* CCITT Group 3 fax encoding */
+#define COMPRESSION_CCITT_T4 3 /* CCITT T.4 (TIFF 6 name) */
+#define COMPRESSION_CCITTFAX4 4 /* CCITT Group 4 fax encoding */
+#define COMPRESSION_CCITT_T6 4 /* CCITT T.6 (TIFF 6 name) */
+#define COMPRESSION_LZW 5 /* Lempel-Ziv & Welch */
+#define COMPRESSION_OJPEG 6 /* !6.0 JPEG */
+#define COMPRESSION_JPEG 7 /* %JPEG DCT compression */
+#define COMPRESSION_T85 9 /* !TIFF/FX T.85 JBIG compression */
+#define COMPRESSION_T43 10 /* !TIFF/FX T.43 colour by layered JBIG compression */
#define COMPRESSION_NEXT 32766 /* NeXT 2-bit RLE */
#define COMPRESSION_CCITTRLEW 32771 /* #1 w/ word alignment */
#define COMPRESSION_PACKBITS 32773 /* Macintosh RLE */
@@ -203,113 +203,107 @@ typedef enum
#define COMPRESSION_PIXARFILM 32908 /* Pixar companded 10bit LZW */
#define COMPRESSION_PIXARLOG 32909 /* Pixar companded 11bit ZIP */
#define COMPRESSION_DEFLATE 32946 /* Deflate compression, legacy tag */
-#define COMPRESSION_ADOBE_DEFLATE \
- 8 /* Deflate compression, \
- as recognized by Adobe */
+#define COMPRESSION_ADOBE_DEFLATE 8 /* Deflate compression, as recognized by Adobe */
/* compression code 32947 is reserved for Oceana Matrix <dev@oceana.com> */
#define COMPRESSION_DCS 32947 /* Kodak DCS encoding */
#define COMPRESSION_JBIG 34661 /* ISO JBIG */
#define COMPRESSION_SGILOG 34676 /* SGI Log Luminance RLE */
#define COMPRESSION_SGILOG24 34677 /* SGI Log 24-bit packed */
#define COMPRESSION_JP2000 34712 /* Leadtools JPEG2000 */
-#define COMPRESSION_LERC \
- 34887 /* ESRI Lerc codec: https://github.com/Esri/lerc */
+#define COMPRESSION_LERC 34887 /* ESRI Lerc codec: https://github.com/Esri/lerc */
/* compression codes 34887-34889 are reserved for ESRI */
-#define COMPRESSION_LZMA 34925 /* LZMA2 */
-#define COMPRESSION_ZSTD \
- 50000 /* ZSTD: WARNING not registered in Adobe-maintained registry */
-#define COMPRESSION_WEBP \
- 50001 /* WEBP: WARNING not registered in Adobe-maintained registry */
-#define COMPRESSION_JXL \
- 50002 /* JPEGXL: WARNING not registered in Adobe-maintained registry */
-#define TIFFTAG_PHOTOMETRIC 262 /* photometric interpretation */
-#define PHOTOMETRIC_MINISWHITE 0 /* min value is white */
-#define PHOTOMETRIC_MINISBLACK 1 /* min value is black */
-#define PHOTOMETRIC_RGB 2 /* RGB color model */
-#define PHOTOMETRIC_PALETTE 3 /* color map indexed */
-#define PHOTOMETRIC_MASK 4 /* $holdout mask */
-#define PHOTOMETRIC_SEPARATED 5 /* !color separations */
-#define PHOTOMETRIC_YCBCR 6 /* !CCIR 601 */
-#define PHOTOMETRIC_CIELAB 8 /* !1976 CIE L*a*b* */
-#define PHOTOMETRIC_ICCLAB 9 /* ICC L*a*b* [Adobe TIFF Technote 4] */
-#define PHOTOMETRIC_ITULAB 10 /* ITU L*a*b* */
-#define PHOTOMETRIC_CFA 32803 /* color filter array */
-#define PHOTOMETRIC_LOGL 32844 /* CIE Log2(L) */
-#define PHOTOMETRIC_LOGLUV 32845 /* CIE Log2(L) (u',v') */
-#define TIFFTAG_THRESHHOLDING 263 /* +thresholding used on data */
-#define THRESHHOLD_BILEVEL 1 /* b&w art scan */
-#define THRESHHOLD_HALFTONE 2 /* or dithered scan */
-#define THRESHHOLD_ERRORDIFFUSE 3 /* usually floyd-steinberg */
-#define TIFFTAG_CELLWIDTH 264 /* +dithering matrix width */
-#define TIFFTAG_CELLLENGTH 265 /* +dithering matrix height */
-#define TIFFTAG_FILLORDER 266 /* data order within a byte */
-#define FILLORDER_MSB2LSB 1 /* most significant -> least */
-#define FILLORDER_LSB2MSB 2 /* least significant -> most */
-#define TIFFTAG_DOCUMENTNAME 269 /* name of doc. image is from */
-#define TIFFTAG_IMAGEDESCRIPTION 270 /* info about image */
-#define TIFFTAG_MAKE 271 /* scanner manufacturer name */
-#define TIFFTAG_MODEL 272 /* scanner model name/number */
-#define TIFFTAG_STRIPOFFSETS 273 /* offsets to data strips */
-#define TIFFTAG_ORIENTATION 274 /* +image orientation */
-#define ORIENTATION_TOPLEFT 1 /* row 0 top, col 0 lhs */
-#define ORIENTATION_TOPRIGHT 2 /* row 0 top, col 0 rhs */
-#define ORIENTATION_BOTRIGHT 3 /* row 0 bottom, col 0 rhs */
-#define ORIENTATION_BOTLEFT 4 /* row 0 bottom, col 0 lhs */
-#define ORIENTATION_LEFTTOP 5 /* row 0 lhs, col 0 top */
-#define ORIENTATION_RIGHTTOP 6 /* row 0 rhs, col 0 top */
-#define ORIENTATION_RIGHTBOT 7 /* row 0 rhs, col 0 bottom */
-#define ORIENTATION_LEFTBOT 8 /* row 0 lhs, col 0 bottom */
-#define TIFFTAG_SAMPLESPERPIXEL 277 /* samples per pixel */
-#define TIFFTAG_ROWSPERSTRIP 278 /* rows per strip of data */
-#define TIFFTAG_STRIPBYTECOUNTS 279 /* bytes counts for strips */
-#define TIFFTAG_MINSAMPLEVALUE 280 /* +minimum sample value */
-#define TIFFTAG_MAXSAMPLEVALUE 281 /* +maximum sample value */
-#define TIFFTAG_XRESOLUTION 282 /* pixels/resolution in x */
-#define TIFFTAG_YRESOLUTION 283 /* pixels/resolution in y */
-#define TIFFTAG_PLANARCONFIG 284 /* storage organization */
-#define PLANARCONFIG_CONTIG 1 /* single image plane */
-#define PLANARCONFIG_SEPARATE 2 /* separate planes of data */
-#define TIFFTAG_PAGENAME 285 /* page name image is from */
-#define TIFFTAG_XPOSITION 286 /* x page offset of image lhs */
-#define TIFFTAG_YPOSITION 287 /* y page offset of image lhs */
-#define TIFFTAG_FREEOFFSETS 288 /* +byte offset to free block */
-#define TIFFTAG_FREEBYTECOUNTS 289 /* +sizes of free blocks */
-#define TIFFTAG_GRAYRESPONSEUNIT 290 /* $gray scale curve accuracy */
-#define GRAYRESPONSEUNIT_10S 1 /* tenths of a unit */
-#define GRAYRESPONSEUNIT_100S 2 /* hundredths of a unit */
-#define GRAYRESPONSEUNIT_1000S 3 /* thousandths of a unit */
-#define GRAYRESPONSEUNIT_10000S 4 /* ten-thousandths of a unit */
-#define GRAYRESPONSEUNIT_100000S 5 /* hundred-thousandths */
-#define TIFFTAG_GRAYRESPONSECURVE 291 /* $gray scale response curve */
-#define TIFFTAG_GROUP3OPTIONS 292 /* 32 flag bits */
-#define TIFFTAG_T4OPTIONS 292 /* TIFF 6.0 proper name alias */
-#define GROUP3OPT_2DENCODING 0x1 /* 2-dimensional coding */
-#define GROUP3OPT_UNCOMPRESSED 0x2 /* data not compressed */
-#define GROUP3OPT_FILLBITS 0x4 /* fill to byte boundary */
-#define TIFFTAG_GROUP4OPTIONS 293 /* 32 flag bits */
-#define TIFFTAG_T6OPTIONS 293 /* TIFF 6.0 proper name */
-#define GROUP4OPT_UNCOMPRESSED 0x2 /* data not compressed */
-#define TIFFTAG_RESOLUTIONUNIT 296 /* units of resolutions */
-#define RESUNIT_NONE 1 /* no meaningful units */
-#define RESUNIT_INCH 2 /* english */
-#define RESUNIT_CENTIMETER 3 /* metric */
-#define TIFFTAG_PAGENUMBER 297 /* page numbers of multi-page */
-#define TIFFTAG_COLORRESPONSEUNIT 300 /* $color curve accuracy */
-#define COLORRESPONSEUNIT_10S 1 /* tenths of a unit */
-#define COLORRESPONSEUNIT_100S 2 /* hundredths of a unit */
-#define COLORRESPONSEUNIT_1000S 3 /* thousandths of a unit */
-#define COLORRESPONSEUNIT_10000S 4 /* ten-thousandths of a unit */
-#define COLORRESPONSEUNIT_100000S 5 /* hundred-thousandths */
-#define TIFFTAG_TRANSFERFUNCTION 301 /* !colorimetry info */
-#define TIFFTAG_SOFTWARE 305 /* name & release */
-#define TIFFTAG_DATETIME 306 /* creation date and time */
-#define TIFFTAG_ARTIST 315 /* creator of image */
-#define TIFFTAG_HOSTCOMPUTER 316 /* machine where created */
-#define TIFFTAG_PREDICTOR 317 /* prediction scheme w/ LZW */
-#define PREDICTOR_NONE 1 /* no prediction scheme used */
-#define PREDICTOR_HORIZONTAL 2 /* horizontal differencing */
-#define PREDICTOR_FLOATINGPOINT 3 /* floating point predictor */
-#define TIFFTAG_WHITEPOINT 318 /* image white point */
+#define COMPRESSION_LZMA 34925 /* LZMA2 */
+#define COMPRESSION_ZSTD 50000 /* ZSTD: WARNING not registered in Adobe-maintained registry */
+#define COMPRESSION_WEBP 50001 /* WEBP: WARNING not registered in Adobe-maintained registry */
+#define COMPRESSION_JXL 50002 /* JPEGXL: WARNING not registered in Adobe-maintained registry */
+#define TIFFTAG_PHOTOMETRIC 262 /* photometric interpretation */
+#define PHOTOMETRIC_MINISWHITE 0 /* min value is white */
+#define PHOTOMETRIC_MINISBLACK 1 /* min value is black */
+#define PHOTOMETRIC_RGB 2 /* RGB color model */
+#define PHOTOMETRIC_PALETTE 3 /* color map indexed */
+#define PHOTOMETRIC_MASK 4 /* $holdout mask */
+#define PHOTOMETRIC_SEPARATED 5 /* !color separations */
+#define PHOTOMETRIC_YCBCR 6 /* !CCIR 601 */
+#define PHOTOMETRIC_CIELAB 8 /* !1976 CIE L*a*b* */
+#define PHOTOMETRIC_ICCLAB 9 /* ICC L*a*b* [Adobe TIFF Technote 4] */
+#define PHOTOMETRIC_ITULAB 10 /* ITU L*a*b* */
+#define PHOTOMETRIC_CFA 32803 /* color filter array */
+#define PHOTOMETRIC_LOGL 32844 /* CIE Log2(L) */
+#define PHOTOMETRIC_LOGLUV 32845 /* CIE Log2(L) (u',v') */
+#define TIFFTAG_THRESHHOLDING 263 /* +thresholding used on data */
+#define THRESHHOLD_BILEVEL 1 /* b&w art scan */
+#define THRESHHOLD_HALFTONE 2 /* or dithered scan */
+#define THRESHHOLD_ERRORDIFFUSE 3 /* usually floyd-steinberg */
+#define TIFFTAG_CELLWIDTH 264 /* +dithering matrix width */
+#define TIFFTAG_CELLLENGTH 265 /* +dithering matrix height */
+#define TIFFTAG_FILLORDER 266 /* data order within a byte */
+#define FILLORDER_MSB2LSB 1 /* most significant -> least */
+#define FILLORDER_LSB2MSB 2 /* least significant -> most */
+#define TIFFTAG_DOCUMENTNAME 269 /* name of doc. image is from */
+#define TIFFTAG_IMAGEDESCRIPTION 270 /* info about image */
+#define TIFFTAG_MAKE 271 /* scanner manufacturer name */
+#define TIFFTAG_MODEL 272 /* scanner model name/number */
+#define TIFFTAG_STRIPOFFSETS 273 /* offsets to data strips */
+#define TIFFTAG_ORIENTATION 274 /* +image orientation */
+#define ORIENTATION_TOPLEFT 1 /* row 0 top, col 0 lhs */
+#define ORIENTATION_TOPRIGHT 2 /* row 0 top, col 0 rhs */
+#define ORIENTATION_BOTRIGHT 3 /* row 0 bottom, col 0 rhs */
+#define ORIENTATION_BOTLEFT 4 /* row 0 bottom, col 0 lhs */
+#define ORIENTATION_LEFTTOP 5 /* row 0 lhs, col 0 top */
+#define ORIENTATION_RIGHTTOP 6 /* row 0 rhs, col 0 top */
+#define ORIENTATION_RIGHTBOT 7 /* row 0 rhs, col 0 bottom */
+#define ORIENTATION_LEFTBOT 8 /* row 0 lhs, col 0 bottom */
+#define TIFFTAG_SAMPLESPERPIXEL 277 /* samples per pixel */
+#define TIFFTAG_ROWSPERSTRIP 278 /* rows per strip of data */
+#define TIFFTAG_STRIPBYTECOUNTS 279 /* bytes counts for strips */
+#define TIFFTAG_MINSAMPLEVALUE 280 /* +minimum sample value */
+#define TIFFTAG_MAXSAMPLEVALUE 281 /* +maximum sample value */
+#define TIFFTAG_XRESOLUTION 282 /* pixels/resolution in x */
+#define TIFFTAG_YRESOLUTION 283 /* pixels/resolution in y */
+#define TIFFTAG_PLANARCONFIG 284 /* storage organization */
+#define PLANARCONFIG_CONTIG 1 /* single image plane */
+#define PLANARCONFIG_SEPARATE 2 /* separate planes of data */
+#define TIFFTAG_PAGENAME 285 /* page name image is from */
+#define TIFFTAG_XPOSITION 286 /* x page offset of image lhs */
+#define TIFFTAG_YPOSITION 287 /* y page offset of image lhs */
+#define TIFFTAG_FREEOFFSETS 288 /* +byte offset to free block */
+#define TIFFTAG_FREEBYTECOUNTS 289 /* +sizes of free blocks */
+#define TIFFTAG_GRAYRESPONSEUNIT 290 /* $gray scale curve accuracy */
+#define GRAYRESPONSEUNIT_10S 1 /* tenths of a unit */
+#define GRAYRESPONSEUNIT_100S 2 /* hundredths of a unit */
+#define GRAYRESPONSEUNIT_1000S 3 /* thousandths of a unit */
+#define GRAYRESPONSEUNIT_10000S 4 /* ten-thousandths of a unit */
+#define GRAYRESPONSEUNIT_100000S 5 /* hundred-thousandths */
+#define TIFFTAG_GRAYRESPONSECURVE 291 /* $gray scale response curve */
+#define TIFFTAG_GROUP3OPTIONS 292 /* 32 flag bits */
+#define TIFFTAG_T4OPTIONS 292 /* TIFF 6.0 proper name alias */
+#define GROUP3OPT_2DENCODING 0x1 /* 2-dimensional coding */
+#define GROUP3OPT_UNCOMPRESSED 0x2 /* data not compressed */
+#define GROUP3OPT_FILLBITS 0x4 /* fill to byte boundary */
+#define TIFFTAG_GROUP4OPTIONS 293 /* 32 flag bits */
+#define TIFFTAG_T6OPTIONS 293 /* TIFF 6.0 proper name */
+#define GROUP4OPT_UNCOMPRESSED 0x2 /* data not compressed */
+#define TIFFTAG_RESOLUTIONUNIT 296 /* units of resolutions */
+#define RESUNIT_NONE 1 /* no meaningful units */
+#define RESUNIT_INCH 2 /* english */
+#define RESUNIT_CENTIMETER 3 /* metric */
+#define TIFFTAG_PAGENUMBER 297 /* page numbers of multi-page */
+#define TIFFTAG_COLORRESPONSEUNIT 300 /* $color curve accuracy */
+#define COLORRESPONSEUNIT_10S 1 /* tenths of a unit */
+#define COLORRESPONSEUNIT_100S 2 /* hundredths of a unit */
+#define COLORRESPONSEUNIT_1000S 3 /* thousandths of a unit */
+#define COLORRESPONSEUNIT_10000S 4 /* ten-thousandths of a unit */
+#define COLORRESPONSEUNIT_100000S 5 /* hundred-thousandths */
+#define TIFFTAG_TRANSFERFUNCTION 301 /* !colorimetry info */
+#define TIFFTAG_SOFTWARE 305 /* name & release */
+#define TIFFTAG_DATETIME 306 /* creation date and time */
+#define TIFFTAG_ARTIST 315 /* creator of image */
+#define TIFFTAG_HOSTCOMPUTER 316 /* machine where created */
+#define TIFFTAG_PREDICTOR 317 /* prediction scheme w/ LZW */
+#define PREDICTOR_NONE 1 /* no prediction scheme used */
+#define PREDICTOR_HORIZONTAL 2 /* horizontal differencing */
+#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 palette image */
#define TIFFTAG_HALFTONEHINTS 321 /* !highlight+shadow info */
@@ -325,39 +319,31 @@ typedef enum
#define TIFFTAG_CONSECUTIVEBADFAXLINES 328 /* max consecutive bad lines */
#define TIFFTAG_SUBIFD 330 /* subimage descriptors */
#define TIFFTAG_INKSET 332 /* !inks in separated image */
-#define INKSET_CMYK 1 /* !cyan-magenta-yellow-black color */
-#define INKSET_MULTIINK 2 /* !multi-ink or hi-fi color */
-#define TIFFTAG_INKNAMES 333 /* !ascii names of inks */
-#define TIFFTAG_NUMBEROFINKS 334 /* !number of inks */
-#define TIFFTAG_DOTRANGE 336 /* !0% and 100% dot codes */
-#define TIFFTAG_TARGETPRINTER 337 /* !separation target */
-#define TIFFTAG_EXTRASAMPLES 338 /* !info about extra samples */
-#define EXTRASAMPLE_UNSPECIFIED 0 /* !unspecified data */
-#define EXTRASAMPLE_ASSOCALPHA 1 /* !associated alpha data */
-#define EXTRASAMPLE_UNASSALPHA 2 /* !unassociated alpha data */
-#define TIFFTAG_SAMPLEFORMAT 339 /* !data sample format */
-#define SAMPLEFORMAT_UINT 1 /* !unsigned integer data */
-#define SAMPLEFORMAT_INT 2 /* !signed integer data */
-#define SAMPLEFORMAT_IEEEFP 3 /* !IEEE floating point data */
-#define SAMPLEFORMAT_VOID 4 /* !untyped data */
-#define SAMPLEFORMAT_COMPLEXINT 5 /* !complex signed int */
-#define SAMPLEFORMAT_COMPLEXIEEEFP 6 /* !complex ieee floating */
-#define TIFFTAG_SMINSAMPLEVALUE 340 /* !variable MinSampleValue */
-#define TIFFTAG_SMAXSAMPLEVALUE 341 /* !variable MaxSampleValue */
-#define TIFFTAG_CLIPPATH \
- 343 /* %ClipPath \
- [Adobe TIFF technote 2] */
-#define TIFFTAG_XCLIPPATHUNITS \
- 344 /* %XClipPathUnits \
- [Adobe TIFF technote 2] */
-#define TIFFTAG_YCLIPPATHUNITS \
- 345 /* %YClipPathUnits \
- [Adobe TIFF technote 2] */
-#define TIFFTAG_INDEXED \
- 346 /* %Indexed \
- [Adobe TIFF Technote 3] */
-#define TIFFTAG_JPEGTABLES 347 /* %JPEG table stream */
-#define TIFFTAG_OPIPROXY 351 /* %OPI Proxy [Adobe TIFF technote] */
+#define INKSET_CMYK 1 /* !cyan-magenta-yellow-black color */
+#define INKSET_MULTIINK 2 /* !multi-ink or hi-fi color */
+#define TIFFTAG_INKNAMES 333 /* !ascii names of inks */
+#define TIFFTAG_NUMBEROFINKS 334 /* !number of inks */
+#define TIFFTAG_DOTRANGE 336 /* !0% and 100% dot codes */
+#define TIFFTAG_TARGETPRINTER 337 /* !separation target */
+#define TIFFTAG_EXTRASAMPLES 338 /* !info about extra samples */
+#define EXTRASAMPLE_UNSPECIFIED 0 /* !unspecified data */
+#define EXTRASAMPLE_ASSOCALPHA 1 /* !associated alpha data */
+#define EXTRASAMPLE_UNASSALPHA 2 /* !unassociated alpha data */
+#define TIFFTAG_SAMPLEFORMAT 339 /* !data sample format */
+#define SAMPLEFORMAT_UINT 1 /* !unsigned integer data */
+#define SAMPLEFORMAT_INT 2 /* !signed integer data */
+#define SAMPLEFORMAT_IEEEFP 3 /* !IEEE floating point data */
+#define SAMPLEFORMAT_VOID 4 /* !untyped data */
+#define SAMPLEFORMAT_COMPLEXINT 5 /* !complex signed int */
+#define SAMPLEFORMAT_COMPLEXIEEEFP 6 /* !complex ieee floating */
+#define TIFFTAG_SMINSAMPLEVALUE 340 /* !variable MinSampleValue */
+#define TIFFTAG_SMAXSAMPLEVALUE 341 /* !variable MaxSampleValue */
+#define TIFFTAG_CLIPPATH 343 /* %ClipPath [Adobe TIFF technote 2] */
+#define TIFFTAG_XCLIPPATHUNITS 344 /* %XClipPathUnits [Adobe TIFF technote 2] */
+#define TIFFTAG_YCLIPPATHUNITS 345 /* %YClipPathUnits [Adobe TIFF technote 2] */
+#define TIFFTAG_INDEXED 346 /* %Indexed [Adobe TIFF Technote 3] */
+#define TIFFTAG_JPEGTABLES 347 /* %JPEG table stream */
+#define TIFFTAG_OPIPROXY 351 /* %OPI Proxy [Adobe TIFF technote] */
/* Tags 400-435 are from the TIFF/FX spec */
#define TIFFTAG_GLOBALPARAMETERSIFD 400 /* ! */
#define TIFFTAG_PROFILETYPE 401 /* ! */
@@ -404,16 +390,11 @@ typedef enum
#define YCBCRPOSITION_COSITED 2 /* !as in CCIR 601-1 */
#define TIFFTAG_REFERENCEBLACKWHITE 532 /* !colorimetry info */
#define TIFFTAG_STRIPROWCOUNTS 559 /* !TIFF/FX strip row counts */
-#define TIFFTAG_XMLPACKET \
- 700 /* %XML packet \
- [Adobe XMP Specification, \
- January 2004 */
-#define TIFFTAG_OPIIMAGEID \
- 32781 /* %OPI ImageID \
- [Adobe TIFF technote] */
-#define TIFFTAG_TIFFANNOTATIONDATA \
- 32932 /* http://web.archive.org/web/20050309141348/http://www.kofile.com/support%20pro/faqs/annospec.htm \
- */
+#define TIFFTAG_XMLPACKET 700 /* %XML packet [Adobe XMP Specification, January 2004 */
+#define TIFFTAG_OPIIMAGEID 32781 /* %OPI ImageID [Adobe TIFF technote] */
+/* For eiStream Annotation Specification, Version 1.00.06 see
+ * http://web.archive.org/web/20050309141348/http://www.kofile.com/support%20pro/faqs/annospec.htm */
+#define TIFFTAG_TIFFANNOTATIONDATA 32932
/* tags 32952-32956 are private tags registered to Island Graphics */
#define TIFFTAG_REFPTS 32953 /* image reference points */
#define TIFFTAG_REGIONTACKPOINT 32954 /* region-xform tack point */
@@ -444,53 +425,36 @@ typedef enum
#define TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA 33306
/* tag 33405 is a private tag registered to Eastman Kodak */
#define TIFFTAG_WRITERSERIALNUMBER 33405 /* device serial number */
-#define TIFFTAG_CFAREPEATPATTERNDIM 33421 /* dimensions of CFA pattern */
-#define TIFFTAG_CFAPATTERN 33422 /* color filter array pattern */
+#define TIFFTAG_CFAREPEATPATTERNDIM 33421 /* (alias for TIFFTAG_EP_CFAREPEATPATTERNDIM)*/
+#define TIFFTAG_CFAPATTERN 33422 /* (alias for TIFFTAG_EP_CFAPATTERN) */
+#define TIFFTAG_BATTERYLEVEL 33423 /* (alias for TIFFTAG_EP_BATTERYLEVEL) */
/* tag 33432 is listed in the 6.0 spec w/ unknown ownership */
#define TIFFTAG_COPYRIGHT 33432 /* copyright string */
-/* Tags 33445-33452 are used for GEL fileformat, see
- * http://research.stowers-institute.org/mcm/efg/ScientificSoftware/Utility/TiffTags/GEL-FileFormat.pdf
+/* Tags 33445-33452 are used for Molecular Dynamics GEL fileformat,
+ * see http://research.stowers-institute.org/mcm/efg/ScientificSoftware/Utility/TiffTags/GEL-FileFormat.pdf
+ * (2023: the above web site is unavailable but tags are explained briefly at
+ * https://www.awaresystems.be/imaging/tiff/tifftags/docs/gel.html
*/
-#define TIFFTAG_MD_FILETAG \
- 33445 /* http://research.stowers-institute.org/mcm/efg/ScientificSoftware/Utility/TiffTags/GEL-FileFormat.pdf \
- */
-#define TIFFTAG_MD_SCALEPIXEL \
- 33446 /* http://research.stowers-institute.org/mcm/efg/ScientificSoftware/Utility/TiffTags/GEL-FileFormat.pdf \
- */
-#define TIFFTAG_MD_COLORTABLE \
- 33447 /* http://research.stowers-institute.org/mcm/efg/ScientificSoftware/Utility/TiffTags/GEL-FileFormat.pdf \
- */
-#define TIFFTAG_MD_LABNAME \
- 33448 /* http://research.stowers-institute.org/mcm/efg/ScientificSoftware/Utility/TiffTags/GEL-FileFormat.pdf \
- */
-#define TIFFTAG_MD_SAMPLEINFO \
- 33449 /* http://research.stowers-institute.org/mcm/efg/ScientificSoftware/Utility/TiffTags/GEL-FileFormat.pdf \
- */
-#define TIFFTAG_MD_PREPDATE \
- 33450 /* http://research.stowers-institute.org/mcm/efg/ScientificSoftware/Utility/TiffTags/GEL-FileFormat.pdf \
- */
-#define TIFFTAG_MD_PREPTIME \
- 33451 /* http://research.stowers-institute.org/mcm/efg/ScientificSoftware/Utility/TiffTags/GEL-FileFormat.pdf \
- */
-#define TIFFTAG_MD_FILEUNITS \
- 33452 /* http://research.stowers-institute.org/mcm/efg/ScientificSoftware/Utility/TiffTags/GEL-FileFormat.pdf \
- */
+#define TIFFTAG_MD_FILETAG 33445 /* Specifies the pixel data format encoding in the GEL file format. */
+#define TIFFTAG_MD_SCALEPIXEL 33446 /* scale factor */
+#define TIFFTAG_MD_COLORTABLE 33447 /* conversion from 16bit to 8bit */
+#define TIFFTAG_MD_LABNAME 33448 /* name of the lab that scanned this file. */
+#define TIFFTAG_MD_SAMPLEINFO 33449 /* information about the scanned GEL sample */
+#define TIFFTAG_MD_PREPDATE 33450 /* information about the date the sample was prepared YY/MM/DD */
+#define TIFFTAG_MD_PREPTIME 33451 /* information about the time the sample was prepared HH:MM*/
+#define TIFFTAG_MD_FILEUNITS 33452 /* Units for data in this file, as used in the GEL file format. */
/* IPTC TAG from RichTIFF specifications */
#define TIFFTAG_RICHTIFFIPTC 33723
-#define TIFFTAG_INGR_PACKET_DATA_TAG \
- 33918 /* Intergraph Application specific storage. */
-#define TIFFTAG_INGR_FLAG_REGISTERS \
- 33919 /* Intergraph Application specific flags. */
-#define TIFFTAG_IRASB_TRANSORMATION_MATRIX \
- 33920 /* Originally part of Intergraph's GeoTIFF tags, but likely \
- understood by IrasB only. */
-#define TIFFTAG_MODELTIEPOINTTAG 33922 /* GeoTIFF */
+#define TIFFTAG_INGR_PACKET_DATA_TAG 33918 /* Intergraph Application specific storage. */
+#define TIFFTAG_INGR_FLAG_REGISTERS 33919 /* Intergraph Application specific flags. */
+#define TIFFTAG_IRASB_TRANSORMATION_MATRIX 33920 /* Originally part of Intergraph's GeoTIFF tags, but likely understood by IrasB only. */
+#define TIFFTAG_MODELTIEPOINTTAG 33922 /* GeoTIFF */
/* 34016-34029 are reserved for ANSI IT8 TIFF/IT <dkelly@apago.com) */
-#define TIFFTAG_IT8SITE 34016 /* site name */
-#define TIFFTAG_IT8COLORSEQUENCE 34017 /* color seq. [RGB,CMYK,etc] */
-#define TIFFTAG_IT8HEADER 34018 /* DDES Header */
-#define TIFFTAG_IT8RASTERPADDING 34019 /* raster scanline padding */
-#define TIFFTAG_IT8BITSPERRUNLENGTH 34020 /* # of bits in short run */
+#define TIFFTAG_IT8SITE 34016 /* site name */
+#define TIFFTAG_IT8COLORSEQUENCE 34017 /* color seq. [RGB,CMYK,etc] */
+#define TIFFTAG_IT8HEADER 34018 /* DDES Header */
+#define TIFFTAG_IT8RASTERPADDING 34019 /* raster scanline padding */
+#define TIFFTAG_IT8BITSPERRUNLENGTH 34020 /* # of bits in short run */
#define TIFFTAG_IT8BITSPEREXTENDEDRUNLENGTH 34021 /* # of bits in long run */
#define TIFFTAG_IT8COLORTABLE 34022 /* LW colortable */
#define TIFFTAG_IT8IMAGECOLORINDICATOR 34023 /* BP/BL image color switch */
@@ -501,14 +465,11 @@ typedef enum
#define TIFFTAG_IT8TRANSPARENCYINDICATOR 34028 /* HC transparency switch */
#define TIFFTAG_IT8COLORCHARACTERIZATION 34029 /* color character. table */
#define TIFFTAG_IT8HCUSAGE 34030 /* HC usage indicator */
-#define TIFFTAG_IT8TRAPINDICATOR \
- 34031 /* Trapping indicator \
- (untrapped=0, trapped=1) */
-#define TIFFTAG_IT8CMYKEQUIVALENT 34032 /* CMYK color equivalents */
+#define TIFFTAG_IT8TRAPINDICATOR 34031 /* Trapping indicator (untrapped=0, trapped=1) */
+#define TIFFTAG_IT8CMYKEQUIVALENT 34032 /* CMYK color equivalents */
/* tags 34232-34236 are private tags registered to Texas Instruments */
-#define TIFFTAG_FRAMECOUNT 34232 /* Sequence Frame Count */
-#define TIFFTAG_MODELTRANSFORMATIONTAG \
- 34264 /* Used in interchangeable GeoTIFF files */
+#define TIFFTAG_FRAMECOUNT 34232 /* Sequence Frame Count */
+#define TIFFTAG_MODELTRANSFORMATIONTAG 34264 /* Used in interchangeable GeoTIFF files */
/* tag 34377 is private tag registered to Adobe for PhotoShop */
#define TIFFTAG_PHOTOSHOP 34377
/* tags 34665, 34853 and 40965 are documented in EXIF specification */
@@ -518,7 +479,7 @@ typedef enum
#define TIFFTAG_IMAGELAYER 34732 /* !TIFF/FX image layer information */
/* tag 34750 is a private tag registered to Pixel Magic */
#define TIFFTAG_JBIGOPTIONS 34750 /* JBIG options */
-#define TIFFTAG_GPSIFD 34853 /* Pointer to GPS private directory */
+#define TIFFTAG_GPSIFD 34853 /* Pointer to EXIF GPS private directory */
/* tags 34908-34914 are private tags registered to SGI */
#define TIFFTAG_FAXRECVPARAMS 34908 /* encoded Class 2 ses. params */
#define TIFFTAG_FAXSUBADDRESS 34909 /* received SubAddr string */
@@ -527,150 +488,196 @@ typedef enum
/* tags 37439-37443 are registered to SGI <gregl@sgi.com> */
#define TIFFTAG_STONITS 37439 /* Sample value to Nits */
/* tag 34929 is a private tag registered to FedEx */
-#define TIFFTAG_FEDEX_EDR 34929 /* unknown use */
-#define TIFFTAG_IMAGESOURCEDATA \
- 37724 /* http://justsolve.archiveteam.org/wiki/PSD, \
- http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/ */
-#define TIFFTAG_INTEROPERABILITYIFD \
- 40965 /* Pointer to Interoperability private directory */
-#define TIFFTAG_GDAL_METADATA 42112 /* Used by the GDAL library */
-#define TIFFTAG_GDAL_NODATA 42113 /* Used by the GDAL library */
-#define TIFFTAG_OCE_SCANJOB_DESCRIPTION \
- 50215 /* Used in the Oce scanning process */
-#define TIFFTAG_OCE_APPLICATION_SELECTOR \
- 50216 /* Used in the Oce scanning process. */
+#define TIFFTAG_FEDEX_EDR 34929 /* unknown use */
+#define TIFFTAG_IMAGESOURCEDATA 37724 /* http://justsolve.archiveteam.org/wiki/PSD, http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/ */
+#define TIFFTAG_INTEROPERABILITYIFD 40965 /* Pointer to EXIF Interoperability private directory */
+#define TIFFTAG_GDAL_METADATA 42112 /* Used by the GDAL library */
+#define TIFFTAG_GDAL_NODATA 42113 /* Used by the GDAL library */
+#define TIFFTAG_OCE_SCANJOB_DESCRIPTION 50215 /* Used in the Oce scanning process */
+#define TIFFTAG_OCE_APPLICATION_SELECTOR 50216 /* Used in the Oce scanning process. */
#define TIFFTAG_OCE_IDENTIFICATION_NUMBER 50217
#define TIFFTAG_OCE_IMAGELOGIC_CHARACTERISTICS 50218
-
/* tags 50674 to 50677 are reserved for ESRI */
-#define TIFFTAG_LERC_PARAMETERS \
- 50674 /* Stores LERC version and additional compression method */
+#define TIFFTAG_LERC_PARAMETERS 50674 /* Stores LERC version and additional compression method */
+
/* Adobe Digital Negative (DNG) format tags */
-#define TIFFTAG_DNGVERSION 50706 /* &DNG version number */
-#define TIFFTAG_DNGBACKWARDVERSION 50707 /* &DNG compatibility version */
-#define TIFFTAG_UNIQUECAMERAMODEL 50708 /* &name for the camera model */
-#define TIFFTAG_LOCALIZEDCAMERAMODEL \
- 50709 /* &localized camera model \
- name */
-#define TIFFTAG_CFAPLANECOLOR \
- 50710 /* &CFAPattern->LinearRaw space \
- mapping */
-#define TIFFTAG_CFALAYOUT 50711 /* &spatial layout of the CFA */
-#define TIFFTAG_LINEARIZATIONTABLE 50712 /* &lookup table description */
-#define TIFFTAG_BLACKLEVELREPEATDIM \
- 50713 /* &repeat pattern size for \
- the BlackLevel tag */
-#define TIFFTAG_BLACKLEVEL 50714 /* &zero light encoding level */
-#define TIFFTAG_BLACKLEVELDELTAH \
- 50715 /* &zero light encoding level \
- differences (columns) */
-#define TIFFTAG_BLACKLEVELDELTAV \
- 50716 /* &zero light encoding level \
- differences (rows) */
-#define TIFFTAG_WHITELEVEL \
- 50717 /* &fully saturated encoding \
- level */
-#define TIFFTAG_DEFAULTSCALE 50718 /* &default scale factors */
-#define TIFFTAG_DEFAULTCROPORIGIN \
- 50719 /* &origin of the final image \
- area */
-#define TIFFTAG_DEFAULTCROPSIZE \
- 50720 /* &size of the final image \
- area */
-#define TIFFTAG_COLORMATRIX1 \
- 50721 /* &XYZ->reference color space \
- transformation matrix 1 */
-#define TIFFTAG_COLORMATRIX2 \
- 50722 /* &XYZ->reference color space \
- transformation matrix 2 */
-#define TIFFTAG_CAMERACALIBRATION1 50723 /* &calibration matrix 1 */
-#define TIFFTAG_CAMERACALIBRATION2 50724 /* &calibration matrix 2 */
-#define TIFFTAG_REDUCTIONMATRIX1 \
- 50725 /* &dimensionality reduction \
- matrix 1 */
-#define TIFFTAG_REDUCTIONMATRIX2 \
- 50726 /* &dimensionality reduction \
- matrix 2 */
-#define TIFFTAG_ANALOGBALANCE \
- 50727 /* &gain applied the stored raw \
- values*/
-#define TIFFTAG_ASSHOTNEUTRAL \
- 50728 /* &selected white balance in \
- linear reference space */
-#define TIFFTAG_ASSHOTWHITEXY \
- 50729 /* &selected white balance in \
- x-y chromaticity \
- coordinates */
-#define TIFFTAG_BASELINEEXPOSURE \
- 50730 /* &how much to move the zero \
- point */
-#define TIFFTAG_BASELINENOISE 50731 /* &relative noise level */
-#define TIFFTAG_BASELINESHARPNESS \
- 50732 /* &relative amount of \
- sharpening */
-#define TIFFTAG_BAYERGREENSPLIT \
- 50733 /* &how closely the values of \
- the green pixels in the \
- blue/green rows track the \
- values of the green pixels \
- in the red/green rows */
-#define TIFFTAG_LINEARRESPONSELIMIT 50734 /* &non-linear encoding range */
-#define TIFFTAG_CAMERASERIALNUMBER 50735 /* &camera's serial number */
-#define TIFFTAG_LENSINFO 50736 /* info about the lens */
-#define TIFFTAG_CHROMABLURRADIUS 50737 /* &chroma blur radius */
-#define TIFFTAG_ANTIALIASSTRENGTH \
- 50738 /* &relative strength of the \
- camera's anti-alias filter */
-#define TIFFTAG_SHADOWSCALE 50739 /* &used by Adobe Camera Raw */
-#define TIFFTAG_DNGPRIVATEDATA 50740 /* &manufacturer's private data */
-#define TIFFTAG_MAKERNOTESAFETY \
- 50741 /* &whether the EXIF MakerNote \
- tag is safe to preserve \
- along with the rest of the \
- EXIF data */
-#define TIFFTAG_CALIBRATIONILLUMINANT1 50778 /* &illuminant 1 */
-#define TIFFTAG_CALIBRATIONILLUMINANT2 50779 /* &illuminant 2 */
-#define TIFFTAG_BESTQUALITYSCALE 50780 /* &best quality multiplier */
-#define TIFFTAG_RAWDATAUNIQUEID \
- 50781 /* &unique identifier for \
- the raw image data */
-#define TIFFTAG_ORIGINALRAWFILENAME \
- 50827 /* &file name of the original \
- raw file */
-#define TIFFTAG_ORIGINALRAWFILEDATA \
- 50828 /* &contents of the original \
- raw file */
-#define TIFFTAG_ACTIVEAREA \
- 50829 /* &active (non-masked) pixels \
- of the sensor */
-#define TIFFTAG_MASKEDAREAS \
- 50830 /* &list of coordinates \
- of fully masked pixels */
-#define TIFFTAG_ASSHOTICCPROFILE 50831 /* &these two tags used to */
-#define TIFFTAG_ASSHOTPREPROFILEMATRIX \
- 50832 /* map cameras's color space \
- into ICC profile space */
+#define TIFFTAG_DNGVERSION 50706 /* &DNG version number */
+#define TIFFTAG_DNGBACKWARDVERSION 50707 /* &DNG compatibility version */
+#define TIFFTAG_UNIQUECAMERAMODEL 50708 /* &name for the camera model */
+#define TIFFTAG_LOCALIZEDCAMERAMODEL 50709 /* &localized camera model name (UTF-8) */
+#define TIFFTAG_CFAPLANECOLOR 50710 /* &CFAPattern->LinearRaw space mapping */
+#define TIFFTAG_CFALAYOUT 50711 /* &spatial layout of the CFA */
+#define TIFFTAG_LINEARIZATIONTABLE 50712 /* &lookup table description */
+#define TIFFTAG_BLACKLEVELREPEATDIM 50713 /* &repeat pattern size for the BlackLevel tag */
+#define TIFFTAG_BLACKLEVEL 50714 /* &zero light encoding level */
+#define TIFFTAG_BLACKLEVELDELTAH 50715 /* &zero light encoding level differences (columns) */
+#define TIFFTAG_BLACKLEVELDELTAV 50716 /* &zero light encoding level differences (rows) */
+#define TIFFTAG_WHITELEVEL 50717 /* &fully saturated encoding level */
+#define TIFFTAG_DEFAULTSCALE 50718 /* &default scale factors */
+#define TIFFTAG_DEFAULTCROPORIGIN 50719 /* &origin of the final image area */
+#define TIFFTAG_DEFAULTCROPSIZE 50720 /* &size of the final image area */
+#define TIFFTAG_COLORMATRIX1 50721 /* &XYZ->reference color space transformation matrix 1 */
+#define TIFFTAG_COLORMATRIX2 50722 /* &XYZ->reference color space transformation matrix 2 */
+#define TIFFTAG_CAMERACALIBRATION1 50723 /* &calibration matrix 1 */
+#define TIFFTAG_CAMERACALIBRATION2 50724 /* &calibration matrix 2 */
+#define TIFFTAG_REDUCTIONMATRIX1 50725 /* &dimensionality reduction matrix 1 */
+#define TIFFTAG_REDUCTIONMATRIX2 50726 /* &dimensionality reduction matrix 2 */
+#define TIFFTAG_ANALOGBALANCE 50727 /* &gain applied the stored raw values*/
+#define TIFFTAG_ASSHOTNEUTRAL 50728 /* &selected white balance in linear reference space */
+#define TIFFTAG_ASSHOTWHITEXY 50729 /* &selected white balance in x-y chromaticity coordinates */
+#define TIFFTAG_BASELINEEXPOSURE 50730 /* &how much to move the zero point */
+#define TIFFTAG_BASELINENOISE 50731 /* &relative noise level */
+#define TIFFTAG_BASELINESHARPNESS 50732 /* &relative amount of sharpening */
+/* TIFFTAG_BAYERGREENSPLIT: &how closely the values of the green pixels in the blue/green rows
+ * track the values of the green pixels in the red/green rows */
+#define TIFFTAG_BAYERGREENSPLIT 50733
+#define TIFFTAG_LINEARRESPONSELIMIT 50734 /* &non-linear encoding range */
+#define TIFFTAG_CAMERASERIALNUMBER 50735 /* &camera's serial number */
+#define TIFFTAG_LENSINFO 50736 /* info about the lens */
+#define TIFFTAG_CHROMABLURRADIUS 50737 /* &chroma blur radius */
+#define TIFFTAG_ANTIALIASSTRENGTH 50738 /* &relative strength of the camera's anti-alias filter */
+#define TIFFTAG_SHADOWSCALE 50739 /* &used by Adobe Camera Raw */
+#define TIFFTAG_DNGPRIVATEDATA 50740 /* &manufacturer's private data */
+#define TIFFTAG_MAKERNOTESAFETY 50741 /* &whether the EXIF MakerNote tag is safe to preserve along with the rest of the EXIF data */
+#define TIFFTAG_CALIBRATIONILLUMINANT1 50778 /* &illuminant 1 */
+#define TIFFTAG_CALIBRATIONILLUMINANT2 50779 /* &illuminant 2 */
+#define TIFFTAG_BESTQUALITYSCALE 50780 /* &best quality multiplier */
+#define TIFFTAG_RAWDATAUNIQUEID 50781 /* &unique identifier for the raw image data */
+#define TIFFTAG_ORIGINALRAWFILENAME 50827 /* &file name of the original raw file (UTF-8) */
+#define TIFFTAG_ORIGINALRAWFILEDATA 50828 /* &contents of the original raw file */
+#define TIFFTAG_ACTIVEAREA 50829 /* &active (non-masked) pixels of the sensor */
+#define TIFFTAG_MASKEDAREAS 50830 /* &list of coordinates of fully masked pixels */
+#define TIFFTAG_ASSHOTICCPROFILE 50831 /* &these two tags used to */
+#define TIFFTAG_ASSHOTPREPROFILEMATRIX 50832 /* map cameras's color space into ICC profile space */
#define TIFFTAG_CURRENTICCPROFILE 50833 /* & */
#define TIFFTAG_CURRENTPREPROFILEMATRIX 50834 /* & */
-#define TIFFTAG_RPCCOEFFICIENT \
- 50844 /* Define by GDAL for geospatial georeferencing through RPC: \
- http://geotiff.maptools.org/rpc_prop.html */
+/* DNG 1.2.0.0 */
+#define TIFFTAG_COLORIMETRICREFERENCE 50879 /* &colorimetric reference */
+#define TIFFTAG_CAMERACALIBRATIONSIGNATURE 50931 /* &camera calibration signature (UTF-8) */
+#define TIFFTAG_PROFILECALIBRATIONSIGNATURE 50932 /* &profile calibration signature (UTF-8) */
+/* TIFFTAG_EXTRACAMERAPROFILES 50933 &extra camera profiles : is already defined for GeoTIFF DGIWG */
+#define TIFFTAG_ASSHOTPROFILENAME 50934 /* &as shot profile name (UTF-8) */
+#define TIFFTAG_NOISEREDUCTIONAPPLIED 50935 /* &amount of applied noise reduction */
+#define TIFFTAG_PROFILENAME 50936 /* &camera profile name (UTF-8) */
+#define TIFFTAG_PROFILEHUESATMAPDIMS 50937 /* &dimensions of HSV mapping */
+#define TIFFTAG_PROFILEHUESATMAPDATA1 50938 /* &first HSV mapping table */
+#define TIFFTAG_PROFILEHUESATMAPDATA2 50939 /* &second HSV mapping table */
+#define TIFFTAG_PROFILETONECURVE 50940 /* &default tone curve */
+#define TIFFTAG_PROFILEEMBEDPOLICY 50941 /* &profile embedding policy */
+#define TIFFTAG_PROFILECOPYRIGHT 50942 /* &profile copyright information (UTF-8) */
+#define TIFFTAG_FORWARDMATRIX1 50964 /* &matrix for mapping white balanced camera colors to XYZ D50 */
+#define TIFFTAG_FORWARDMATRIX2 50965 /* &matrix for mapping white balanced camera colors to XYZ D50 */
+#define TIFFTAG_PREVIEWAPPLICATIONNAME 50966 /* &name of application that created preview (UTF-8) */
+#define TIFFTAG_PREVIEWAPPLICATIONVERSION 50967 /* &version of application that created preview (UTF-8) */
+#define TIFFTAG_PREVIEWSETTINGSNAME 50968 /* &name of conversion settings (UTF-8) */
+#define TIFFTAG_PREVIEWSETTINGSDIGEST 50969 /* &unique id of conversion settings */
+#define TIFFTAG_PREVIEWCOLORSPACE 50970 /* &preview color space */
+#define TIFFTAG_PREVIEWDATETIME 50971 /* &date/time preview was rendered */
+#define TIFFTAG_RAWIMAGEDIGEST 50972 /* &md5 of raw image data */
+#define TIFFTAG_ORIGINALRAWFILEDIGEST 50973 /* &md5 of the data stored in the OriginalRawFileData tag */
+#define TIFFTAG_SUBTILEBLOCKSIZE 50974 /* &subtile block size */
+#define TIFFTAG_ROWINTERLEAVEFACTOR 50975 /* &number of interleaved fields */
+#define TIFFTAG_PROFILELOOKTABLEDIMS 50981 /* &num of input samples in each dim of default "look" table */
+#define TIFFTAG_PROFILELOOKTABLEDATA 50982 /* &default "look" table for use as starting point */
-#define TIFFTAG_ALIAS_LAYER_METADATA \
- 50784 /* Alias Sketchbook Pro layer usage description. */
+/* DNG 1.3.0.0 */
+#define TIFFTAG_OPCODELIST1 51008 /* &opcodes that should be applied to raw image after reading */
+#define TIFFTAG_OPCODELIST2 51009 /* &opcodes that should be applied after mapping to linear reference */
+#define TIFFTAG_OPCODELIST3 51022 /* &opcodes that should be applied after demosaicing */
+#define TIFFTAG_NOISEPROFILE 51041 /* &noise profile */
-/* GeoTIFF DGIWG */
-#define TIFFTAG_TIFF_RSID \
- 50908 /* https://www.awaresystems.be/imaging/tiff/tifftags/tiff_rsid.html \
- */
-#define TIFFTAG_GEO_METADATA \
- 50909 /* https://www.awaresystems.be/imaging/tiff/tifftags/geo_metadata.html \
- */
+/* DNG 1.4.0.0 */
+#define TIFFTAG_DEFAULTUSERCROP 51125 /* &default user crop rectangle in relative coords */
+#define TIFFTAG_DEFAULTBLACKRENDER 51110 /* &black rendering hint */
+#define TIFFTAG_BASELINEEXPOSUREOFFSET 51109 /* &baseline exposure offset */
+#define TIFFTAG_PROFILELOOKTABLEENCODING 51108 /* &3D LookTable indexing conversion */
+#define TIFFTAG_PROFILEHUESATMAPENCODING 51107 /* &3D HueSatMap indexing conversion */
+#define TIFFTAG_ORIGINALDEFAULTFINALSIZE 51089 /* &default final size of larger original file for this proxy */
+#define TIFFTAG_ORIGINALBESTQUALITYFINALSIZE 51090 /* &best quality final size of larger original file for this proxy */
+#define TIFFTAG_ORIGINALDEFAULTCROPSIZE 51091 /* &the default crop size of larger original file for this proxy */
+#define TIFFTAG_NEWRAWIMAGEDIGEST 51111 /* &modified MD5 digest of the raw image data */
+#define TIFFTAG_RAWTOPREVIEWGAIN 51112 /* &The gain between the main raw FD and the preview IFD containing this tag */
+
+/* DNG 1.5.0.0 */
+#define TIFFTAG_DEPTHFORMAT 51177 /* &encoding of the depth data in the file */
+#define TIFFTAG_DEPTHNEAR 51178 /* &distance from the camera represented by value 0 in the depth map */
+#define TIFFTAG_DEPTHFAR 51179 /* &distance from the camera represented by the maximum value in the depth map */
+#define TIFFTAG_DEPTHUNITS 51180 /* &measurement units for DepthNear and DepthFar */
+#define TIFFTAG_DEPTHMEASURETYPE 51181 /* &measurement geometry for the depth map */
+#define TIFFTAG_ENHANCEPARAMS 51182 /* &a string that documents how the enhanced image data was processed. */
+
+/* DNG 1.6.0.0 */
+#define TIFFTAG_PROFILEGAINTABLEMAP 52525 /* &spatially varying gain tables that can be applied as starting point */
+#define TIFFTAG_SEMANTICNAME 52526 /* &a string that identifies the semantic mask */
+#define TIFFTAG_SEMANTICINSTANCEID 52528 /* &a string that identifies a specific instance in a semantic mask */
+#define TIFFTAG_MASKSUBAREA 52536 /* &the crop rectangle of this IFD's mask, relative to the main image */
+#define TIFFTAG_RGBTABLES 52543 /* &color transforms to apply to masked image regions */
+#define TIFFTAG_CALIBRATIONILLUMINANT3 52529 /* &the illuminant used for the third set of color calibration tags */
+#define TIFFTAG_COLORMATRIX3 52531 /* &matrix to convert XYZ values to reference camera native color space under CalibrationIlluminant3 */
+#define TIFFTAG_CAMERACALIBRATION3 52530 /* &matrix to transform reference camera native space values to individual camera native space values under CalibrationIlluminant3 */
+#define TIFFTAG_REDUCTIONMATRIX3 52538 /* &dimensionality reduction matrix for use in color conversion to XYZ under CalibrationIlluminant3 */
+#define TIFFTAG_PROFILEHUESATMAPDATA3 52537 /* &the data for the third HSV table */
+#define TIFFTAG_FORWARDMATRIX3 52532 /* &matrix to map white balanced camera colors to XYZ D50 */
+#define TIFFTAG_ILLUMINANTDATA1 52533 /* &data for the first calibration illuminant */
+#define TIFFTAG_ILLUMINANTDATA2 52534 /* &data for the second calibration illuminant */
+#define TIFFTAG_ILLUMINANTDATA3 53535 /* &data for the third calibration illuminant */
-#define TIFFTAG_EXTRACAMERAPROFILES \
- 50933 /* http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/products/photoshop/pdfs/dng_spec_1.4.0.0.pdf \
- */
+/* TIFF/EP */
+#define TIFFTAG_EP_CFAREPEATPATTERNDIM 33421 /* dimensions of CFA pattern */
+#define TIFFTAG_EP_CFAPATTERN 33422 /* color filter array pattern */
+#define TIFFTAG_EP_BATTERYLEVEL 33423 /* battery level (rational or ASCII) */
+#define TIFFTAG_EP_INTERLACE 34857 /* Number of multi-field images */
+/* TIFFTAG_EP_IPTC_NAA and TIFFTAG_RICHTIFFIPTC share the same tag number (33723)
+ * LibTIFF type is UNDEFINED or BYTE, but often times incorrectly specified as LONG,
+ * because TIFF/EP (ISO/DIS 12234-2) specifies type LONG or ASCII. */
+#define TIFFTAG_EP_IPTC_NAA 33723 /* Alias IPTC/NAA Newspaper Association RichTIFF */
+#define TIFFTAG_EP_TIMEZONEOFFSET 34858 /* Time zone offset relative to UTC */
+#define TIFFTAG_EP_SELFTIMERMODE 34859 /* Number of seconds capture was delayed from button press */
+#define TIFFTAG_EP_FLASHENERGY 37387 /* Flash energy, or range if there is uncertainty */
+#define TIFFTAG_EP_SPATIALFREQUENCYRESPONSE 37388 /* Spatial frequency response */
+#define TIFFTAG_EP_NOISE 37389 /* Camera noise measurement values */
+#define TIFFTAG_EP_FOCALPLANEXRESOLUTION 37390 /* Focal plane X resolution */
+#define TIFFTAG_EP_FOCALPLANEYRESOLUTION 37391 /* Focal plane Y resolution */
+#define TIFFTAG_EP_FOCALPLANERESOLUTIONUNIT 37392 /* Focal plane resolution unit */
+#define TIFFTAG_EP_IMAGENUMBER 37393 /* Number of image when several of burst shot stored in same TIFF/EP */
+#define TIFFTAG_EP_SECURITYCLASSIFICATION 37394 /* Security classification */
+#define TIFFTAG_EP_IMAGEHISTORY 37395 /* Record of what has been done to the image */
+#define TIFFTAG_EP_EXPOSUREINDEX 37397 /* Exposure index */
+#define TIFFTAG_EP_STANDARDID 37398 /* TIFF/EP standard version, n.n.n.n */
+#define TIFFTAG_EP_SENSINGMETHOD 37399 /* Type of image sensor */
+/*
+ * TIFF/EP tags equivalent to EXIF tags
+ * Note that TIFF-EP and EXIF use nearly the same metadata tag set, but TIFF-EP stores the tags in IFD 0,
+ * while EXIF store the tags in a separate IFD. Either location is allowed by DNG, but the EXIF location is preferred.
+ */
+#define TIFFTAG_EP_EXPOSURETIME 33434 /* Exposure time */
+#define TIFFTAG_EP_FNUMBER 33437 /* F number */
+#define TIFFTAG_EP_EXPOSUREPROGRAM 34850 /* Exposure program */
+#define TIFFTAG_EP_SPECTRALSENSITIVITY 34852 /* Spectral sensitivity */
+#define TIFFTAG_EP_ISOSPEEDRATINGS 34855 /* ISO speed rating */
+#define TIFFTAG_EP_OECF 34856 /* Optoelectric conversion factor */
+#define TIFFTAG_EP_DATETIMEORIGINAL 36867 /* Date and time of original data generation */
+#define TIFFTAG_EP_COMPRESSEDBITSPERPIXEL 37122 /* Image compression mode */
+#define TIFFTAG_EP_SHUTTERSPEEDVALUE 37377 /* Shutter speed */
+#define TIFFTAG_EP_APERTUREVALUE 37378 /* Aperture */
+#define TIFFTAG_EP_BRIGHTNESSVALUE 37379 /* Brightness */
+#define TIFFTAG_EP_EXPOSUREBIASVALUE 37380 /* Exposure bias */
+#define TIFFTAG_EP_MAXAPERTUREVALUE 37381 /* Maximum lens aperture */
+#define TIFFTAG_EP_SUBJECTDISTANCE 37382 /* Subject distance */
+#define TIFFTAG_EP_METERINGMODE 37383 /* Metering mode */
+#define TIFFTAG_EP_LIGHTSOURCE 37384 /* Light source */
+#define TIFFTAG_EP_FLASH 37385 /* Flash */
+#define TIFFTAG_EP_FOCALLENGTH 37386 /* Lens focal length */
+#define TIFFTAG_EP_SUBJECTLOCATION 37396 /* Subject location (area) */
+
+#define TIFFTAG_RPCCOEFFICIENT 50844 /* Define by GDAL for geospatial georeferencing through RPC: http://geotiff.maptools.org/rpc_prop.html */
+#define TIFFTAG_ALIAS_LAYER_METADATA 50784 /* Alias Sketchbook Pro layer usage description. */
+
+/* GeoTIFF DGIWG */
+#define TIFFTAG_TIFF_RSID 50908 /* https://www.awaresystems.be/imaging/tiff/tifftags/tiff_rsid.html */
+#define TIFFTAG_GEO_METADATA 50909 /* https://www.awaresystems.be/imaging/tiff/tifftags/geo_metadata.html */
+#define TIFFTAG_EXTRACAMERAPROFILES 50933 /* http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/products/photoshop/pdfs/dng_spec_1.4.0.0.pdf */
/* tag 65535 is an undefined tag used by Eastman Kodak */
#define TIFFTAG_DCSHUESHIFTVALUES 65535 /* hue shift correction data */
@@ -751,220 +758,141 @@ typedef enum
#define LERC_ADD_COMPRESSION_NONE 0
#define LERC_ADD_COMPRESSION_DEFLATE 1
#define LERC_ADD_COMPRESSION_ZSTD 2
-#define TIFFTAG_LERC_MAXZERROR 65567 /* LERC maximum error */
-#define TIFFTAG_WEBP_LEVEL 65568 /* WebP compression level */
-#define TIFFTAG_WEBP_LOSSLESS 65569 /* WebP lossless/lossy */
-#define TIFFTAG_DEFLATE_SUBCODEC \
- 65570 /* ZIP codec: to get/set the sub-codec to use. Will default to \
- libdeflate when available */
+#define TIFFTAG_LERC_MAXZERROR 65567 /* LERC maximum error */
+#define TIFFTAG_WEBP_LEVEL 65568 /* WebP compression level */
+#define TIFFTAG_WEBP_LOSSLESS 65569 /* WebP lossless/lossy */
+#define TIFFTAG_DEFLATE_SUBCODEC 65570 /* ZIP codec: to get/set the sub-codec to use. Will default to libdeflate when available */
#define DEFLATE_SUBCODEC_ZLIB 0
#define DEFLATE_SUBCODEC_LIBDEFLATE 1
/*
* EXIF tags
*/
-#define EXIFTAG_EXPOSURETIME 33434 /* Exposure time */
-#define EXIFTAG_FNUMBER 33437 /* F number */
-#define EXIFTAG_EXPOSUREPROGRAM 34850 /* Exposure program */
-#define EXIFTAG_SPECTRALSENSITIVITY 34852 /* Spectral sensitivity */
-#define EXIFTAG_ISOSPEEDRATINGS 34855 /* ISO speed rating */
-#define EXIFTAG_PHOTOGRAPHICSENSITIVITY \
- 34855 /* Photographic Sensitivity (new name for tag 34855) */
-#define EXIFTAG_OECF 34856 /* Optoelectric conversion factor */
-#define EXIFTAG_EXIFVERSION 36864 /* Exif version */
-#define EXIFTAG_DATETIMEORIGINAL \
- 36867 /* Date and time of original \
- data generation */
-#define EXIFTAG_DATETIMEDIGITIZED \
- 36868 /* Date and time of digital \
- data generation */
-#define EXIFTAG_COMPONENTSCONFIGURATION 37121 /* Meaning of each component */
-#define EXIFTAG_COMPRESSEDBITSPERPIXEL 37122 /* Image compression mode */
-#define EXIFTAG_SHUTTERSPEEDVALUE 37377 /* Shutter speed */
-#define EXIFTAG_APERTUREVALUE 37378 /* Aperture */
-#define EXIFTAG_BRIGHTNESSVALUE 37379 /* Brightness */
-#define EXIFTAG_EXPOSUREBIASVALUE 37380 /* Exposure bias */
-#define EXIFTAG_MAXAPERTUREVALUE 37381 /* Maximum lens aperture */
-#define EXIFTAG_SUBJECTDISTANCE 37382 /* Subject distance */
-#define EXIFTAG_METERINGMODE 37383 /* Metering mode */
-#define EXIFTAG_LIGHTSOURCE 37384 /* Light source */
-#define EXIFTAG_FLASH 37385 /* Flash */
-#define EXIFTAG_FOCALLENGTH 37386 /* Lens focal length */
-#define EXIFTAG_SUBJECTAREA 37396 /* Subject area */
-#define EXIFTAG_MAKERNOTE 37500 /* Manufacturer notes */
-#define EXIFTAG_USERCOMMENT 37510 /* User comments */
-#define EXIFTAG_SUBSECTIME 37520 /* DateTime subseconds */
-#define EXIFTAG_SUBSECTIMEORIGINAL 37521 /* DateTimeOriginal subseconds */
-#define EXIFTAG_SUBSECTIMEDIGITIZED 37522 /* DateTimeDigitized subseconds */
-#define EXIFTAG_FLASHPIXVERSION 40960 /* Supported Flashpix version */
-#define EXIFTAG_COLORSPACE 40961 /* Color space information */
-#define EXIFTAG_PIXELXDIMENSION 40962 /* Valid image width */
-#define EXIFTAG_PIXELYDIMENSION 40963 /* Valid image height */
-#define EXIFTAG_RELATEDSOUNDFILE 40964 /* Related audio file */
-#define EXIFTAG_FLASHENERGY 41483 /* Flash energy */
-#define EXIFTAG_SPATIALFREQUENCYRESPONSE \
- 41484 /* Spatial frequency response \
- */
-#define EXIFTAG_FOCALPLANEXRESOLUTION 41486 /* Focal plane X resolution */
-#define EXIFTAG_FOCALPLANEYRESOLUTION 41487 /* Focal plane Y resolution */
-#define EXIFTAG_FOCALPLANERESOLUTIONUNIT \
- 41488 /* Focal plane resolution unit \
- */
-#define EXIFTAG_SUBJECTLOCATION 41492 /* Subject location */
-#define EXIFTAG_EXPOSUREINDEX 41493 /* Exposure index */
-#define EXIFTAG_SENSINGMETHOD 41495 /* Sensing method */
-#define EXIFTAG_FILESOURCE 41728 /* File source */
-#define EXIFTAG_SCENETYPE 41729 /* Scene type */
-#define EXIFTAG_CFAPATTERN 41730 /* CFA pattern */
-#define EXIFTAG_CUSTOMRENDERED 41985 /* Custom image processing */
-#define EXIFTAG_EXPOSUREMODE 41986 /* Exposure mode */
-#define EXIFTAG_WHITEBALANCE 41987 /* White balance */
-#define EXIFTAG_DIGITALZOOMRATIO 41988 /* Digital zoom ratio */
-#define EXIFTAG_FOCALLENGTHIN35MMFILM 41989 /* Focal length in 35 mm film */
-#define EXIFTAG_SCENECAPTURETYPE 41990 /* Scene capture type */
-#define EXIFTAG_GAINCONTROL 41991 /* Gain control */
-#define EXIFTAG_CONTRAST 41992 /* Contrast */
-#define EXIFTAG_SATURATION 41993 /* Saturation */
-#define EXIFTAG_SHARPNESS 41994 /* Sharpness */
-#define EXIFTAG_DEVICESETTINGDESCRIPTION \
- 41995 /* Device settings description \
- */
-#define EXIFTAG_SUBJECTDISTANCERANGE 41996 /* Subject distance range */
-#define EXIFTAG_IMAGEUNIQUEID 42016 /* Unique image ID */
+#define EXIFTAG_EXPOSURETIME 33434 /* Exposure time */
+#define EXIFTAG_FNUMBER 33437 /* F number */
+#define EXIFTAG_EXPOSUREPROGRAM 34850 /* Exposure program */
+#define EXIFTAG_SPECTRALSENSITIVITY 34852 /* Spectral sensitivity */
+/* After EXIF 2.2.1 ISOSpeedRatings is named PhotographicSensitivity.
+ In addition, while "Count=Any", only 1 count should be used. */
+#define EXIFTAG_ISOSPEEDRATINGS 34855 /* ISO speed rating */
+#define EXIFTAG_PHOTOGRAPHICSENSITIVITY 34855 /* Photographic Sensitivity (new name for tag 34855) */
+#define EXIFTAG_OECF 34856 /* Optoelectric conversion factor */
+#define EXIFTAG_EXIFVERSION 36864 /* Exif version */
+#define EXIFTAG_DATETIMEORIGINAL 36867 /* Date and time of original data generation */
+#define EXIFTAG_DATETIMEDIGITIZED 36868 /* Date and time of digital data generation */
+#define EXIFTAG_COMPONENTSCONFIGURATION 37121 /* Meaning of each component */
+#define EXIFTAG_COMPRESSEDBITSPERPIXEL 37122 /* Image compression mode */
+#define EXIFTAG_SHUTTERSPEEDVALUE 37377 /* Shutter speed */
+#define EXIFTAG_APERTUREVALUE 37378 /* Aperture */
+#define EXIFTAG_BRIGHTNESSVALUE 37379 /* Brightness */
+#define EXIFTAG_EXPOSUREBIASVALUE 37380 /* Exposure bias */
+#define EXIFTAG_MAXAPERTUREVALUE 37381 /* Maximum lens aperture */
+#define EXIFTAG_SUBJECTDISTANCE 37382 /* Subject distance */
+#define EXIFTAG_METERINGMODE 37383 /* Metering mode */
+#define EXIFTAG_LIGHTSOURCE 37384 /* Light source */
+#define EXIFTAG_FLASH 37385 /* Flash */
+#define EXIFTAG_FOCALLENGTH 37386 /* Lens focal length */
+#define EXIFTAG_SUBJECTAREA 37396 /* Subject area */
+#define EXIFTAG_MAKERNOTE 37500 /* Manufacturer notes */
+#define EXIFTAG_USERCOMMENT 37510 /* User comments */
+#define EXIFTAG_SUBSECTIME 37520 /* DateTime subseconds */
+#define EXIFTAG_SUBSECTIMEORIGINAL 37521 /* DateTimeOriginal subseconds */
+#define EXIFTAG_SUBSECTIMEDIGITIZED 37522 /* DateTimeDigitized subseconds */
+#define EXIFTAG_FLASHPIXVERSION 40960 /* Supported Flashpix version */
+#define EXIFTAG_COLORSPACE 40961 /* Color space information */
+#define EXIFTAG_PIXELXDIMENSION 40962 /* Valid image width */
+#define EXIFTAG_PIXELYDIMENSION 40963 /* Valid image height */
+#define EXIFTAG_RELATEDSOUNDFILE 40964 /* Related audio file */
+#define EXIFTAG_FLASHENERGY 41483 /* Flash energy */
+#define EXIFTAG_SPATIALFREQUENCYRESPONSE 41484 /* Spatial frequency response */
+#define EXIFTAG_FOCALPLANEXRESOLUTION 41486 /* Focal plane X resolution */
+#define EXIFTAG_FOCALPLANEYRESOLUTION 41487 /* Focal plane Y resolution */
+#define EXIFTAG_FOCALPLANERESOLUTIONUNIT 41488 /* Focal plane resolution unit */
+#define EXIFTAG_SUBJECTLOCATION 41492 /* Subject location */
+#define EXIFTAG_EXPOSUREINDEX 41493 /* Exposure index */
+#define EXIFTAG_SENSINGMETHOD 41495 /* Sensing method */
+#define EXIFTAG_FILESOURCE 41728 /* File source */
+#define EXIFTAG_SCENETYPE 41729 /* Scene type */
+#define EXIFTAG_CFAPATTERN 41730 /* CFA pattern */
+#define EXIFTAG_CUSTOMRENDERED 41985 /* Custom image processing */
+#define EXIFTAG_EXPOSUREMODE 41986 /* Exposure mode */
+#define EXIFTAG_WHITEBALANCE 41987 /* White balance */
+#define EXIFTAG_DIGITALZOOMRATIO 41988 /* Digital zoom ratio */
+#define EXIFTAG_FOCALLENGTHIN35MMFILM 41989 /* Focal length in 35 mm film */
+#define EXIFTAG_SCENECAPTURETYPE 41990 /* Scene capture type */
+#define EXIFTAG_GAINCONTROL 41991 /* Gain control */
+#define EXIFTAG_CONTRAST 41992 /* Contrast */
+#define EXIFTAG_SATURATION 41993 /* Saturation */
+#define EXIFTAG_SHARPNESS 41994 /* Sharpness */
+#define EXIFTAG_DEVICESETTINGDESCRIPTION 41995 /* Device settings description */
+#define EXIFTAG_SUBJECTDISTANCERANGE 41996 /* Subject distance range */
+#define EXIFTAG_IMAGEUNIQUEID 42016 /* Unique image ID */
/*--: New for EXIF-Version 2.32, May 2019 ... */
-#define EXIFTAG_SENSITIVITYTYPE \
- 34864 /* The SensitivityType tag indicates which one of the parameters of \
- ISO12232 is the PhotographicSensitivity tag. */
-#define EXIFTAG_STANDARDOUTPUTSENSITIVITY \
- 34865 /* This tag indicates the standard output sensitivity value of a \
- camera or input device defined in ISO 12232. */
-#define EXIFTAG_RECOMMENDEDEXPOSUREINDEX \
- 34866 /* recommended exposure index \
- */
-#define EXIFTAG_ISOSPEED 34867 /* ISO speed value */
-#define EXIFTAG_ISOSPEEDLATITUDEYYY 34868 /* ISO speed latitude yyy */
-#define EXIFTAG_ISOSPEEDLATITUDEZZZ 34869 /* ISO speed latitude zzz */
-#define EXIFTAG_OFFSETTIME \
- 36880 /* offset from UTC of the time of DateTime tag. */
-#define EXIFTAG_OFFSETTIMEORIGINAL \
- 36881 /* offset from UTC of the time of DateTimeOriginal tag. */
-#define EXIFTAG_OFFSETTIMEDIGITIZED \
- 36882 /* offset from UTC of the time of DateTimeDigitized tag. */
-#define EXIFTAG_TEMPERATURE \
- 37888 /* Temperature as the ambient situation at the shot in dergee \
- Celsius */
-#define EXIFTAG_HUMIDITY \
- 37889 /* Humidity as the ambient situation at the shot in percent */
-#define EXIFTAG_PRESSURE \
- 37890 /* Pressure as the ambient situation at the shot hecto-Pascal (hPa) \
- */
-#define EXIFTAG_WATERDEPTH \
- 37891 /* WaterDepth as the ambient situation at the shot in meter (m) */
-#define EXIFTAG_ACCELERATION \
- 37892 /* Acceleration (a scalar regardless of direction) as the ambient \
- situation at the shot in units of mGal (10-5 m/s^2) */
-#define EXIFTAG_CAMERAELEVATIONANGLE \
- 37893 /* Elevation/depression. angle of the orientation of the \
- camera(imaging optical axis) as the ambient situation at the shot \
- in degree from -180deg to +180deg. */
-#define EXIFTAG_CAMERAOWNERNAME 42032 /* owner of a camera */
-#define EXIFTAG_BODYSERIALNUMBER \
- 42033 /* serial number of the body of the camera */
-#define EXIFTAG_LENSSPECIFICATION \
- 42034 /* minimum focal length (in mm), maximum focal length (in mm), \
- minimum F number in the minimum focal length, and minimum F \
- number in the maximum focal length, */
-#define EXIFTAG_LENSMAKE 42035 /* the lens manufacturer */
-#define EXIFTAG_LENSMODEL 42036 /* the lens model name and model number */
-#define EXIFTAG_LENSSERIALNUMBER \
- 42037 /* the serial number of the interchangeable lens */
-#define EXIFTAG_GAMMA 42240 /* value of coefficient gamma */
-#define EXIFTAG_COMPOSITEIMAGE 42080 /* composite image */
-#define EXIFTAG_SOURCEIMAGENUMBEROFCOMPOSITEIMAGE \
- 42081 /* source image number of composite image */
-#define EXIFTAG_SOURCEEXPOSURETIMESOFCOMPOSITEIMAGE \
- 42082 /* source exposure times of composite image */
+#define EXIFTAG_SENSITIVITYTYPE 34864 /* The SensitivityType tag indicates which one of the parameters of ISO12232 is the PhotographicSensitivity tag. */
+#define EXIFTAG_STANDARDOUTPUTSENSITIVITY 34865 /* This tag indicates the standard output sensitivity value of a camera or input device defined in ISO 12232. */
+#define EXIFTAG_RECOMMENDEDEXPOSUREINDEX 34866 /* recommended exposure index */
+#define EXIFTAG_ISOSPEED 34867 /* ISO speed value */
+#define EXIFTAG_ISOSPEEDLATITUDEYYY 34868 /* ISO speed latitude yyy */
+#define EXIFTAG_ISOSPEEDLATITUDEZZZ 34869 /* ISO speed latitude zzz */
+#define EXIFTAG_OFFSETTIME 36880 /* offset from UTC of the time of DateTime tag. */
+#define EXIFTAG_OFFSETTIMEORIGINAL 36881 /* offset from UTC of the time of DateTimeOriginal tag. */
+#define EXIFTAG_OFFSETTIMEDIGITIZED 36882 /* offset from UTC of the time of DateTimeDigitized tag. */
+#define EXIFTAG_TEMPERATURE 37888 /* Temperature as the ambient situation at the shot in dergee Celsius */
+#define EXIFTAG_HUMIDITY 37889 /* Humidity as the ambient situation at the shot in percent */
+#define EXIFTAG_PRESSURE 37890 /* Pressure as the ambient situation at the shot hecto-Pascal (hPa) */
+#define EXIFTAG_WATERDEPTH 37891 /* WaterDepth as the ambient situation at the shot in meter (m) */
+#define EXIFTAG_ACCELERATION 37892 /* Acceleration (a scalar regardless of direction) as the ambientsituation at the shot in units of mGal (10-5 m/s^2) */
+/* EXIFTAG_CAMERAELEVATIONANGLE: Elevation/depression. angle of the orientation of the camera(imaging optical axis)
+ * as the ambient situation at the shot in degree from -180deg to +180deg. */
+#define EXIFTAG_CAMERAELEVATIONANGLE 37893
+#define EXIFTAG_CAMERAOWNERNAME 42032 /* owner of a camera */
+#define EXIFTAG_BODYSERIALNUMBER 42033 /* serial number of the body of the camera */
+/* EXIFTAG_LENSSPECIFICATION: minimum focal length (in mm), maximum focal length (in mm),minimum F number in the minimum focal length,
+ * and minimum F number in the maximum focal length, */
+#define EXIFTAG_LENSSPECIFICATION 42034
+#define EXIFTAG_LENSMAKE 42035 /* the lens manufacturer */
+#define EXIFTAG_LENSMODEL 42036 /* the lens model name and model number */
+#define EXIFTAG_LENSSERIALNUMBER 42037 /* the serial number of the interchangeable lens */
+#define EXIFTAG_GAMMA 42240 /* value of coefficient gamma */
+#define EXIFTAG_COMPOSITEIMAGE 42080 /* composite image */
+#define EXIFTAG_SOURCEIMAGENUMBEROFCOMPOSITEIMAGE 42081 /* source image number of composite image */
+#define EXIFTAG_SOURCEEXPOSURETIMESOFCOMPOSITEIMAGE 42082 /* source exposure times of composite image */
/*
* EXIF-GPS tags (Version 2.31, July 2016)
*/
-#define GPSTAG_VERSIONID 0 /* Indicates the version of GPSInfoIFD. */
-#define GPSTAG_LATITUDEREF \
- 1 /* Indicates whether the latitude is north or south latitude. \
- */
-#define GPSTAG_LATITUDE 2 /* Indicates the latitude. */
-#define GPSTAG_LONGITUDEREF \
- 3 /* Indicates whether the longitude is east or west longitude. \
- */
-#define GPSTAG_LONGITUDE 4 /* Indicates the longitude. */
-#define GPSTAG_ALTITUDEREF \
- 5 /* Indicates the altitude used as the reference altitude. */
-#define GPSTAG_ALTITUDE \
- 6 /* Indicates the altitude based on the reference in \
- GPSAltitudeRef. */
-#define GPSTAG_TIMESTAMP \
- 7 /* Indicates the time as UTC (Coordinated Universal Time). */
-#define GPSTAG_SATELLITES \
- 8 /* Indicates the GPS satellites used for measurements. */
-#define GPSTAG_STATUS \
- 9 /* Indicates the status of the GPS receiver when the image is \
- recorded. */
-#define GPSTAG_MEASUREMODE \
- 10 /* Indicates the GPS measurement mode. */
-#define GPSTAG_DOP \
- 11 /* Indicates the GPS DOP (data degree of precision). */
-#define GPSTAG_SPEEDREF \
- 12 /* Indicates the unit used to express the GPS receiver speed of \
- movement. */
-#define GPSTAG_SPEED \
- 13 /* Indicates the speed of GPS receiver movement. */
-#define GPSTAG_TRACKREF \
- 14 /* Indicates the reference for giving the direction of GPS \
- receiver movement. */
-#define GPSTAG_TRACK \
- 15 /* Indicates the direction of GPS receiver movement. */
-#define GPSTAG_IMGDIRECTIONREF \
- 16 /* Indicates the reference for giving the direction of the image \
- when it is captured. */
-#define GPSTAG_IMGDIRECTION \
- 17 /* Indicates the direction of the image when it was captured. \
- */
-#define GPSTAG_MAPDATUM \
- 18 /* Indicates the geodetic survey data used by the GPS receiver. \
- (e.g. WGS-84) */
-#define GPSTAG_DESTLATITUDEREF \
- 19 /* Indicates whether the latitude of the destination point is \
- north or south latitude. */
-#define GPSTAG_DESTLATITUDE \
- 20 /* Indicates the latitude of the destination point. */
-#define GPSTAG_DESTLONGITUDEREF \
- 21 /* Indicates whether the longitude of the destination point is \
- east or west longitude. */
-#define GPSTAG_DESTLONGITUDE \
- 22 /* Indicates the longitude of the destination point. */
-#define GPSTAG_DESTBEARINGREF \
- 23 /* Indicates the reference used for giving the bearing to the \
- destination point. */
-#define GPSTAG_DESTBEARING \
- 24 /* Indicates the bearing to the destination point. */
-#define GPSTAG_DESTDISTANCEREF \
- 25 /* Indicates the unit used to express the distance to the \
- destination point. */
-#define GPSTAG_DESTDISTANCE \
- 26 /* Indicates the distance to the destination point. */
-#define GPSTAG_PROCESSINGMETHOD \
- 27 /* A character string recording the name of the method used for \
- location finding. */
-#define GPSTAG_AREAINFORMATION \
- 28 /* A character string recording the name of the GPS area. */
-#define GPSTAG_DATESTAMP \
- 29 /* A character string recording date and time information \
- relative to UTC (Coordinated Universal Time). */
-#define GPSTAG_DIFFERENTIAL \
- 30 /* Indicates whether differential correction is applied to the \
- GPS receiver. */
-#define GPSTAG_GPSHPOSITIONINGERROR \
- 31 /* Indicates horizontal positioning errors in meters. */
+#define GPSTAG_VERSIONID 0 /* Indicates the version of GPSInfoIFD. */
+#define GPSTAG_LATITUDEREF 1 /* Indicates whether the latitude is north or south latitude. */
+#define GPSTAG_LATITUDE 2 /* Indicates the latitude. */
+#define GPSTAG_LONGITUDEREF 3 /* Indicates whether the longitude is east or west longitude. */
+#define GPSTAG_LONGITUDE 4 /* Indicates the longitude. */
+#define GPSTAG_ALTITUDEREF 5 /* Indicates the altitude used as the reference altitude. */
+#define GPSTAG_ALTITUDE 6 /* Indicates the altitude based on the reference in GPSAltitudeRef. */
+#define GPSTAG_TIMESTAMP 7 /*Indicates the time as UTC (Coordinated Universal Time). */
+#define GPSTAG_SATELLITES 8 /*Indicates the GPS satellites used for measurements. */
+#define GPSTAG_STATUS 9 /* Indicates the status of the GPS receiver when the image is recorded. */
+#define GPSTAG_MEASUREMODE 10 /* Indicates the GPS measurement mode. */
+#define GPSTAG_DOP 11 /* Indicates the GPS DOP (data degree of precision). */
+#define GPSTAG_SPEEDREF 12 /* Indicates the unit used to express the GPS receiver speed of movement. */
+#define GPSTAG_SPEED 13 /* Indicates the speed of GPS receiver movement. */
+#define GPSTAG_TRACKREF 14 /* Indicates the reference for giving the direction of GPS receiver movement. */
+#define GPSTAG_TRACK 15 /* Indicates the direction of GPS receiver movement. */
+#define GPSTAG_IMGDIRECTIONREF 16 /* Indicates the reference for giving the direction of the image when it is captured. */
+#define GPSTAG_IMGDIRECTION 17 /* Indicates the direction of the image when it was captured. */
+#define GPSTAG_MAPDATUM 18 /* Indicates the geodetic survey data used by the GPS receiver. (e.g. WGS-84) */
+#define GPSTAG_DESTLATITUDEREF 19 /* Indicates whether the latitude of the destination point is north or south latitude. */
+#define GPSTAG_DESTLATITUDE 20 /* Indicates the latitude of the destination point. */
+#define GPSTAG_DESTLONGITUDEREF 21 /* Indicates whether the longitude of the destination point is east or west longitude. */
+#define GPSTAG_DESTLONGITUDE 22 /* Indicates the longitude of the destination point. */
+#define GPSTAG_DESTBEARINGREF 23 /* Indicates the reference used for giving the bearing to the destination point. */
+#define GPSTAG_DESTBEARING 24 /* Indicates the bearing to the destination point. */
+#define GPSTAG_DESTDISTANCEREF 25 /* Indicates the unit used to express the distance to the destination point. */
+#define GPSTAG_DESTDISTANCE 26 /* Indicates the distance to the destination point. */
+#define GPSTAG_PROCESSINGMETHOD 27 /* A character string recording the name of the method used for location finding. */
+#define GPSTAG_AREAINFORMATION 28 /* A character string recording the name of the GPS area. */
+#define GPSTAG_DATESTAMP 29 /* A character string recording date and time information relative to UTC (Coordinated Universal Time). */
+#define GPSTAG_DIFFERENTIAL 30 /* Indicates whether differential correction is applied to the GPS receiver. */
+#define GPSTAG_GPSHPOSITIONINGERROR 31 /* Indicates horizontal positioning errors in meters. */
#endif /* _TIFF_ */
diff --git a/third_party/libtiff/tiffio.h b/third_party/libtiff/tiffio.h
index 4df57665f..d6bf0cc54 100644
--- a/third_party/libtiff/tiffio.h
+++ b/third_party/libtiff/tiffio.h
@@ -263,6 +263,12 @@ typedef struct
TIFFInitMethod init;
} TIFFCodec;
+typedef struct
+{
+ uint32_t uNum;
+ uint32_t uDenom;
+} TIFFRational_t;
+
#include <stdarg.h>
#include <stdio.h>
diff --git a/third_party/libtiff/tiffiop.h b/third_party/libtiff/tiffiop.h
index d3ba287af..a7cc12b81 100644
--- a/third_party/libtiff/tiffiop.h
+++ b/third_party/libtiff/tiffiop.h
@@ -143,15 +143,14 @@ struct tiff
#define TIFF_CHOPPEDUPARRAYS \
0x4000000U /* set when allocChoppedUpStripArrays() has modified strip \
array */
- uint64_t tif_diroff; /* file offset of current directory */
- uint64_t tif_nextdiroff; /* file offset of following directory */
- uint64_t tif_lastdiroff; /* file offset of last directory written so far */
- uint64_t *tif_dirlistoff; /* list of offsets to already seen directories to
- prevent IFD looping */
+ uint64_t tif_diroff; /* file offset of current directory */
+ uint64_t tif_nextdiroff; /* file offset of following directory */
+ uint64_t tif_lastdiroff; /* file offset of last directory written so far */
TIFFHashSet *tif_map_dir_offset_to_number;
TIFFHashSet *tif_map_dir_number_to_offset;
- tdir_t tif_dirnumber; /* number of already seen directories */
- TIFFDirectory tif_dir; /* internal rep of current directory */
+ int tif_setdirectory_force_absolute; /* switch between relative and absolute
+ stepping in TIFFSetDirectory() */
+ TIFFDirectory tif_dir; /* internal rep of current directory */
TIFFDirectory
tif_customdir; /* custom IFDs are separated from the main ones */
union
@@ -444,6 +443,8 @@ extern "C"
extern float _TIFFClampDoubleToFloat(double);
extern uint32_t _TIFFClampDoubleToUInt32(double);
+ extern void _TIFFCleanupIFDOffsetAndNumberMaps(TIFF *tif);
+
extern tmsize_t _TIFFReadEncodedStripAndAllocBuffer(TIFF *tif,
uint32_t strip,
void **buf,
diff --git a/third_party/libtiff/tiffvers.h b/third_party/libtiff/tiffvers.h
index 552e88576..ed847760c 100644
--- a/third_party/libtiff/tiffvers.h
+++ b/third_party/libtiff/tiffvers.h
@@ -3,7 +3,7 @@
/* clang-format disabled because FindTIFF.cmake is very sensitive to the
* formatting of below line being a single line.
*/
-#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.5.0\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
+#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.5.1\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
@@ -11,12 +11,12 @@
* version checking should be done based on the
* string returned by TIFFGetVersion.
*/
-#define TIFFLIB_VERSION 20221213
+#define TIFFLIB_VERSION 20230609
/* The following defines have been added in 4.5.0 */
#define TIFFLIB_MAJOR_VERSION 4
#define TIFFLIB_MINOR_VERSION 5
-#define TIFFLIB_MICRO_VERSION 0
+#define TIFFLIB_MICRO_VERSION 1
/* Macro added in 4.5.0. Returns TRUE if the current libtiff version is
* greater or equal to major.minor.micro
diff --git a/third_party/ninja/README.pdfium b/third_party/ninja/README.pdfium
index e79bd45f2..8a5f1eeba 100644
--- a/third_party/ninja/README.pdfium
+++ b/third_party/ninja/README.pdfium
@@ -5,6 +5,7 @@ Revision: See the CIPD version in DEPS
License: Apache License 2.0
License File: https://github.com/ninja-build/ninja/blob/master/COPYING
Security Critical: no
+Shipped: no
Description:
Ninja is a small build system with a focus on speed, and is used to build
diff --git a/third_party/pymock/README.chromium b/third_party/pymock/README.chromium
index 255c2bfeb..e49f239b2 100644
--- a/third_party/pymock/README.chromium
+++ b/third_party/pymock/README.chromium
@@ -2,8 +2,10 @@ Name: mock
URL: http://pypi.python.org/pypi/mock
Version: 1.0.1
Security Critical: no
+Shipped: no
License: BSD
-License File: NOT_SHIPPED
+License File: LICENSE.txt
+
Description:
Python mock library, currently used by native_client_sdk. This is the
same mock library that is now part of python 3.3 where it is know as
diff --git a/third_party/skia_shared/SkFloatToDecimal.cpp b/third_party/skia_shared/SkFloatToDecimal.cpp
deleted file mode 100644
index 90d4be37e..000000000
--- a/third_party/skia_shared/SkFloatToDecimal.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkFloatToDecimal.h"
-
-#include <cassert>
-#include <cfloat>
-#include <climits>
-#include <cmath>
-
-namespace pdfium {
-namespace skia {
-namespace {
-
-// Return pow(10.0, e), optimized for common cases.
-double pow10(int e) {
- switch (e) {
- case 0: return 1.0; // common cases
- case 1: return 10.0;
- case 2: return 100.0;
- case 3: return 1e+03;
- case 4: return 1e+04;
- case 5: return 1e+05;
- case 6: return 1e+06;
- case 7: return 1e+07;
- case 8: return 1e+08;
- case 9: return 1e+09;
- case 10: return 1e+10;
- case 11: return 1e+11;
- case 12: return 1e+12;
- case 13: return 1e+13;
- case 14: return 1e+14;
- case 15: return 1e+15;
- default:
- if (e > 15) {
- double value = 1e+15;
- while (e-- > 15) { value *= 10.0; }
- return value;
- } else {
- assert(e < 0);
- double value = 1.0;
- while (e++ < 0) {
- value /= 10.0;
- }
- return value;
- }
- }
-}
-
-} // namespace
-
-/** Write a string into output, including a terminating '\0' (for
- unit testing). Return strlen(output) (for SkWStream::write) The
- resulting string will be in the form /[-]?([0-9]*.)?[0-9]+/ and
- sscanf(output, "%f", &x) will return the original value iff the
- value is finite. This function accepts all possible input values.
-
- Motivation: "PDF does not support [numbers] in exponential format
- (such as 6.02e23)." Otherwise, this function would rely on a
- sprintf-type function from the standard library. */
-unsigned SkFloatToDecimal(float value, char output[kMaximumSkFloatToDecimalLength]) {
- /* The longest result is -FLT_MIN.
- We serialize it as "-.0000000000000000000000000000000000000117549435"
- which has 48 characters plus a terminating '\0'. */
-
- static_assert(kMaximumSkFloatToDecimalLength == 49, "");
- // 3 = '-', '.', and '\0' characters.
- // 9 = number of significant digits
- // abs(FLT_MIN_10_EXP) = number of zeros in FLT_MIN
- static_assert(kMaximumSkFloatToDecimalLength == 3 + 9 - FLT_MIN_10_EXP, "");
-
- /* section C.1 of the PDF1.4 spec (http://goo.gl/0SCswJ) says that
- most PDF rasterizers will use fixed-point scalars that lack the
- dynamic range of floats. Even if this is the case, I want to
- serialize these (uncommon) very small and very large scalar
- values with enough precision to allow a floating-point
- rasterizer to read them in with perfect accuracy.
- Experimentally, rasterizers such as pdfium do seem to benefit
- from this. Rasterizers that rely on fixed-point scalars should
- gracefully ignore these values that they can not parse. */
- char* output_ptr = &output[0];
- const char* const end = &output[kMaximumSkFloatToDecimalLength - 1];
- // subtract one to leave space for '\0'.
-
- /* This function is written to accept any possible input value,
- including non-finite values such as INF and NAN. In that case,
- we ignore value-correctness and output a syntacticly-valid
- number. */
- if (value == INFINITY) {
- value = FLT_MAX; // nearest finite float.
- }
- if (value == -INFINITY) {
- value = -FLT_MAX; // nearest finite float.
- }
- if (!std::isfinite(value) || value == 0.0f) {
- // NAN is unsupported in PDF. Always output a valid number.
- // Also catch zero here, as a special case.
- *output_ptr++ = '0';
- *output_ptr = '\0';
- return static_cast<unsigned>(output_ptr - output);
- }
- if (value < 0.0) {
- *output_ptr++ = '-';
- value = -value;
- }
- assert(value >= 0.0f);
-
- int binaryExponent;
- (void)std::frexp(value, &binaryExponent);
- static const double kLog2 = 0.3010299956639812; // log10(2.0);
- int decimalExponent = static_cast<int>(std::floor(kLog2 * binaryExponent));
- int decimalShift = decimalExponent - 8;
- double power = pow10(-decimalShift);
- assert(value * power <= (double)INT_MAX);
- int d = static_cast<int>(value * power + 0.5);
- // assert(value == (float)(d * pow(10.0, decimalShift)));
- assert(d <= 999999999);
- if (d > 167772159) { // floor(pow(10,1+log10(1<<24)))
- // need one fewer decimal digits for 24-bit precision.
- decimalShift = decimalExponent - 7;
- // assert(power * 0.1 = pow10(-decimalShift));
- // recalculate to get rounding right.
- d = static_cast<int>(value * (power * 0.1) + 0.5);
- assert(d <= 99999999);
- }
- while (d % 10 == 0) {
- d /= 10;
- ++decimalShift;
- }
- assert(d > 0);
- // assert(value == (float)(d * pow(10.0, decimalShift)));
- unsigned char buffer[9]; // decimal value buffer.
- int bufferIndex = 0;
- do {
- buffer[bufferIndex++] = d % 10;
- d /= 10;
- } while (d != 0);
- assert(bufferIndex <= (int)sizeof(buffer) && bufferIndex > 0);
- if (decimalShift >= 0) {
- do {
- --bufferIndex;
- *output_ptr++ = '0' + buffer[bufferIndex];
- } while (bufferIndex);
- for (int i = 0; i < decimalShift; ++i) {
- *output_ptr++ = '0';
- }
- } else {
- int placesBeforeDecimal = bufferIndex + decimalShift;
- if (placesBeforeDecimal > 0) {
- while (placesBeforeDecimal-- > 0) {
- --bufferIndex;
- *output_ptr++ = '0' + buffer[bufferIndex];
- }
- *output_ptr++ = '.';
- } else {
- *output_ptr++ = '.';
- int placesAfterDecimal = -placesBeforeDecimal;
- while (placesAfterDecimal-- > 0) {
- *output_ptr++ = '0';
- }
- }
- while (bufferIndex > 0) {
- --bufferIndex;
- *output_ptr++ = '0' + buffer[bufferIndex];
- if (output_ptr == end) {
- break; // denormalized: don't need extra precision.
- // Note: denormalized numbers will not have the same number of
- // significantDigits, but do not need them to round-trip.
- }
- }
- }
- assert(output_ptr <= end);
- *output_ptr = '\0';
- return static_cast<unsigned>(output_ptr - output);
-}
-} // namespace skia
-} // namespace pdfium
diff --git a/third_party/skia_shared/SkFloatToDecimal.h b/third_party/skia_shared/SkFloatToDecimal.h
deleted file mode 100644
index 376b093b2..000000000
--- a/third_party/skia_shared/SkFloatToDecimal.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkFloatToDecimal_DEFINED
-#define SkFloatToDecimal_DEFINED
-
-namespace pdfium {
-namespace skia {
-
-constexpr unsigned kMaximumSkFloatToDecimalLength = 49;
-
-/** \fn SkFloatToDecimal
- Convert a float into a decimal string.
-
- The resulting string will be in the form `[-]?([0-9]*\.)?[0-9]+` (It does
- not use scientific notation.) and `sscanf(output, "%f", &x)` will return
- the original value if the value is finite. This function accepts all
- possible input values.
-
- INFINITY and -INFINITY are rounded to FLT_MAX and -FLT_MAX.
-
- NAN values are converted to 0.
-
- This function will always add a terminating '\0' to the output.
-
- @param value Any floating-point number
- @param output The buffer to write the string into. Must be non-null.
-
- @return strlen(output)
-*/
-unsigned SkFloatToDecimal(float value, char output[kMaximumSkFloatToDecimalLength]);
-
-} // namespace skia
-} // namespace pdfium
-
-#endif // SkFloatToDecimal_DEFINED
diff --git a/xfa/fde/cfde_texteditengine.cpp b/xfa/fde/cfde_texteditengine.cpp
index 497beb5e9..b28cced80 100644
--- a/xfa/fde/cfde_texteditengine.cpp
+++ b/xfa/fde/cfde_texteditengine.cpp
@@ -13,7 +13,7 @@
#include "core/fxcrt/span_util.h"
#include "core/fxge/text_char_pos.h"
#include "third_party/base/check.h"
-#include "third_party/base/notreached.h"
+#include "third_party/base/check_op.h"
#include "third_party/base/numerics/safe_conversions.h"
#include "xfa/fde/cfde_textout.h"
#include "xfa/fde/cfde_wordbreak_data.h"
@@ -1130,11 +1130,7 @@ std::pair<int32_t, CFX_RectF> CFDE_TextEditEngine::GetCharacterInfo(
if (it->nStart <= start_idx && start_idx < it->nStart + it->nCount)
break;
}
- if (it == text_piece_info_.end()) {
- NOTREACHED();
- return {0, CFX_RectF()};
- }
-
+ CHECK_NE(it, text_piece_info_.end());
return {it->nBidiLevel, GetCharRects(*it)[start_idx - it->nStart]};
}
diff --git a/xfa/fde/cfde_textout.cpp b/xfa/fde/cfde_textout.cpp
index af6ce5370..d7582d812 100644
--- a/xfa/fde/cfde_textout.cpp
+++ b/xfa/fde/cfde_textout.cpp
@@ -22,6 +22,7 @@
#include "core/fxge/fx_font.h"
#include "core/fxge/text_char_pos.h"
#include "third_party/base/check.h"
+#include "third_party/base/check_op.h"
#include "third_party/base/numerics/safe_conversions.h"
#include "xfa/fgas/font/cfgas_gefont.h"
#include "xfa/fgas/layout/cfgas_txtbreak.h"
@@ -129,7 +130,7 @@ CFDE_TextOut::Piece::Piece(const Piece& that) = default;
CFDE_TextOut::Piece::~Piece() = default;
CFDE_TextOut::CFDE_TextOut()
- : m_pTxtBreak(std::make_unique<CFGAS_TxtBreak>()), m_ttoLines(5) {}
+ : m_pTxtBreak(std::make_unique<CFGAS_TxtBreak>()) {}
CFDE_TextOut::~CFDE_TextOut() = default;
@@ -344,6 +345,7 @@ void CFDE_TextOut::LoadText(const WideString& str, const CFX_RectF& rect) {
}
if (m_fLinePos + fLineStep > fLineStop) {
size_t iCurLine = bEndofLine ? m_iCurLine - 1 : m_iCurLine;
+ CHECK_LT(m_iCurLine, m_ttoLines.size());
m_ttoLines[iCurLine].set_new_reload(true);
bRet = true;
break;
@@ -394,6 +396,7 @@ bool CFDE_TextOut::RetrievePieces(CFGAS_Char::BreakType dwBreakStatus,
}
if (j == chars_to_skip && !bReload) {
+ CHECK_LT(m_iCurLine, m_ttoLines.size());
m_ttoLines[m_iCurLine].set_new_reload(true);
} else if (j > chars_to_skip) {
Piece piece;
diff --git a/xfa/fde/cfde_textout.h b/xfa/fde/cfde_textout.h
index 72ff5b767..af2308b40 100644
--- a/xfa/fde/cfde_textout.h
+++ b/xfa/fde/cfde_textout.h
@@ -14,7 +14,7 @@
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/widestring.h"
#include "core/fxge/dib/fx_dib.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#include "xfa/fde/cfde_data.h"
#include "xfa/fgas/layout/cfgas_break.h"
#include "xfa/fgas/layout/cfgas_char.h"
diff --git a/xfa/fde/cfde_textout_unittest.cpp b/xfa/fde/cfde_textout_unittest.cpp
index fe078b0e9..006730288 100644
--- a/xfa/fde/cfde_textout_unittest.cpp
+++ b/xfa/fde/cfde_textout_unittest.cpp
@@ -86,7 +86,14 @@ class CFDETextOutTest : public testing::Test {
TEST_F(CFDETextOutTest, DrawLogicTextBasic) {
text_out().DrawLogicText(device(), L"foo", CFX_RectF(0, 0, 2100, 100));
- EXPECT_STREQ("b26f1c171fcdbf185823364185adacf0", GetBitmapChecksum().c_str());
+ const char* checksum = []() {
+#if BUILDFLAG(IS_WIN)
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
+ return "76fd535f7d490d963598474494d0701e";
+#endif
+ return "b26f1c171fcdbf185823364185adacf0";
+ }();
+ EXPECT_STREQ(checksum, GetBitmapChecksum().c_str());
}
TEST_F(CFDETextOutTest, DrawLogicTextEmptyRect) {
@@ -117,8 +124,9 @@ class CFDETextOutLargeBitmapTest : public CFDETextOutTest {
}
const char* GetLargeTextBlobChecksum() {
- if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
- return "6181929583fd7651169306852397806f";
+ if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
+ return "cd357c6afbf17bb2ac48817df5d9eaad";
+ }
return "268b71a8660b51e31c6bf30fc7ff1e08";
}
};
diff --git a/xfa/fgas/crt/cfgas_stringformatter.cpp b/xfa/fgas/crt/cfgas_stringformatter.cpp
index f70517580..d073dd71f 100644
--- a/xfa/fgas/crt/cfgas_stringformatter.cpp
+++ b/xfa/fgas/crt/cfgas_stringformatter.cpp
@@ -727,8 +727,7 @@ CFGAS_StringFormatter::DateTimeType AddDateToDatelessType(
case CFGAS_StringFormatter::DateTimeType::kTime:
return CFGAS_StringFormatter::DateTimeType::kTimeDate;
default:
- NOTREACHED();
- return type;
+ NOTREACHED_NORETURN();
}
}
@@ -740,8 +739,7 @@ CFGAS_StringFormatter::DateTimeType AddTimeToTimelessType(
case CFGAS_StringFormatter::DateTimeType::kDate:
return CFGAS_StringFormatter::DateTimeType::kDateTime;
default:
- NOTREACHED();
- return type;
+ NOTREACHED_NORETURN();
}
}
@@ -1735,7 +1733,6 @@ bool CFGAS_StringFormatter::ParseDateTime(LocaleMgrIface* pLocaleMgr,
ParseLocaleDate(wsSrcDateTime, wsDatePattern, pLocale, dtValue,
&iStart);
case DateTimeType::kUnknown:
- default:
return false;
}
}
diff --git a/xfa/fgas/crt/cfgas_stringformatter.h b/xfa/fgas/crt/cfgas_stringformatter.h
index 0dfa2bf4a..0acc76d15 100644
--- a/xfa/fgas/crt/cfgas_stringformatter.h
+++ b/xfa/fgas/crt/cfgas_stringformatter.h
@@ -10,7 +10,7 @@
#include <vector>
#include "core/fxcrt/widestring.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#include "xfa/fgas/crt/locale_iface.h"
class CFX_DateTime;
diff --git a/xfa/fgas/font/cfgas_fontmgr.cpp b/xfa/fgas/font/cfgas_fontmgr.cpp
index ec0eeeade..bb913b497 100644
--- a/xfa/fgas/font/cfgas_fontmgr.cpp
+++ b/xfa/fgas/font/cfgas_fontmgr.cpp
@@ -28,8 +28,8 @@
#include "core/fxge/fx_font.h"
#include "third_party/base/check.h"
#include "third_party/base/containers/contains.h"
+#include "third_party/base/containers/span.h"
#include "third_party/base/numerics/safe_conversions.h"
-#include "third_party/base/span.h"
#include "xfa/fgas/font/cfgas_gefont.h"
#include "xfa/fgas/font/fgas_fontutils.h"
diff --git a/xfa/fgas/font/cfgas_fontmgr.h b/xfa/fgas/font/cfgas_fontmgr.h
index 090d6386a..02cb47a95 100644
--- a/xfa/fgas/font/cfgas_fontmgr.h
+++ b/xfa/fgas/font/cfgas_fontmgr.h
@@ -66,9 +66,9 @@ class CFGAS_FontDescriptor {
uint32_t m_dwCsb[2] = {};
};
-class CFGAS_FontDescriptorInfo {
+struct CFGAS_FontDescriptorInfo {
public:
- CFGAS_FontDescriptor* pFont;
+ UNOWNED_PTR_EXCLUSION CFGAS_FontDescriptor* pFont; // POD struct.
int32_t nPenalty;
bool operator>(const CFGAS_FontDescriptorInfo& other) const {
diff --git a/xfa/fgas/font/fgas_fontutils.cpp b/xfa/fgas/font/fgas_fontutils.cpp
index e8b8876ee..9cc421ca3 100644
--- a/xfa/fgas/font/fgas_fontutils.cpp
+++ b/xfa/fgas/font/fgas_fontutils.cpp
@@ -2450,14 +2450,17 @@ const FGAS_FONTUSB* FGAS_GetUnicodeBitField(wchar_t unicode) {
WideString FGAS_FontNameToEnglishName(const WideString& wsLocalName) {
uint32_t dwLocalNameHash =
FX_HashCode_GetLoweredW(wsLocalName.AsStringView());
- const FGAS_FontInfo* pEnd = kXFAFontsMap + std::size(kXFAFontsMap);
+ const FGAS_FontInfo* pBegin = std::begin(kXFAFontsMap);
+ const FGAS_FontInfo* pEnd = std::end(kXFAFontsMap);
const FGAS_FontInfo* pFontInfo =
- std::lower_bound(kXFAFontsMap, pEnd, dwLocalNameHash,
+ std::lower_bound(pBegin, pEnd, dwLocalNameHash,
[](const FGAS_FontInfo& entry, uint32_t hash) {
return entry.dwFontNameHash < hash;
});
- if (pFontInfo < pEnd && pFontInfo->dwFontNameHash == dwLocalNameHash)
+
+ if (pFontInfo < pEnd && pFontInfo->dwFontNameHash == dwLocalNameHash) {
return WideString::FromASCII(ByteStringView(pFontInfo->pPsName));
+ }
return wsLocalName;
}
@@ -2466,13 +2469,16 @@ const FGAS_FontInfo* FGAS_FontInfoByFontName(WideStringView wsFontName) {
wsFontNameTemp.Remove(L' ');
uint32_t dwCurFontNameHash =
FX_HashCode_GetLoweredW(wsFontNameTemp.AsStringView());
- const FGAS_FontInfo* pEnd = kXFAFontsMap + std::size(kXFAFontsMap);
+ const FGAS_FontInfo* pBegin = std::begin(kXFAFontsMap);
+ const FGAS_FontInfo* pEnd = std::end(kXFAFontsMap);
const FGAS_FontInfo* pFontInfo =
- std::lower_bound(kXFAFontsMap, pEnd, dwCurFontNameHash,
+ std::lower_bound(pBegin, pEnd, dwCurFontNameHash,
[](const FGAS_FontInfo& entry, uint32_t hash) {
return entry.dwFontNameHash < hash;
});
- if (pFontInfo < pEnd && pFontInfo->dwFontNameHash == dwCurFontNameHash)
+
+ if (pFontInfo < pEnd && pFontInfo->dwFontNameHash == dwCurFontNameHash) {
return pFontInfo;
+ }
return nullptr;
}
diff --git a/xfa/fgas/graphics/cfgas_gegraphics.cpp b/xfa/fgas/graphics/cfgas_gegraphics.cpp
index c9091830b..cb2b9596a 100644
--- a/xfa/fgas/graphics/cfgas_gegraphics.cpp
+++ b/xfa/fgas/graphics/cfgas_gegraphics.cpp
@@ -19,7 +19,6 @@
#include "core/fxge/cfx_unicodeencoding.h"
#include "core/fxge/dib/cfx_dibitmap.h"
#include "third_party/base/check.h"
-#include "third_party/base/notreached.h"
#include "xfa/fgas/graphics/cfgas_gecolor.h"
#include "xfa/fgas/graphics/cfgas_gepath.h"
#include "xfa/fgas/graphics/cfgas_gepattern.h"
@@ -129,10 +128,7 @@ void CFGAS_GEGraphics::SaveGraphState() {
void CFGAS_GEGraphics::RestoreGraphState() {
m_renderDevice->RestoreState(false);
- if (m_infoStack.empty()) {
- NOTREACHED();
- return;
- }
+ CHECK(!m_infoStack.empty());
m_info = *m_infoStack.back();
m_infoStack.pop_back();
return;
@@ -261,7 +257,7 @@ void CFGAS_GEGraphics::FillPathWithPattern(
auto mask = pdfium::MakeRetain<CFX_DIBitmap>();
mask->Create(data.width, data.height, FXDIB_Format::k1bppMask);
fxcrt::spancpy(
- mask->GetBuffer(),
+ mask->GetWritableBuffer(),
pdfium::make_span(data.maskBits).first(mask->GetPitch() * data.height));
const CFX_FloatRect rectf =
matrix.TransformRect(path.GetPath().GetBoundingBox());
@@ -390,10 +386,6 @@ void CFGAS_GEGraphics::FillPathWithShading(
result = true;
break;
}
- default: {
- result = false;
- break;
- }
}
if (result) {
CFX_RenderDevice::StateRestorer restorer(m_renderDevice);
diff --git a/xfa/fgas/graphics/cfgas_gegraphics.h b/xfa/fgas/graphics/cfgas_gegraphics.h
index cf86c3842..8e4e408c5 100644
--- a/xfa/fgas/graphics/cfgas_gegraphics.h
+++ b/xfa/fgas/graphics/cfgas_gegraphics.h
@@ -16,7 +16,7 @@
#include "core/fxcrt/unowned_ptr.h"
#include "core/fxge/cfx_fillrenderoptions.h"
#include "core/fxge/cfx_graphstatedata.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#include "xfa/fgas/graphics/cfgas_gecolor.h"
class CFGAS_GEPath;
diff --git a/xfa/fgas/layout/cfgas_rtfbreak.cpp b/xfa/fgas/layout/cfgas_rtfbreak.cpp
index 66192dc8f..540a226b5 100644
--- a/xfa/fgas/layout/cfgas_rtfbreak.cpp
+++ b/xfa/fgas/layout/cfgas_rtfbreak.cpp
@@ -113,7 +113,6 @@ CFGAS_Char::BreakType CFGAS_RTFBreak::AppendChar(wchar_t wch) {
case FX_CHARTYPE::kSpace:
case FX_CHARTYPE::kNumeric:
case FX_CHARTYPE::kNormal:
- default:
dwRet2 = AppendChar_Others(pCurChar);
break;
}
diff --git a/xfa/fgas/layout/cfgas_txtbreak.cpp b/xfa/fgas/layout/cfgas_txtbreak.cpp
index e00ab02a7..22a627711 100644
--- a/xfa/fgas/layout/cfgas_txtbreak.cpp
+++ b/xfa/fgas/layout/cfgas_txtbreak.cpp
@@ -260,7 +260,6 @@ CFGAS_Char::BreakType CFGAS_TxtBreak::AppendChar(wchar_t wch) {
case FX_CHARTYPE::kSpace:
case FX_CHARTYPE::kNumeric:
case FX_CHARTYPE::kNormal:
- default:
dwRet2 = AppendChar_Others(pCurChar);
break;
}
diff --git a/xfa/fgas/layout/cfgas_txtbreak.h b/xfa/fgas/layout/cfgas_txtbreak.h
index ae69a2445..c7b993115 100644
--- a/xfa/fgas/layout/cfgas_txtbreak.h
+++ b/xfa/fgas/layout/cfgas_txtbreak.h
@@ -12,6 +12,8 @@
#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/retain_ptr.h"
+#include "core/fxcrt/unowned_ptr.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
#include "xfa/fgas/layout/cfgas_break.h"
#include "xfa/fgas/layout/cfgas_char.h"
@@ -49,9 +51,9 @@ class CFGAS_TxtBreak final : public CFGAS_Break {
Run(const Run& other);
~Run();
- CFGAS_TxtBreak::Engine* pEdtEngine = nullptr;
+ UnownedPtr<CFGAS_TxtBreak::Engine> pEdtEngine;
WideString wsStr;
- int32_t* pWidths = nullptr;
+ UNOWNED_PTR_EXCLUSION int32_t* pWidths = nullptr;
// TODO(thestig): These 2 members probably should be size_t.
int32_t iStart = 0;
int32_t iLength = 0;
@@ -61,7 +63,7 @@ class CFGAS_TxtBreak final : public CFGAS_Break {
int32_t iHorizontalScale = 100;
int32_t iVerticalScale = 100;
uint32_t dwCharStyles = 0;
- const CFX_RectF* pRect = nullptr;
+ UnownedPtr<const CFX_RectF> pRect;
bool bSkipSpace = true;
};
diff --git a/xfa/fwl/cfwl_edit.cpp b/xfa/fwl/cfwl_edit.cpp
index f95176db3..9d624c90f 100644
--- a/xfa/fwl/cfwl_edit.cpp
+++ b/xfa/fwl/cfwl_edit.cpp
@@ -15,7 +15,6 @@
#include "core/fxge/cfx_renderdevice.h"
#include "core/fxge/text_char_pos.h"
#include "third_party/base/check.h"
-#include "third_party/base/cxx17_backports.h"
#include "third_party/base/numerics/safe_conversions.h"
#include "v8/include/cppgc/visitor.h"
#include "xfa/fde/cfde_textout.h"
@@ -583,7 +582,7 @@ CFWL_ScrollBar* CFWL_Edit::UpdateScroll() {
float fRange =
std::max(contents_bounds.height - m_EngineRect.height, fStep);
m_pVertScrollBar->SetRange(0.0f, fRange);
- float fPos = pdfium::clamp(m_fScrollOffsetY, 0.0f, fRange);
+ float fPos = std::clamp(m_fScrollOffsetY, 0.0f, fRange);
m_pVertScrollBar->SetPos(fPos);
m_pVertScrollBar->SetTrackPos(fPos);
m_pVertScrollBar->SetPageSize(rtScroll.height);
diff --git a/xfa/fwl/cfwl_event.h b/xfa/fwl/cfwl_event.h
index 385abec12..ab9606d98 100644
--- a/xfa/fwl/cfwl_event.h
+++ b/xfa/fwl/cfwl_event.h
@@ -7,6 +7,7 @@
#ifndef XFA_FWL_CFWL_EVENT_H_
#define XFA_FWL_CFWL_EVENT_H_
+#include "core/fxcrt/unowned_ptr.h"
#include "v8/include/cppgc/macros.h"
class CFWL_Widget;
@@ -41,8 +42,8 @@ class CFWL_Event {
private:
const Type m_type;
- CFWL_Widget* const m_pSrcTarget = nullptr;
- CFWL_Widget* const m_pDstTarget = nullptr;
+ UnownedPtr<CFWL_Widget> const m_pSrcTarget;
+ UnownedPtr<CFWL_Widget> const m_pDstTarget;
};
#endif // XFA_FWL_CFWL_EVENT_H_
diff --git a/xfa/fwl/cfwl_listbox.cpp b/xfa/fwl/cfwl_listbox.cpp
index dbd29e16b..9f4c89a79 100644
--- a/xfa/fwl/cfwl_listbox.cpp
+++ b/xfa/fwl/cfwl_listbox.cpp
@@ -11,7 +11,6 @@
#include <utility>
#include "core/fxcrt/stl_util.h"
-#include "third_party/base/cxx17_backports.h"
#include "third_party/base/numerics/safe_conversions.h"
#include "v8/include/cppgc/visitor.h"
#include "xfa/fde/cfde_textout.h"
@@ -463,7 +462,7 @@ CFX_SizeF CFWL_ListBox::CalcSize() {
m_pVertScrollBar->SetPageSize(rtScrollBar.height * 9 / 10);
m_pVertScrollBar->SetStepSize(m_fItemHeight);
- float fPos = pdfium::clamp(m_pVertScrollBar->GetPos(), 0.0f, fMax);
+ float fPos = std::clamp(m_pVertScrollBar->GetPos(), 0.0f, fMax);
m_pVertScrollBar->SetPos(fPos);
m_pVertScrollBar->SetTrackPos(fPos);
if ((m_Properties.m_dwStyleExts & FWL_STYLEEXT_LTB_ShowScrollBarFocus) ==
@@ -493,7 +492,7 @@ CFX_SizeF CFWL_ListBox::CalcSize() {
m_pHorzScrollBar->SetPageSize(fWidth * 9 / 10);
m_pHorzScrollBar->SetStepSize(fWidth / 10);
- float fPos = pdfium::clamp(m_pHorzScrollBar->GetPos(), 0.0f, fMax);
+ float fPos = std::clamp(m_pHorzScrollBar->GetPos(), 0.0f, fMax);
m_pHorzScrollBar->SetPos(fPos);
m_pHorzScrollBar->SetTrackPos(fPos);
if ((m_Properties.m_dwStyleExts & FWL_STYLEEXT_LTB_ShowScrollBarFocus) ==
@@ -617,8 +616,6 @@ void CFWL_ListBox::OnProcessMessage(CFWL_Message* pMessage) {
OnKeyDown(pMsg);
break;
}
- default:
- break;
}
// Dst target could be |this|, continue only if not destroyed by above.
if (pMessage->GetDstTarget())
diff --git a/xfa/fwl/cfwl_listbox.h b/xfa/fwl/cfwl_listbox.h
index 9f27b6530..223684203 100644
--- a/xfa/fwl/cfwl_listbox.h
+++ b/xfa/fwl/cfwl_listbox.h
@@ -10,6 +10,7 @@
#include <memory>
#include <vector>
+#include "core/fxcrt/unowned_ptr.h"
#include "xfa/fwl/cfwl_edit.h"
#include "xfa/fwl/cfwl_event.h"
#include "xfa/fwl/cfwl_listbox.h"
@@ -136,8 +137,8 @@ class CFWL_ListBox : public CFWL_Widget {
bool m_bLButtonDown = false;
float m_fItemHeight = 0.0f;
float m_fScorllBarWidth = 0.0f;
- Item* m_hAnchor = nullptr;
- std::vector<std::unique_ptr<Item>> m_ItemArray;
+ std::vector<std::unique_ptr<Item>> m_ItemArray; // Must outlive `m_hAnchor`.
+ UnownedPtr<Item> m_hAnchor;
};
#endif // XFA_FWL_CFWL_LISTBOX_H_
diff --git a/xfa/fwl/cfwl_monthcalendar.cpp b/xfa/fwl/cfwl_monthcalendar.cpp
index 145198bd9..5867ec9d0 100644
--- a/xfa/fwl/cfwl_monthcalendar.cpp
+++ b/xfa/fwl/cfwl_monthcalendar.cpp
@@ -50,8 +50,7 @@ WideString GetAbbreviatedDayOfWeek(int day) {
case 6:
return L"Sat";
default:
- NOTREACHED();
- return L"";
+ NOTREACHED_NORETURN();
}
}
@@ -82,8 +81,7 @@ WideString GetMonth(int month) {
case 11:
return L"December";
default:
- NOTREACHED();
- return L"";
+ NOTREACHED_NORETURN();
}
}
diff --git a/xfa/fwl/cfwl_notedriver.cpp b/xfa/fwl/cfwl_notedriver.cpp
index e6bcfe8ba..f3506d695 100644
--- a/xfa/fwl/cfwl_notedriver.cpp
+++ b/xfa/fwl/cfwl_notedriver.cpp
@@ -131,8 +131,6 @@ bool CFWL_NoteDriver::DispatchMessage(CFWL_Message* pMessage,
return false;
break;
}
- default:
- break;
}
IFWL_WidgetDelegate* pDelegate = pMessage->GetDstTarget()->GetDelegate();
if (pDelegate)
diff --git a/xfa/fwl/cfwl_scrollbar.cpp b/xfa/fwl/cfwl_scrollbar.cpp
index 36dd9e567..4bf4b366d 100644
--- a/xfa/fwl/cfwl_scrollbar.cpp
+++ b/xfa/fwl/cfwl_scrollbar.cpp
@@ -10,7 +10,6 @@
#include <memory>
#include <utility>
-#include "third_party/base/cxx17_backports.h"
#include "xfa/fwl/cfwl_app.h"
#include "xfa/fwl/cfwl_messagemouse.h"
#include "xfa/fwl/cfwl_messagemousewheel.h"
@@ -200,7 +199,7 @@ CFX_RectF CFWL_ScrollBar::CalcThumbButtonRect(const CFX_RectF& rtThumb) {
fThumbSize = std::max(fThumbSize, kMinThumbSize);
float fDiff = std::max(fLength - fThumbSize, 0.0f);
- float fTrackPos = pdfium::clamp(m_fTrackPos, m_fRangeMin, m_fRangeMax);
+ float fTrackPos = std::clamp(m_fTrackPos, m_fRangeMin, m_fRangeMax);
if (!fRange)
return rect;
@@ -268,7 +267,7 @@ float CFWL_ScrollBar::GetTrackPointPos(const CFX_PointF& point) {
}
fPos += m_fLastTrackPos;
- return pdfium::clamp(fPos, m_fRangeMin, m_fRangeMax);
+ return std::clamp(fPos, m_fRangeMin, m_fRangeMax);
}
bool CFWL_ScrollBar::SendEvent() {
diff --git a/xfa/fxfa/cxfa_ffline.cpp b/xfa/fxfa/cxfa_ffline.cpp
index b8f781599..47ebc2e9b 100644
--- a/xfa/fxfa/cxfa_ffline.cpp
+++ b/xfa/fxfa/cxfa_ffline.cpp
@@ -48,8 +48,7 @@ void CXFA_FFLine::GetRectFromHand(CFX_RectF& rect,
case XFA_AttributeValue::Even:
break;
default:
- NOTREACHED();
- break;
+ NOTREACHED_NORETURN();
}
} else if (rect.width < 1.0f) {
switch (iHand) {
@@ -62,8 +61,7 @@ void CXFA_FFLine::GetRectFromHand(CFX_RectF& rect,
case XFA_AttributeValue::Even:
break;
default:
- NOTREACHED();
- break;
+ NOTREACHED_NORETURN();
}
} else {
switch (iHand) {
@@ -76,8 +74,7 @@ void CXFA_FFLine::GetRectFromHand(CFX_RectF& rect,
case XFA_AttributeValue::Even:
break;
default:
- NOTREACHED();
- break;
+ NOTREACHED_NORETURN();
}
}
}
diff --git a/xfa/fxfa/cxfa_textlayout.cpp b/xfa/fxfa/cxfa_textlayout.cpp
index 10782c02f..8228a5cb2 100644
--- a/xfa/fxfa/cxfa_textlayout.cpp
+++ b/xfa/fxfa/cxfa_textlayout.cpp
@@ -182,8 +182,7 @@ void CXFA_TextLayout::InitBreak(float fLineWidth) {
case XFA_AttributeValue::Radix:
break;
default:
- NOTREACHED();
- break;
+ NOTREACHED_NORETURN();
}
m_pBreak->SetAlignment(iAlign);
@@ -715,8 +714,7 @@ void CXFA_TextLayout::LoadText(CXFA_Node* pNode,
break;
}
default:
- NOTREACHED();
- break;
+ NOTREACHED_NORETURN();
}
}
diff --git a/xfa/fxfa/cxfa_textparser.cpp b/xfa/fxfa/cxfa_textparser.cpp
index c50368973..15b517883 100644
--- a/xfa/fxfa/cxfa_textparser.cpp
+++ b/xfa/fxfa/cxfa_textparser.cpp
@@ -135,8 +135,7 @@ RetainPtr<CFX_CSSComputedStyle> CXFA_TextParser::CreateRootStyle(
case XFA_AttributeValue::Radix:
break;
default:
- NOTREACHED();
- break;
+ NOTREACHED_NORETURN();
}
pStyle->SetTextAlign(hAlign);
CFX_CSSRect rtMarginWidth;
diff --git a/xfa/fxfa/formcalc/cxfa_fmparser.h b/xfa/fxfa/formcalc/cxfa_fmparser.h
index 1f02f6032..e8b6c4435 100644
--- a/xfa/fxfa/formcalc/cxfa_fmparser.h
+++ b/xfa/fxfa/formcalc/cxfa_fmparser.h
@@ -9,7 +9,7 @@
#include <vector>
-#include "core/fxcrt/unowned_ptr.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
#include "fxjs/gc/heap.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "v8/include/cppgc/macros.h"
@@ -64,7 +64,7 @@ class CXFA_FMParser {
ParseArgumentList();
UnownedPtr<cppgc::Heap> const m_heap;
- UnownedPtr<CXFA_FMLexer> m_lexer;
+ UNOWNED_PTR_EXCLUSION CXFA_FMLexer* const m_lexer; // Stack allocated.
CXFA_FMLexer::Token m_token;
bool m_error = false;
unsigned long m_parse_depth = 0;
diff --git a/xfa/fxfa/layout/cxfa_contentlayoutprocessor.cpp b/xfa/fxfa/layout/cxfa_contentlayoutprocessor.cpp
index 1d827f390..96eb05f72 100644
--- a/xfa/fxfa/layout/cxfa_contentlayoutprocessor.cpp
+++ b/xfa/fxfa/layout/cxfa_contentlayoutprocessor.cpp
@@ -78,7 +78,7 @@ void UpdateWidgetSize(CXFA_ContentLayoutItem* pLayoutItem,
break;
}
default:
- NOTREACHED();
+ NOTREACHED_NORETURN();
}
}
@@ -1849,7 +1849,6 @@ CXFA_ContentLayoutProcessor::DoLayoutFlowedContainer(
case Result::kRowFullBreak:
goto SuspendAndCreateNewRow;
case Result::kDone:
- default:
fContentCurRowY +=
pProcessor->InsertPendingItems(m_pCurChildNode);
pProcessor = nullptr;
@@ -1859,8 +1858,6 @@ CXFA_ContentLayoutProcessor::DoLayoutFlowedContainer(
}
case Stage::kDone:
break;
- default:
- break;
}
GotoNextContainerNodeSimple();
if (bAddedItemInRow && eFlowStrategy == XFA_AttributeValue::Tb)
diff --git a/xfa/fxfa/layout/cxfa_viewlayoutprocessor.h b/xfa/fxfa/layout/cxfa_viewlayoutprocessor.h
index e48c9dffc..859621d79 100644
--- a/xfa/fxfa/layout/cxfa_viewlayoutprocessor.h
+++ b/xfa/fxfa/layout/cxfa_viewlayoutprocessor.h
@@ -13,6 +13,7 @@
#include <vector>
#include "core/fxcrt/unowned_ptr.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
#include "fxjs/gc/heap.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "v8/include/cppgc/garbage-collected.h"
@@ -33,16 +34,16 @@ class CXFA_ViewLayoutProcessor
struct BreakData {
CPPGC_STACK_ALLOCATED(); // Raw/Unowned pointers allowed.
public:
- CXFA_Node* pLeader;
- CXFA_Node* pTrailer;
+ UNOWNED_PTR_EXCLUSION CXFA_Node* pLeader; // POD struct.
+ UNOWNED_PTR_EXCLUSION CXFA_Node* pTrailer; // POD struct.
bool bCreatePage;
};
struct OverflowData {
CPPGC_STACK_ALLOCATED(); // Raw/Unowned pointers allowed.
public:
- CXFA_Node* pLeader;
- CXFA_Node* pTrailer;
+ UNOWNED_PTR_EXCLUSION CXFA_Node* pLeader; // POD struct.
+ UNOWNED_PTR_EXCLUSION CXFA_Node* pTrailer; // POD struct.
};
CONSTRUCT_VIA_MAKE_GARBAGE_COLLECTED;
diff --git a/xfa/fxfa/parser/cxfa_box.cpp b/xfa/fxfa/parser/cxfa_box.cpp
index 761c7c813..cd644aa9f 100644
--- a/xfa/fxfa/parser/cxfa_box.cpp
+++ b/xfa/fxfa/parser/cxfa_box.cpp
@@ -207,7 +207,7 @@ void CXFA_Box::Draw(CFGAS_GEGraphics* pGS,
} else if (type == XFA_Element::Rectangle || type == XFA_Element::Border) {
ToRectangle(this)->Draw(strokes, pGS, rtWidget, matrix);
} else {
- NOTREACHED();
+ NOTREACHED_NORETURN();
}
}
@@ -237,7 +237,7 @@ void CXFA_Box::DrawFill(const std::vector<CXFA_Stroke*>& strokes,
} else if (type == XFA_Element::Rectangle || type == XFA_Element::Border) {
ToRectangle(this)->GetFillPath(strokes, rtWidget, &fillPath);
} else {
- NOTREACHED();
+ NOTREACHED_NORETURN();
}
fillPath.Close();
fill->Draw(pGS, fillPath, rtWidget, matrix);
diff --git a/xfa/fxfa/parser/cxfa_document.cpp b/xfa/fxfa/parser/cxfa_document.cpp
index 70464c469..45c7849fa 100644
--- a/xfa/fxfa/parser/cxfa_document.cpp
+++ b/xfa/fxfa/parser/cxfa_document.cpp
@@ -1648,8 +1648,7 @@ CXFA_Node* CXFA_Document::DataMerge_CopyContainer(CXFA_Node* pTemplateNode,
case XFA_Element::Variables:
return nullptr;
default:
- NOTREACHED();
- return nullptr;
+ NOTREACHED_NORETURN();
}
}
diff --git a/xfa/fxfa/parser/cxfa_document.h b/xfa/fxfa/parser/cxfa_document.h
index 585ee4c54..3b334838f 100644
--- a/xfa/fxfa/parser/cxfa_document.h
+++ b/xfa/fxfa/parser/cxfa_document.h
@@ -18,7 +18,7 @@
#include "core/fxcrt/widestring.h"
#include "fxjs/gc/heap.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#include "v8/include/cppgc/garbage-collected.h"
#include "v8/include/cppgc/member.h"
#include "v8/include/cppgc/persistent.h"
diff --git a/xfa/fxfa/parser/cxfa_document_builder.cpp b/xfa/fxfa/parser/cxfa_document_builder.cpp
index 6fc52b723..c1032845c 100644
--- a/xfa/fxfa/parser/cxfa_document_builder.cpp
+++ b/xfa/fxfa/parser/cxfa_document_builder.cpp
@@ -170,8 +170,7 @@ void ConvertXMLToPlainText(CFX_XMLElement* pRootXMLNode, WideString& wsOutput) {
break;
}
default:
- NOTREACHED();
- break;
+ NOTREACHED_NORETURN();
}
}
}
diff --git a/xfa/fxfa/parser/cxfa_localemgr.cpp b/xfa/fxfa/parser/cxfa_localemgr.cpp
index 53444b05b..f49275e04 100644
--- a/xfa/fxfa/parser/cxfa_localemgr.cpp
+++ b/xfa/fxfa/parser/cxfa_localemgr.cpp
@@ -1199,7 +1199,6 @@ CXFA_XMLLocale* CXFA_LocaleMgr::GetLocale(LangID lcid) {
case LangID::k_ru_RU:
return GetLocaleFromBuffer(m_pHeap, k_ruRU_Locale);
case LangID::k_en_US:
- default:
return GetLocaleFromBuffer(m_pHeap, k_enUS_Locale);
}
}
diff --git a/xfa/fxfa/parser/cxfa_localevalue.cpp b/xfa/fxfa/parser/cxfa_localevalue.cpp
index 165fe26d5..b3b097048 100644
--- a/xfa/fxfa/parser/cxfa_localevalue.cpp
+++ b/xfa/fxfa/parser/cxfa_localevalue.cpp
@@ -15,7 +15,7 @@
#include "core/fxcrt/cfx_datetime.h"
#include "core/fxcrt/fx_extension.h"
#include "third_party/base/check.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#include "xfa/fgas/crt/cfgas_stringformatter.h"
#include "xfa/fxfa/parser/cxfa_document.h"
#include "xfa/fxfa/parser/cxfa_localemgr.h"
diff --git a/xfa/fxfa/parser/cxfa_measurement.cpp b/xfa/fxfa/parser/cxfa_measurement.cpp
index db71075f5..94675c8ae 100644
--- a/xfa/fxfa/parser/cxfa_measurement.cpp
+++ b/xfa/fxfa/parser/cxfa_measurement.cpp
@@ -127,8 +127,7 @@ bool CXFA_Measurement::ToUnitInternal(XFA_Unit eUnit, float* fValue) const {
*fValue /= kPtToPc;
return true;
default:
- NOTREACHED();
- return false;
+ NOTREACHED_NORETURN();
}
}
diff --git a/xfa/fxfa/parser/cxfa_node.cpp b/xfa/fxfa/parser/cxfa_node.cpp
index e50813688..2bf0f16f9 100644
--- a/xfa/fxfa/parser/cxfa_node.cpp
+++ b/xfa/fxfa/parser/cxfa_node.cpp
@@ -36,8 +36,8 @@
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
#include "third_party/base/containers/contains.h"
+#include "third_party/base/containers/span.h"
#include "third_party/base/notreached.h"
-#include "third_party/base/span.h"
#include "xfa/fde/cfde_textout.h"
#include "xfa/fgas/crt/cfgas_decimal.h"
#include "xfa/fgas/crt/locale_iface.h"
@@ -2918,7 +2918,7 @@ CXFA_Node::CreateChildUIAndValueNodesIfNeeded() {
widget_type = XFA_FFWidgetType::kTextEdit;
}
} else {
- NOTREACHED();
+ NOTREACHED_NORETURN();
}
if (!pUIChild) {
@@ -2933,8 +2933,7 @@ CXFA_Node::CreateChildUIAndValueNodesIfNeeded() {
}
XFA_FFWidgetType CXFA_Node::GetDefaultFFWidgetType() const {
- NOTREACHED();
- return XFA_FFWidgetType::kNone;
+ NOTREACHED_NORETURN();
}
CXFA_Node* CXFA_Node::CreateUINodeIfNeeded(CXFA_Ui* ui, XFA_Element type) {
@@ -2979,7 +2978,7 @@ CXFA_Node* CXFA_Node::GetUIChildNode() {
} else if (type == XFA_Element::ExclGroup) {
ff_widget_type_ = XFA_FFWidgetType::kExclGroup;
} else {
- NOTREACHED();
+ NOTREACHED_NORETURN();
}
return ui_ ? ui_->GetFirstChild() : nullptr;
}
@@ -3710,8 +3709,7 @@ absl::optional<float> CXFA_Node::FindSplitPos(CXFA_FFDocView* pDocView,
fStartOffset += (fHeight - fTextHeight + fSpaceAbove);
break;
default:
- NOTREACHED();
- break;
+ NOTREACHED_NORETURN();
}
}
if (fStartOffset < 0.1f)
@@ -5096,7 +5094,7 @@ void CXFA_Node::SetToXML(const WideString& value) {
ToXMLText(GetXMLMappingNode())->SetText(value);
break;
default:
- NOTREACHED();
+ NOTREACHED_NORETURN();
}
}
diff --git a/xfa/fxfa/parser/cxfa_node.h b/xfa/fxfa/parser/cxfa_node.h
index 9bffa7ddd..08e19f6c4 100644
--- a/xfa/fxfa/parser/cxfa_node.h
+++ b/xfa/fxfa/parser/cxfa_node.h
@@ -17,11 +17,12 @@
#include "core/fxcrt/mask.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/unowned_ptr.h"
+#include "core/fxcrt/unowned_ptr_exclusion.h"
#include "core/fxcrt/widestring.h"
#include "core/fxge/dib/fx_dib.h"
#include "fxjs/gc/gced_tree_node_mixin.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#include "v8/include/cppgc/member.h"
#include "v8/include/cppgc/visitor.h"
#include "xfa/fxfa/cxfa_ffwidget_type.h"
@@ -108,7 +109,7 @@ class CXFA_Node : public CXFA_Object, public GCedTreeNodeMixin<CXFA_Node> {
struct AttributeData {
XFA_Attribute attribute;
XFA_AttributeType type;
- void* default_value;
+ UNOWNED_PTR_EXCLUSION void* default_value; // POD type.
};
// Node is created from cppgc heap.
diff --git a/xfa/fxfa/parser/cxfa_node_unittest.cpp b/xfa/fxfa/parser/cxfa_node_unittest.cpp
index 2c745cab6..e00772c5a 100644
--- a/xfa/fxfa/parser/cxfa_node_unittest.cpp
+++ b/xfa/fxfa/parser/cxfa_node_unittest.cpp
@@ -411,3 +411,14 @@ TEST_F(CXFANodeTest, AncestorOf) {
EXPECT_TRUE(GetNode()->IsAncestorOf(grandchild));
EXPECT_FALSE(child1->IsAncestorOf(grandchild));
}
+
+TEST_F(CXFANodeTest, DeltaObjectIsNode) {
+ CXFA_Node* delta =
+ CXFA_Node::Create(GetDoc(), XFA_Element::Delta, XFA_PacketType::Form);
+ ASSERT_TRUE(delta);
+ ASSERT_TRUE(delta->IsNode());
+
+ // This call should not crash, like in crbug.com/1465239.
+ delta->JSObject()->SetAttributeByEnum(XFA_Attribute::Name, L"delta",
+ /*bNotify=*/false);
+}
diff --git a/xfa/fxfa/parser/cxfa_object.h b/xfa/fxfa/parser/cxfa_object.h
index 84c4e983b..c482d3b57 100644
--- a/xfa/fxfa/parser/cxfa_object.h
+++ b/xfa/fxfa/parser/cxfa_object.h
@@ -59,7 +59,8 @@ class CXFA_Object : public cppgc::GarbageCollected<CXFA_Object> {
m_objectType == XFA_ObjectType::ModelNode ||
m_objectType == XFA_ObjectType::TextNode ||
m_objectType == XFA_ObjectType::ContainerNode ||
- m_objectType == XFA_ObjectType::ContentNode;
+ m_objectType == XFA_ObjectType::ContentNode ||
+ m_elementType == XFA_Element::Delta;
}
bool IsTreeList() const { return m_objectType == XFA_ObjectType::TreeList; }
bool IsContentNode() const {
diff --git a/xfa/fxfa/parser/cxfa_rectangle.cpp b/xfa/fxfa/parser/cxfa_rectangle.cpp
index 60ac29433..c6be5aca2 100644
--- a/xfa/fxfa/parser/cxfa_rectangle.cpp
+++ b/xfa/fxfa/parser/cxfa_rectangle.cpp
@@ -303,8 +303,7 @@ void CXFA_Rectangle::Stroke(const std::vector<CXFA_Stroke*>& strokes,
StrokeEmbossed(pGS, rtWidget, fThickness, matrix);
break;
default:
- NOTREACHED();
- break;
+ NOTREACHED_NORETURN();
}
return;
}
diff --git a/xfa/fxfa/parser/cxfa_xmllocale.h b/xfa/fxfa/parser/cxfa_xmllocale.h
index 726a4faec..0c045ff91 100644
--- a/xfa/fxfa/parser/cxfa_xmllocale.h
+++ b/xfa/fxfa/parser/cxfa_xmllocale.h
@@ -11,7 +11,7 @@
#include "core/fxcrt/unowned_ptr.h"
#include "fxjs/gc/heap.h"
-#include "third_party/base/span.h"
+#include "third_party/base/containers/span.h"
#include "v8/include/cppgc/garbage-collected.h"
#include "xfa/fxfa/parser/gced_locale_iface.h"