| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef PDF_PDFIUM_PDFIUM_ENGINE_H_ |
| #define PDF_PDFIUM_PDFIUM_ENGINE_H_ |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include <array> |
| #include <map> |
| #include <memory> |
| #include <optional> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "base/containers/flat_map.h" |
| #include "base/containers/span.h" |
| #include "base/dcheck_is_on.h" |
| #include "base/functional/callback.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/time/time.h" |
| #include "base/timer/timer.h" |
| #include "base/values.h" |
| #include "build/build_config.h" |
| #include "pdf/accessibility_structs.h" |
| #include "pdf/buildflags.h" |
| #include "pdf/document_attachment_info.h" |
| #include "pdf/document_layout.h" |
| #include "pdf/document_metadata.h" |
| #include "pdf/loader/document_loader.h" |
| #include "pdf/pdf_annotation_agent.h" |
| #include "pdf/pdf_caret.h" |
| #include "pdf/pdf_caret_client.h" |
| #include "pdf/pdf_rect.h" |
| #include "pdf/pdfium/pdfium_engine_client.h" |
| #include "pdf/pdfium/pdfium_form_filler.h" |
| #include "pdf/pdfium/pdfium_page.h" |
| #include "pdf/pdfium/pdfium_print.h" |
| #include "pdf/pdfium/pdfium_range.h" |
| #include "pdf/region_data.h" |
| #include "printing/mojom/print.mojom-forward.h" |
| #include "services/screen_ai/buildflags/buildflags.h" |
| #include "third_party/pdfium/public/cpp/fpdf_scopers.h" |
| #include "third_party/pdfium/public/fpdf_formfill.h" |
| #include "third_party/pdfium/public/fpdf_progressive.h" |
| #include "third_party/pdfium/public/fpdfview.h" |
| #include "third_party/skia/include/core/SkBitmap.h" |
| #include "third_party/skia/include/core/SkColor.h" |
| #include "ui/gfx/geometry/insets.h" |
| #include "ui/gfx/geometry/point.h" |
| #include "ui/gfx/geometry/point_f.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/gfx/geometry/rect_f.h" |
| #include "ui/gfx/geometry/size.h" |
| #include "ui/gfx/geometry/vector2d.h" |
| |
| #if BUILDFLAG(IS_WIN) |
| #include <windows.h> |
| #endif |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| #include "pdf/flatten_pdf_result.h" |
| #endif |
| |
| #if BUILDFLAG(ENABLE_PDF_INK2) |
| #include "pdf/pdf_ink_ids.h" |
| #include "pdf/pdf_ink_metrics_handler.h" |
| #include "third_party/ink/src/ink/geometry/partitioned_mesh.h" |
| #include "ui/gfx/geometry/transform.h" |
| #endif |
| |
| #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) |
| #include "pdf/pdfium/pdfium_searchify.h" |
| #include "services/screen_ai/public/mojom/screen_ai_service.mojom-forward.h" |
| #endif |
| |
| namespace blink { |
| class WebInputEvent; |
| class WebKeyboardEvent; |
| class WebMouseEvent; |
| class WebTouchEvent; |
| struct WebPrintParams; |
| } // namespace blink |
| |
| #if BUILDFLAG(ENABLE_PDF_INK2) |
| namespace base { |
| class TimeDelta; |
| } // namespace base |
| |
| namespace ink { |
| class Stroke; |
| } // namespace ink |
| #endif |
| |
| namespace chrome_pdf { |
| |
| class PDFiumDocument; |
| class PDFiumPermissions; |
| class Thumbnail; |
| enum class AccessibilityScrollAlignment; |
| struct AccessibilityActionData; |
| struct AccessibilityFocusInfo; |
| struct DocumentAttachmentInfo; |
| struct DocumentMetadata; |
| struct PageCharacterIndex; |
| |
| #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) |
| class PDFiumOnDemandSearchifier; |
| #endif |
| |
| namespace draw_utils { |
| class ShadowMatrix; |
| } // namespace draw_utils |
| |
| enum class FontMappingMode { |
| // Do not perform font mapping. |
| kNoMapping, |
| // Perform font mapping in renderer processes using Blink/content APIs. |
| kBlink, |
| }; |
| |
| enum class DocumentPermission { |
| kCopy, |
| kCopyAccessible, |
| kPrintLowQuality, |
| kPrintHighQuality, |
| }; |
| |
| // Do one time initialization of the SDK. |
| // If `enable_v8` is false, then PDFiumEngine will not be able to run |
| // JavaScript. |
| // When `use_skia` is true, the PDFiumEngine will use Skia renderer. Otherwise, |
| // it will use AGG renderer. |
| void InitializeSDK(bool enable_v8, |
| bool use_skia, |
| FontMappingMode font_mapping_mode); |
| // Tells the SDK that we're shutting down. |
| void ShutdownSDK(); |
| |
| using SendThumbnailCallback = base::OnceCallback<void(Thumbnail)>; |
| using AddSearchResultCallback = base::RepeatingCallback<void(PDFiumRange)>; |
| |
| // This class implements a PDF rendering engine using the PDFium library. |
| // |
| // Many methods in this class are virtual to facilitate testing. |
| class PDFiumEngine : public DocumentLoader::Client, |
| public IFSDK_PAUSE, |
| public PdfAnnotationAgent::Container, |
| public PdfCaretClient { |
| public: |
| // Maximum number of parameters a nameddest view can contain. |
| static constexpr size_t kMaxViewParams = 4; |
| |
| // State transition when tabbing forward: |
| // None -> Document -> Page -> None (when focusable annotations on all pages |
| // are done). |
| // Exposed for testing. |
| enum class FocusElementType { kNone, kDocument, kPage }; |
| |
| // Named destination in a document. |
| struct NamedDestination { |
| // 0-based page number. |
| unsigned long page; |
| |
| // View fit type (see table 8.2 "Destination syntax" on page 582 of PDF |
| // Reference 1.7). Empty string if not present. |
| std::string view; |
| |
| // Number of parameters for the view. |
| unsigned long num_params; |
| |
| // Parameters for the view. Their meaning depends on the `view` and their |
| // number is defined by `num_params` but is at most `kMaxViewParams`. Note: |
| // If a parameter stands for the x/y coordinates, it should be transformed |
| // into the corresponding screen coordinates before it's sent to the |
| // viewport. |
| std::array<float, kMaxViewParams> params; |
| |
| // A string of parameters for view fit type XYZ in the format of "x,y,zoom", |
| // where x and y parameters are the screen coordinates and zoom is the zoom |
| // level. If a parameter is "null", then current value of that parameter in |
| // the viewport should be retained. Note: This string is empty if the view's |
| // fit type is not XYZ. |
| std::string xyz_params; |
| }; |
| |
| // NOTE: `script_option` is ignored when PDF_ENABLE_V8 is not defined. |
| PDFiumEngine(PDFiumEngineClient* client, |
| PDFiumFormFiller::ScriptOption script_option); |
| PDFiumEngine(const PDFiumEngine&) = delete; |
| PDFiumEngine& operator=(const PDFiumEngine&) = delete; |
| ~PDFiumEngine() override; |
| |
| // Replaces the normal DocumentLoader for testing. Must be called before |
| // HandleDocumentLoad(). |
| void SetDocumentLoaderForTesting(std::unique_ptr<DocumentLoader> loader); |
| |
| // Returns the FontMappingMode set during PDFium SDK initialization. |
| static FontMappingMode GetFontMappingMode(); |
| |
| // Starts loading the document from `loader`. Follow-up requests (such as for |
| // partial loading) will use `original_url`. |
| bool HandleDocumentLoad(std::unique_ptr<UrlLoader> loader, |
| const std::string& original_url); |
| |
| // Most of these functions are similar to the Pepper functions of the same |
| // name, so not repeating the description here unless it's different. |
| virtual void PageOffsetUpdated(const gfx::Vector2d& page_offset); |
| virtual void PluginSizeUpdated(const gfx::Size& size); |
| virtual void ScrolledToXPosition(int position); |
| virtual void ScrolledToYPosition(int position); |
| // Paint is called a series of times. Before these n calls are made, PrePaint |
| // is called once. After Paint is called n times, PostPaint is called once. |
| void PrePaint(); |
| virtual void Paint(const gfx::Rect& rect, |
| SkBitmap& image_data, |
| std::vector<gfx::Rect>& ready, |
| std::vector<gfx::Rect>& pending); |
| void PostPaint(); |
| virtual bool HandleInputEvent(const blink::WebInputEvent& event); |
| void PrintBegin(); |
| virtual std::vector<uint8_t> PrintPages( |
| base::span<const int> page_indices, |
| const blink::WebPrintParams& print_params); |
| void PrintEnd(); |
| void StartFind(const std::u16string& text, bool case_sensitive); |
| bool SelectFindResult(bool forward); |
| void StopFind(); |
| virtual void ZoomUpdated(double new_zoom_level); |
| void RotateClockwise(); |
| void RotateCounterclockwise(); |
| bool IsReadOnly() const; |
| void SetReadOnly(bool read_only); |
| void SetDocumentLayout(DocumentLayout::PageSpread page_spread); |
| void DisplayAnnotations(bool display); |
| |
| // Returns the text contained on the given page. The caller is responsible for |
| // passing a valid `page_index`. |
| std::u16string GetPageText(int page_index); |
| |
| // Applies the document layout options proposed by a call to |
| // PDFiumEngineClient::ProposeDocumentLayout(), returning the overall size of |
| // the new effective layout. |
| virtual gfx::Size ApplyDocumentLayout(const DocumentLayout::Options& options); |
| |
| std::string GetSelectedText(); |
| // Returns true if focus is within an editable form text area. |
| virtual bool CanEditText() const; |
| |
| // Returns true if focus is within an editable form text area and the text |
| // area has text. |
| bool HasEditableText() const; |
| |
| // Replace selected text within an editable form text area with another |
| // string. If there is no selected text, append the replacement text after the |
| // current caret position. |
| void ReplaceSelection(const std::string& text); |
| |
| // Methods to check if undo/redo is possible, and to perform them. |
| bool CanUndo() const; |
| bool CanRedo() const; |
| void Undo(); |
| void Redo(); |
| |
| // Handles actions invoked by Accessibility clients. |
| void HandleAccessibilityAction(const AccessibilityActionData& action_data); |
| |
| std::string GetLinkAtPosition(const gfx::PointF& point); |
| |
| // Checks the permissions associated with this document. |
| virtual bool HasPermission(DocumentPermission permission) const; |
| |
| virtual void SelectAll(); |
| |
| // Gets the list of DocumentAttachmentInfo from the document. |
| virtual const std::vector<DocumentAttachmentInfo>& |
| GetDocumentAttachmentInfoList() const; |
| |
| // Gets the content of an attachment by the attachment's `index`. `index` |
| // must be in the range of [0, attachment_count-1), where `attachment_count` |
| // is the number of attachments embedded in the document. |
| // The caller of this method is responsible for checking whether the |
| // attachment is readable, attachment size is not 0 byte, and the return |
| // value's size matches the corresponding DocumentAttachmentInfo's |
| // `size_bytes`. |
| std::vector<uint8_t> GetAttachmentData(size_t index); |
| |
| // Gets metadata about the document. |
| virtual const DocumentMetadata& GetDocumentMetadata() const; |
| |
| // Gets the number of pages in the document. |
| virtual int GetNumberOfPages() const; |
| |
| // Returns a list of Values of Bookmarks. Each Bookmark is a dictionary Value |
| // which contains the following key/values: |
| // - "title" - a string Value. |
| // - "page" - an int Value. |
| // - "children" - a list of Values, with each entry containing |
| // a dictionary Value of the same structure. |
| virtual base::Value::List GetBookmarks(); |
| |
| // Gets the named destination by name. |
| std::optional<NamedDestination> GetNamedDestination( |
| const std::string& destination); |
| |
| // Gets the index of the most visible page, or -1 if none are visible. |
| int GetMostVisiblePage(); |
| |
| // Returns whether the page at `page_index` is visible or not. |
| virtual bool IsPageVisible(int page_index) const; |
| |
| // Gets the current layout orientation. |
| PageOrientation GetCurrentOrientation() const; |
| |
| // Gets the rectangle of the page excluding any additional areas. |
| virtual gfx::Rect GetPageContentsRect(int page_index); |
| |
| // Returns a page's rect in screen coordinates, as well as its surrounding |
| // border areas and bottom separator. |
| virtual gfx::Rect GetPageScreenRect(int page_index) const; |
| |
| // Set color / grayscale rendering modes. |
| virtual void SetGrayscale(bool grayscale); |
| |
| // Gets the PDF document's print scaling preference. True if the document can |
| // be scaled to fit. |
| bool GetPrintScaling(); |
| |
| // Returns number of copies to be printed. |
| int GetCopiesToPrint(); |
| |
| // Returns the duplex setting. |
| printing::mojom::DuplexMode GetDuplexMode(); |
| |
| // Gets the size of the page in points for the page at `page_index`. Any |
| // fractional portion of the size is retained in the result. Returns |
| // `std::nullopt` if the indicated page index is not available. |
| virtual std::optional<gfx::SizeF> GetPageSizeInPoints(int page_index) const; |
| |
| // Returns the uniform page size of the document in points. Returns |
| // `std::nullopt` if the document has more than one page size. |
| virtual std::optional<gfx::Size> GetUniformPageSizePoints(); |
| |
| // Append blank pages to make a 1-page document to a `num_pages` document. |
| // Always retain the first page data. |
| void AppendBlankPages(size_t num_pages); |
| |
| // Append the first page of the document loaded with the `engine` to this |
| // document at page `index`. |
| void AppendPage(PDFiumEngine* engine, int index); |
| |
| virtual std::vector<uint8_t> GetSaveData(); |
| |
| virtual void SetCaretPosition(const gfx::Point& position); |
| |
| void MoveRangeSelectionExtent(const gfx::Point& extent); |
| |
| void SetSelectionBounds(const gfx::Point& base, const gfx::Point& extent); |
| |
| std::optional<Selection> GetSelection() const; |
| |
| // Remove focus from form widgets, consolidating the user input. |
| void KillFormFocus(); |
| |
| // Notify whether the PDF currently has the focus or not. |
| void UpdateFocus(bool has_focus); |
| |
| // Returns the focus info of current focus item. |
| AccessibilityFocusInfo GetFocusInfo(); |
| |
| // Returns whether the "/Marked" attribute in the "MarkInfo" dictionary in the |
| // PDF's catalog is set to true. This should indicate whether the PDF includes |
| // a tree of structural elements which describe the logical organization of |
| // the document, e.g. into sections and headings, and describe special |
| // elements, e.g. headings and table cells. |
| virtual bool IsPDFDocTagged() const; |
| |
| virtual uint32_t GetLoadedByteSize(); |
| |
| // Copies data from `doc_loader_` into `buffer` starting from `offset`. |
| // - `buffer` is completely filled, so its size should be less than or equal |
| // to GetLoadedByteSize() - `offset`. |
| // |
| // Returns true on success and writes into `buffer. Returns false on failure. |
| virtual bool ReadLoadedBytes(uint32_t offset, base::span<uint8_t> buffer); |
| |
| // Requests rendering the page at `page_index` as a thumbnail at a given |
| // `device_pixel_ratio`. Runs `send_callback` with the rendered thumbnail. |
| // |
| // - The callback is asynchronous because the request may be delayed if the |
| // page is not ready to be rendered. |
| // - Modifications made with ApplyStroke() are not included in the thumbnail. |
| // |
| // Virtual to support testing. |
| virtual void RequestThumbnail(int page_index, |
| float device_pixel_ratio, |
| SendThumbnailCallback send_callback); |
| #if BUILDFLAG(ENABLE_PDF_INK2) |
| // Virtual to support testing. |
| virtual gfx::Size GetThumbnailSize(int page_index, float device_pixel_ratio); |
| |
| // Writes the supplied stroke for the page at `page_index`. The same `id` |
| // gets used with `UpdateStrokeUsage()`. Must provide a valid `page_index`. |
| // Virtual to support testing. |
| virtual void ApplyStroke(int page_index, |
| InkStrokeId id, |
| const ink::Stroke& stroke); |
| |
| // Modifies an existing stroke identified by `id` on the page at `page_index` |
| // to become either active or inactive. The caller must pass the same |
| // consistent and valid `page_index`/`id` pair as was provided to |
| // `ApplyStroke()`. |
| // Stroke objects that become inactive will no longer be included for |
| // rendering or saving out to PDF data. Their inclusion can be restored if |
| // another call makes them active again. Virtual to support testing. |
| virtual void UpdateStrokeActive(int page_index, InkStrokeId id, bool active); |
| |
| // Removes an existing stroke identified by `id`. The caller must pass the |
| // same consistent and valid `page_index/`id` pair as was provided to |
| // `ApplyStroke()`. Virtual to support testing. |
| virtual void DiscardStroke(int page_index, InkStrokeId id); |
| |
| // Returns whether any of the pages contains a "V2" path created by Ink or |
| // unknown if unable to find any "V2" paths within `timeout`. Virtual to |
| // support testing. |
| virtual PDFLoadedWithV2InkAnnotations ContainsV2InkPath( |
| const base::TimeDelta& timeout) const; |
| |
| // Loads "V2" Ink paths from a page in the PDF identified by `page_index`. The |
| // `page_index` must be in bounds. |
| // |
| // Returns a mapping to identify shapes by IDs. In `this`, store a mapping |
| // from IDs to PDFium page objects. This allows the caller to associate shapes |
| // with their corresponding PDFium page objects, without any direct exposure |
| // to PDFium types. |
| // |
| // It is the caller's responsibility to not call this multiple times per page, |
| // or else there will be multiple IDs associated with the same underlying |
| // PDFium page object. |
| // |
| // Virtual to support testing. |
| virtual std::map<InkModeledShapeId, ink::PartitionedMesh> |
| LoadV2InkPathsForPage(int page_index); |
| |
| // Modifies an existing shape identified by `id` on the page at `page_index` |
| // to become either active or inactive. The caller must pass the same |
| // consistent and valid `page_index`/`id` pair as was provided by |
| // `LoadV2InkPathsForPage()`. |
| // Shape objects that become inactive will no longer be included for |
| // rendering or saving out to PDF data. Their inclusion can be restored if |
| // another call makes them active again. |
| // |
| // Virtual to support testing. |
| virtual void UpdateShapeActive(int page_index, |
| InkModeledShapeId id, |
| bool active); |
| |
| // Regenerate contents for all pages that need it due to Ink strokes. |
| void RegenerateContents(); |
| |
| // Extends the current text selection to the nearest page and character to |
| // `point`. Returns whether any text is being selected after extending. |
| // `point` must be in device coordinates. Virtual to support testing. |
| virtual bool ExtendSelectionByPoint(const gfx::PointF& point); |
| |
| // Returns the transform required to convert canonical coordinates to PDF |
| // coordinates. Virtual to support testing. |
| virtual gfx::Transform GetCanonicalToPdfTransform(int page_index); |
| |
| // Returns all current text selection rects in PDF coordinates, indexed by |
| // their page indices. The rects have tighter bounds than normal, so they can |
| // be used with Ink Strokes to generate less highlight overlap. |
| // Virtual to support testing. |
| virtual std::map<int, std::vector<PdfRect>> GetSelectionRectMap(); |
| |
| // Returns whether `point` is within a selectable text area or within a link |
| // area, excluding form fields. `point` must be in device coordinates. Virtual |
| // to support testing. |
| virtual bool IsSelectableTextOrLinkArea(const gfx::PointF& point); |
| |
| // Handles a text or link area being clicked at `point`, `click_count` times. |
| // The area must selectable, otherwise a crash occurs. `point` must be in |
| // device coordinates. Virtual to support testing. |
| virtual void OnTextOrLinkAreaClick(const gfx::PointF& point, int click_count); |
| |
| const std::map<InkModeledShapeId, FPDF_PAGEOBJECT>& |
| ink_modeled_shape_map_for_testing() const { |
| return ink_modeled_shape_map_; |
| } |
| |
| const std::map<int, PDFiumPage::ScopedUnloadPreventer>& |
| stroked_pages_unload_preventers_for_testing() const { |
| return stroked_pages_unload_preventers_; |
| } |
| #endif // BUILDFLAG(ENABLE_PDF_INK2) |
| |
| // DocumentLoader::Client: |
| std::unique_ptr<URLLoaderWrapper> CreateURLLoader() override; |
| void OnPendingRequestComplete() override; |
| void OnNewDataReceived() override; |
| void OnDocumentComplete() override; |
| void OnDocumentCanceled() override; |
| |
| // PdfCaretClient: |
| void ClearTextSelection() override; |
| void ExtendAndInvalidateSelectionByChar( |
| const PageCharacterIndex& index) override; |
| uint32_t GetCharCount(uint32_t page_index) const override; |
| std::vector<gfx::Rect> GetScreenRectsForCaret( |
| const PageCharacterIndex& index) const override; |
| void InvalidateRect(const gfx::Rect& rect) override; |
| bool IsSelecting() const override; |
| bool IsSynthesizedNewline(const PageCharacterIndex& index) const override; |
| bool PageIndexInBounds(int index) const override; |
| void ScrollToChar(const PageCharacterIndex& index) override; |
| void StartSelection(const PageCharacterIndex& index) override; |
| |
| // `PdfAnnotationAgent::Container`: |
| bool FindAndHighlightTextFragments( |
| base::span<const std::string> text_fragments) override; |
| void ScrollTextFragmentIntoView() override; |
| void RemoveTextFragments() override; |
| |
| #if defined(PDF_ENABLE_XFA) |
| void UpdatePageCount(); |
| #endif // defined(PDF_ENABLE_XFA) |
| |
| #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) |
| // Starts the searchify process and passes two callbacks to functions that |
| // return the maximum image dimension and performs OCR. |
| // This function is expected to be called only once. |
| void StartSearchify(GetOcrMaxImageDimensionCallbackAsync get_max_dimension, |
| PerformOcrCallbackAsync perform_ocr_callback); |
| |
| // Returns a function to pass OCR disconnection events to the searchifier. |
| base::RepeatingClosure GetOcrDisconnectHandler(); |
| |
| // Tells if the page is waiting to be searchified. |
| bool IsPageScheduledForSearchify(int page_index) const; |
| |
| // Schedules searchify for the page if it has no text. `page` must be non-null |
| // and in an available state. |
| void ScheduleSearchifyIfNeeded(PDFiumPage* page); |
| |
| // Notifies that PDF searchifier has switched between busy or not busy. |
| // A busy state is when it has some queued pages to process or is processing a |
| // page at the moment. It comes out of this state either when all tasks are |
| // completed or canceled. |
| void OnSearchifyStateChange(bool busy); |
| |
| // Called when searchify text is added. |
| void OnHasSearchifyText(); |
| |
| PDFiumOnDemandSearchifier* GetSearchifierForTesting() { |
| return searchifier_.get(); |
| } |
| |
| // Tells if the page is in `progressive_paints_` |
| bool IsPageScheduledForPaint(uint32_t page_index) const; |
| |
| // Unloads the page if it is not visible or prevented from unloading. |
| void MaybeUnloadPage(int page_index); |
| #endif // BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) |
| |
| void UnsupportedFeature(const std::string& feature); |
| |
| FPDF_AVAIL fpdf_availability() const; |
| FPDF_DOCUMENT doc() const; |
| FPDF_FORMHANDLE form() const; |
| |
| // Returns the PDFiumPage pointer of a given index. Returns nullptr if `index` |
| // is out of range. |
| PDFiumPage* GetPage(size_t index); |
| |
| bool IsValidLink(const std::string& url); |
| |
| // Sets whether form highlight should be enabled or cleared. |
| virtual void SetFormHighlight(bool enable_form); |
| |
| // Scrolls to and highlights the first entry in `text_fragment_highlights_`. |
| // Only valid if `text_fragment_highlights_` is non-empty (gated by a CHECK). |
| // `force_smooth_scroll` forces smooth scrolling regardless of the current |
| // animation settings. |
| virtual void ScrollToFirstTextFragment(bool force_smooth_scroll); |
| |
| // Searches for a text fragment within the text of the PDF. |
| void SearchForFragment(const std::u16string& term, |
| int character_to_start_searching_from, |
| int last_character_index_to_search, |
| int page_to_search, |
| AddSearchResultCallback add_result_callback); |
| |
| // Sets whether caret browsing is enabled or not. Initializes `caret_` if it |
| // is the first time enabling caret browsing mode. Virtual to support testing. |
| virtual void SetCaretBrowsingEnabled(bool enabled); |
| |
| private: |
| // This is a base class for shared functions and data needed for change |
| // invalidators. Subclasses are used to detect the difference in change rects |
| // between construction and destruction. At destruction, it invalidates all |
| // the tracked rects that changed. |
| class ChangeInvalidator { |
| protected: |
| explicit ChangeInvalidator(PDFiumEngine* engine); |
| virtual ~ChangeInvalidator(); |
| |
| // Gets all visible rects for the tracked changes. |
| virtual std::vector<gfx::Rect> GetVisibleChangeRects() const = 0; |
| |
| // Gets all of the visible screen rects from a list of `ranges`. |
| std::vector<gfx::Rect> GetVisibleScreenRectsFromRanges( |
| base::span<const PDFiumRange> ranges) const; |
| |
| // Invalidates all `screen_rects`, but with each rect slightly expanded to |
| // compensate for any rounding errors. Skips any empty rects. Returns |
| // whether any rect invalidation occurred. |
| bool Invalidate(base::span<const gfx::Rect> screen_rects); |
| |
| // Invalidates all rects added or removed between construction and |
| // destruction. Returns whether any invalidation occurred. |
| bool InvalidateChangesOnDestruct(); |
| |
| // Must be non-nullptr. |
| const raw_ptr<PDFiumEngine> engine_; |
| // The origin at the time this object was constructed. |
| const gfx::Point previous_origin_; |
| |
| // Screen rectangles that were highlighted on construction. |
| std::vector<gfx::Rect> previous_rects_; |
| }; |
| |
| // Tracks and invalidates text selection changes. |
| class SelectionChangeInvalidator : public ChangeInvalidator { |
| public: |
| explicit SelectionChangeInvalidator(PDFiumEngine* engine); |
| ~SelectionChangeInvalidator() override; |
| |
| private: |
| std::vector<gfx::Rect> GetVisibleChangeRects() const override; |
| }; |
| |
| // Tracks and invalidates find result changes. |
| class FindResultChangeInvalidator : public ChangeInvalidator { |
| public: |
| explicit FindResultChangeInvalidator(PDFiumEngine* engine); |
| ~FindResultChangeInvalidator() override; |
| |
| private: |
| std::vector<gfx::Rect> GetVisibleChangeRects() const override; |
| }; |
| |
| // Tracks and invalidates text fragment highlight changes. |
| class HighlightChangeInvalidator : public ChangeInvalidator { |
| public: |
| explicit HighlightChangeInvalidator(PDFiumEngine* engine); |
| ~HighlightChangeInvalidator() override; |
| |
| private: |
| std::vector<gfx::Rect> GetVisibleChangeRects() const override; |
| }; |
| |
| // Used to store mouse down state to handle it in other mouse event handlers. |
| class MouseDownState { |
| public: |
| MouseDownState(const PDFiumPage::Area& area, |
| const PDFiumPage::LinkTarget& target); |
| MouseDownState(const MouseDownState&) = delete; |
| MouseDownState& operator=(const MouseDownState&) = delete; |
| ~MouseDownState(); |
| |
| void Set(const PDFiumPage::Area& area, |
| const PDFiumPage::LinkTarget& target); |
| void Reset(); |
| bool Matches(const PDFiumPage::Area& area, |
| const PDFiumPage::LinkTarget& target) const; |
| |
| private: |
| PDFiumPage::Area area_; |
| PDFiumPage::LinkTarget target_; |
| }; |
| |
| struct PointData { |
| PDFiumPage::Area area = PDFiumPage::NONSELECTABLE_AREA; |
| int page_index = -1; |
| int char_index = -1; |
| PdfRect char_bounds; |
| int form_type = FPDF_FORMFIELD_UNKNOWN; |
| PDFiumPage::LinkTarget target; |
| gfx::PointF pdf_point; |
| }; |
| |
| friend class FormFillerTest; |
| friend class PDFiumDrawSelectionTestBase; |
| friend class PDFiumEngineTabbingTest; |
| friend class PDFiumEngineTest; |
| friend class PDFiumFormFiller; |
| friend class PDFiumTestBase; |
| friend class SelectionChangeInvalidator; |
| |
| gfx::Size plugin_size() const; |
| |
| // We finished getting the pdf file, so load it. This will complete |
| // asynchronously (due to password fetching) and may be run multiple times. |
| void LoadDocument(); |
| |
| // Try loading the document. Returns true if the document is successfully |
| // loaded or is already loaded otherwise it will return false. If there is a |
| // password, then `password` is non-empty. If the document could not be loaded |
| // and needs a password, `needs_password` will be set to true. |
| bool TryLoadingDoc(const std::string& password, bool* needs_password); |
| |
| // Asks the user for the document password and then continue loading the |
| // document. |
| void GetPasswordAndLoad(); |
| |
| // Called when the password has been retrieved. |
| void OnGetPasswordComplete(const std::string& password); |
| |
| // Continues loading the document when the password has been retrieved, or if |
| // there is no password. If there is no password, then `password` is empty. |
| void ContinueLoadingDocument(const std::string& password); |
| |
| // Finishes loading the document. Recalculate the document size if there were |
| // pages that were not previously available. |
| // Also notifies the client that the document has been loaded. |
| // This should only be called after `doc_` has been loaded and the document is |
| // fully downloaded. |
| // If this has been run once, it will not notify the client again. |
| void FinishLoadingDocument(); |
| |
| // Loads information about the pages in the document and performs layout. |
| void LoadPageInfo(); |
| |
| // Refreshes the document layout using the current pages and layout options. |
| void RefreshCurrentDocumentLayout(); |
| |
| // Proposes the next document layout using the current pages and |
| // `desired_layout_options_`. |
| void ProposeNextDocumentLayout(); |
| |
| // Updates `layout` using the current page sizes. |
| void UpdateDocumentLayout(DocumentLayout* layout); |
| |
| // Loads information about the pages in the document, calculating and |
| // returning the individual page sizes. |
| // |
| // Note that the page rects of any new pages will be left uninitialized, so |
| // layout must be performed immediately after calling this method. |
| // |
| // TODO(kmoon): LoadPageSizes() is a bit misnomer, but LoadPageInfo() is |
| // taken right now... |
| std::vector<gfx::Size> LoadPageSizes( |
| const DocumentLayout::Options& layout_options); |
| |
| void LoadBody(); |
| |
| void LoadPages(); |
| |
| void LoadForm(); |
| |
| // Checks whether the document is optimized by linearization. |
| bool IsLinearized(); |
| |
| // Calculates which pages should be displayed right now. |
| void CalculateVisiblePages(); |
| |
| // Internal interface that caches the page index requested by PDFium to get |
| // scrolled to. The cache is to be be used during the interval the PDF |
| // plugin has not finished handling the scroll request. |
| void ScrollToPage(int page); |
| |
| // Checks if a page is now available, and if so marks it as such and returns |
| // true. Otherwise, it will return false and will add the index to the given |
| // array if it's not already there. |
| bool CheckPageAvailable(uint32_t index, std::vector<uint32_t>* pending); |
| |
| // Helper function to get a given page's size in pixels. Converting from |
| // points to pixels are rounded down as part of generating integer values. |
| // This is not part of PDFiumPage because we might not have that structure |
| // when we need this. |
| gfx::Size GetPageSize(int index); |
| gfx::Size GetPageSizeForLayout(int index, |
| const DocumentLayout::Options& layout_options); |
| |
| // Helper function for getting the inset sizes for the current layout. If |
| // two-up view is enabled, the configuration of inset sizes depends on |
| // the position of the page, specified by `page_index` and `num_of_pages`. |
| gfx::Insets GetInsets(const DocumentLayout::Options& layout_options, |
| size_t page_index, |
| size_t num_of_pages) const; |
| |
| // If two-up view is enabled, returns the index of the page beside |
| // `page_index` page. Returns std::nullopt if there is no adjacent page or |
| // if two-up view is disabled. |
| std::optional<size_t> GetAdjacentPageIndexForTwoUpView( |
| size_t page_index, |
| size_t num_of_pages) const; |
| |
| std::vector<gfx::Rect> GetAllScreenRectsUnion( |
| base::span<const PDFiumRange> rect_range, |
| const gfx::Point& point) const; |
| |
| void UpdateTickMarks(); |
| |
| // Called to continue searching so we don't block the main thread. |
| void ContinueFind(bool case_sensitive); |
| |
| // Inserts a find result into `find_results_`, which is sorted. |
| void AddFindResult(PDFiumRange result); |
| |
| // Returns the current find selection, otherwise returns nullptr if there is |
| // no find selection. |
| const PDFiumRange* GetFindSelection() const; |
| |
| // Search a page ourself using ICU. |
| void SearchUsingICU(const std::u16string& term, |
| bool case_sensitive, |
| bool first_search, |
| int character_to_start_searching_from, |
| int last_character_index_to_search, |
| int current_page, |
| int last_page_to_search, |
| AddSearchResultCallback add_result_callback); |
| |
| // Input event handlers. |
| bool OnMouseDown(const blink::WebMouseEvent& event); |
| bool OnMouseUp(const blink::WebMouseEvent& event); |
| bool OnMouseMove(const blink::WebMouseEvent& event); |
| void OnMouseEnter(const blink::WebMouseEvent& event); |
| bool OnKeyDown(const blink::WebKeyboardEvent& event); |
| bool OnKeyUp(const blink::WebKeyboardEvent& event); |
| bool OnChar(const blink::WebKeyboardEvent& event); |
| |
| // Decide what cursor should be displayed. |
| ui::mojom::CursorType DetermineCursorType(PDFiumPage::Area area, |
| int form_type) const; |
| |
| bool ExtendSelection(const PointData& point_data); |
| |
| // Returns whether the text selection was extended to `index`. |
| bool ExtendSelectionByChar(const PageCharacterIndex& index); |
| |
| std::vector<uint8_t> PrintPagesAsRasterPdf( |
| base::span<const int> page_indices, |
| const blink::WebPrintParams& print_params); |
| |
| std::vector<uint8_t> PrintPagesAsPdf( |
| base::span<const int> page_indices, |
| const blink::WebPrintParams& print_params); |
| |
| // Checks if `page` has selected text in a form element. If so, sets that as |
| // the plugin's text selection. |
| void SetFormSelectedText(FPDF_FORMHANDLE form_handle, FPDF_PAGE page); |
| |
| // Returns information about `point` and the objects at that point. |
| // `point` is in device coordinates. |
| PointData GetPointData(const gfx::PointF& point); |
| |
| // Helper that returns `point_data.char_index`, possibly with an adjustment, |
| // based on the relative position of the point to the character. |
| int GetCharIndexBasedOnPointData(const PointData& point_data); |
| |
| void OnSingleClick(int page_index, int char_index); |
| void OnMultipleClick(int click_count, int page_index, int char_index); |
| // Internal version of `OnTextOrLinkAreaClick()` that takes a PointData |
| // instead of a point. |
| void OnTextOrLinkAreaClickInternal(const PointData& point_data, |
| int click_count); |
| |
| bool OnLeftMouseDown(const blink::WebMouseEvent& event); |
| bool OnMiddleMouseDown(const blink::WebMouseEvent& event); |
| bool OnRightMouseDown(const blink::WebMouseEvent& event); |
| |
| // Starts a progressive paint operation given a rectangle in screen |
| // coordinates. Returns the index in `progressive_paints_`. |
| size_t StartPaint(uint32_t page_index, const gfx::Rect& dirty); |
| |
| // Continues a paint operation that was started earlier. Returns true if the |
| // paint is done, or false if it needs to be continued. |
| bool ContinuePaint(size_t progressive_index, SkBitmap& image_data); |
| |
| // Called once PDFium is finished rendering a page so that we draw our |
| // borders, highlighting etc. |
| void FinishPaint(size_t progressive_index, SkBitmap& image_data); |
| |
| // Stops any paints that are in progress. |
| void CancelPaints(); |
| |
| // Invalidates all pages. Use this when some global parameter, such as page |
| // orientation, has changed. |
| void InvalidateAllPages(); |
| |
| // If the page is narrower than the document size, paint the extra space |
| // with the page background. |
| void FillPageSides(int progressive_index); |
| |
| void PaintPageShadow(size_t progressive_index, SkBitmap& image_data); |
| |
| // Draw the text caret. No-op if `caret_` is nullptr. |
| void DrawCaret(size_t progressive_index, SkBitmap& image_data) const; |
| |
| // Highlight visible find results and selections. |
| void DrawSelections(size_t progressive_index, SkBitmap& image_data) const; |
| |
| // Paints an page that hasn't finished downloading. |
| void PaintUnavailablePage(int page_index, |
| const gfx::Rect& dirty, |
| SkBitmap& image_data); |
| |
| // Given a page index, returns the corresponding index in |
| // `progressive_paints_`, or nullopt if it does not exist. |
| std::optional<size_t> GetProgressiveIndex(uint32_t page_index) const; |
| |
| // Creates a FPDF_BITMAP from a rectangle in screen coordinates. |
| ScopedFPDFBitmap CreateBitmap(const gfx::Rect& rect, |
| bool has_alpha, |
| SkBitmap& image_data) const; |
| |
| // Given a rectangle in screen coordinates, returns the coordinates in the |
| // units that PDFium rendering functions expect. |
| gfx::Rect GetPDFiumRect(int page_index, const gfx::Rect& rect) const; |
| |
| // Returns the rendering flags to pass to PDFium. |
| int GetRenderingFlags() const; |
| |
| // Returns the currently visible rectangle in document coordinates. |
| gfx::Rect GetVisibleRect() const; |
| |
| // Given `rect` in document coordinates, returns the rectangle in screen |
| // coordinates. (i.e. 0,0 is top left corner of plugin area) |
| gfx::Rect GetScreenRect(const gfx::Rect& rect) const; |
| |
| // Returns screen rects for a caret at the top-left of the no-text PDF page, |
| // or an empty vector if the caret cannot fit on the page. |
| std::vector<gfx::Rect> GetNoTextPageScreenRectsForCaret( |
| PDFiumPage* page) const; |
| |
| // Given an image `region`, highlights `rect`. |
| // `highlighted_rects` contains the already highlighted rectangles and will be |
| // updated to include `rect` if `rect` has not already been highlighted. |
| void Highlight(const RegionData& region, |
| const gfx::Rect& rect, |
| SkColor color, |
| std::vector<gfx::Rect>& highlighted_rects) const; |
| |
| // Helper function to convert device coordinates to PDF coordinates. If the |
| // page is not yet loaded, returns (0, 0). |
| gfx::PointF DeviceToPdf(uint32_t page_index, const gfx::PointF& device_point); |
| |
| // Helper function to convert device coordinates to screen coordinates. |
| // Normalizes `device_point` based on `position_` and `current_zoom_`. |
| gfx::Point DeviceToScreen(const gfx::PointF& device_point) const; |
| |
| // Helper function to get the index of a given FPDF_PAGE. Returns -1 if not |
| // found. |
| int GetVisiblePageIndex(FPDF_PAGE page); |
| |
| // Helper function to change the current page, running page open/close |
| // triggers as necessary. |
| void SetCurrentPage(int index); |
| |
| void DrawPageShadow(const gfx::Rect& page_rect, |
| const gfx::Rect& shadow_rect, |
| const gfx::Rect& clip_rect, |
| SkBitmap& image_data); |
| |
| // Draws the highlight for the provided `range` if visible. |
| void DrawHighlightOnPage(const PDFiumRange& range, |
| const gfx::Rect& dirty_in_screen, |
| const gfx::Rect& visible_rect, |
| const RegionData& region, |
| SkColor color, |
| std::vector<gfx::Rect>& highlighted_rects) const; |
| |
| std::optional<RegionData> GetRegion(const gfx::Point& location, |
| SkBitmap& image_data) const; |
| |
| // Called when the selection changes. |
| void OnSelectionTextChanged(); |
| void OnSelectionPositionChanged(); |
| |
| // Sets text selection status of document. This does not include text |
| // within form text fields. |
| void SetSelecting(bool selecting); |
| |
| // Sets the type of field that has focus. |
| void SetFieldFocus(PDFiumEngineClient::FocusFieldType type); |
| |
| // Sets whether or not left mouse button is currently being held down. |
| void SetMouseLeftButtonDown(bool is_mouse_left_button_down); |
| |
| // Given an annotation which is a form of `form_type` which is known to be a |
| // form text area, check if it is an editable form text area. |
| bool IsAnnotationAnEditableFormTextArea(FPDF_ANNOTATION annot, |
| int form_type) const; |
| |
| bool IsPageCharacterIndexInBounds(const PageCharacterIndex& index) const; |
| |
| void ScheduleTouchTimer(const blink::WebTouchEvent& event); |
| void KillTouchTimer(); |
| void HandleLongPress(const blink::WebTouchEvent& event); |
| |
| // Returns a dictionary representing a bookmark, which in turn contains child |
| // dictionaries representing the child bookmarks. If `bookmark` is null, then |
| // this method traverses from the root of the bookmarks tree. Note that the |
| // root bookmark contains no useful information. |
| base::Value::Dict TraverseBookmarks(FPDF_BOOKMARK bookmark, |
| unsigned int depth); |
| |
| void ScrollBasedOnScrollAlignment( |
| const gfx::Rect& scroll_rect, |
| const AccessibilityScrollAlignment& horizontal_scroll_alignment, |
| const AccessibilityScrollAlignment& vertical_scroll_alignment); |
| |
| // Scrolls top left of a rect in page `target_rect` to `global_point`. |
| // Global point is point relative to viewport in screen. |
| void ScrollToGlobalPoint(const gfx::Rect& target_rect, |
| const gfx::Point& global_point); |
| |
| // Set if the document has any local edits. |
| void EnteredEditMode(); |
| |
| // Navigates to a link destination depending on the type of destination. |
| // Returns false if `area` is not a link. |
| bool NavigateToLinkDestination(PDFiumPage::Area area, |
| const PDFiumPage::LinkTarget& target, |
| WindowOpenDisposition disposition); |
| |
| // IFSDK_PAUSE callbacks |
| static FPDF_BOOL Pause_NeedToPauseNow(IFSDK_PAUSE* param); |
| |
| // Used for text selection. Given the start and end of selection, sets the |
| // text range in `selection_`. |
| void SetSelection(const PageCharacterIndex& selection_start_index, |
| const PageCharacterIndex& selection_end_index); |
| |
| void SaveSelection(); |
| void RestoreSelection(); |
| |
| // Scroll the current focused annotation into view if not already in view. |
| void ScrollFocusedAnnotationIntoView(); |
| |
| // Given `annot`, scroll the `annot` into view if not already in view. |
| void ScrollAnnotationIntoView(FPDF_ANNOTATION annot, int page_index); |
| |
| // Scrolls to the bounding rectangles that represent the `range` on the |
| // screen. `force_smooth_scroll` forces smooth scrolling regardless of the |
| // current animation settings. |
| void ScrollToBoundingRects(const PDFiumRange& range, |
| bool force_smooth_scroll); |
| |
| void OnFocusedAnnotationUpdated(FPDF_ANNOTATION annot, int page_index); |
| |
| // Read the attachments' information inside the PDF document, and set |
| // `doc_attachment_info_list_`. To be called after the document is loaded. |
| void LoadDocumentAttachmentInfoList(); |
| |
| // Fetches and populates the fields of `doc_metadata_`. To be called after the |
| // document is loaded. |
| void LoadDocumentMetadata(); |
| |
| // This is a layer between OnKeyDown() and actual tab handling to facilitate |
| // testing. |
| bool HandleTabEvent(int modifiers); |
| |
| // Helper functions to handle tab events. |
| bool HandleTabEventWithModifiers(int modifiers); |
| bool HandleTabForward(int modifiers); |
| bool HandleTabBackward(int modifiers); |
| |
| // Updates the currently focused object stored in `focus_element_type_`. |
| // Notifies `client_` about document focus change, if any. |
| void UpdateFocusElementType(FocusElementType focus_element_type); |
| |
| void UpdateLinkUnderCursor(const std::string& target_url); |
| void SetLinkUnderCursorForAnnotation(FPDF_ANNOTATION annot, int page_index); |
| |
| // Checks whether a given `page_index` exists in `pending_thumbnails_`. If so, |
| // requests the thumbnail for that page. |
| void MaybeRequestPendingThumbnail(int page_index); |
| |
| #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) |
| // Called if OCR service gets disconnected. |
| void OnOcrDisconnected(); |
| #endif |
| |
| #if BUILDFLAG(ENABLE_PDF_INK2) |
| std::vector<FPDF_PAGEOBJECT> GetActiveInkPageObjectsForPage( |
| int page_index) const; |
| #endif |
| |
| const raw_ptr<PDFiumEngineClient> client_; |
| |
| // The current document layout. |
| DocumentLayout layout_; |
| |
| // The options for the desired document layout. |
| DocumentLayout::Options desired_layout_options_; |
| |
| // The scroll position in screen coordinates. |
| gfx::Point position_; |
| // The offset of the page into the viewport. |
| gfx::Vector2d page_offset_; |
| // The plugin size in screen coordinates. |
| std::optional<gfx::Size> plugin_size_; |
| double current_zoom_ = 1.0; |
| // The caret position and bound in plugin viewport coordinates. |
| gfx::Rect caret_rect_; |
| |
| std::unique_ptr<DocumentLoader> doc_loader_; // Main document's loader. |
| bool doc_loader_set_for_testing_ = false; |
| |
| // Set to true if the user is being prompted for their password. Will be set |
| // to false after the user finishes getting their password. |
| bool getting_password_ = false; |
| int password_tries_remaining_ = 0; |
| |
| // Needs to be above pages_, as destroying a page may call some methods of |
| // form filler. |
| PDFiumFormFiller form_filler_; |
| |
| #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) |
| std::unique_ptr<PDFiumOnDemandSearchifier> searchifier_; |
| |
| // Keeps track of the indices of pages for which "PDF.PageHasText" metric is |
| // reported. |
| std::set<int> page_has_text_metric_reported_; |
| |
| // Records if at least one page has searchify text. |
| bool has_searchify_text_ = false; |
| #endif |
| |
| std::unique_ptr<PDFiumDocument> document_; |
| bool document_pending_ = false; |
| bool document_loaded_ = false; |
| |
| // The page(s) of the document. |
| std::vector<std::unique_ptr<PDFiumPage>> pages_; |
| |
| // The indexes of the pages currently visible. |
| std::vector<uint32_t> visible_pages_; |
| |
| // The indexes of the pages pending download. |
| std::vector<uint32_t> pending_pages_; |
| |
| // During handling of input events we don't want to unload any pages in |
| // callbacks to us from PDFium, since the current page can change while PDFium |
| // code still has a pointer to it. |
| bool defer_page_unload_ = false; |
| std::vector<int> deferred_page_unloads_; |
| |
| // Used for text selection, but does not include text within form text areas. |
| // There could be more than one range if selection spans more than one page. |
| std::vector<PDFiumRange> selection_; |
| |
| // When rotating the page or updating the PageSpread mode, used to store the |
| // contents of `selection_`. After the page change is completed, the contents |
| // of `selection_` are restored. |
| std::vector<PDFiumRange> saved_selection_; |
| |
| // True if we're in the middle of text selection. |
| bool selecting_ = false; |
| |
| MouseDownState mouse_down_state_; |
| |
| // Text selection within form text fields and form combobox text fields. |
| std::string selected_form_text_; |
| |
| // True if left mouse button is currently being held down. |
| bool mouse_left_button_down_ = false; |
| |
| // Last known position while performing middle mouse button pan, or |
| // std::nullopt if the middle mouse button is currently not held down. |
| std::optional<gfx::PointF> mouse_middle_button_last_position_; |
| |
| // The current text used for searching. |
| std::u16string current_find_text_; |
| // The results found. |
| std::vector<PDFiumRange> find_results_; |
| // Whether a search is in progress. |
| bool search_in_progress_ = false; |
| // Which page to search next. |
| int next_page_to_search_ = -1; |
| // Where to stop searching. |
| int last_page_to_search_ = -1; |
| int last_character_index_to_search_ = -1; // -1 if search until end of page. |
| // Which result the user has currently selected. (0-based) |
| std::optional<size_t> current_find_index_; |
| // Where to resume searching. (0-based) |
| std::optional<size_t> resume_find_index_; |
| |
| std::unique_ptr<PDFiumPermissions> permissions_; |
| |
| gfx::Size default_page_size_; |
| |
| // Timer for touch long press detection. |
| base::OneShotTimer touch_timer_; |
| |
| // Set to true when handling long touch press. |
| bool handling_long_press_ = false; |
| |
| // Set to true when updating plugin focus. |
| bool updating_focus_ = false; |
| |
| // True if `focus_field_type_` is currently set to `FocusFieldType::kText` and |
| // the focused form text area is not read-only. |
| bool editable_form_text_area_ = false; |
| |
| // The type of the currently focused form field. |
| PDFiumEngineClient::FocusFieldType focus_field_type_ = |
| PDFiumEngineClient::FocusFieldType::kNoFocus; |
| |
| // The focus element type for the currently focused object. |
| FocusElementType focus_element_type_ = FocusElementType::kNone; |
| |
| // Stores the last focused object's focus element type before PDF loses focus. |
| FocusElementType last_focused_element_type_ = FocusElementType::kNone; |
| |
| // Stores the last focused annotation's index before PDF loses focus. |
| int last_focused_annot_index_ = -1; |
| |
| // Holds the zero-based page index of the last page that had the focused |
| // object. |
| int last_focused_page_ = -1; |
| |
| // Holds the zero-based page index of the most visible page; refreshed by |
| // calling CalculateVisiblePages() |
| int most_visible_page_ = -1; |
| |
| // Holds the page index requested by PDFium while the scroll operation |
| // is being handled (asynchronously). |
| std::optional<int> in_flight_visible_page_; |
| |
| // Set to true after FORM_DoDocumentJSAction/FORM_DoDocumentOpenAction have |
| // been called. Only after that can we call FORM_DoPageAAction. |
| bool called_do_document_action_ = false; |
| |
| // Records parts of form fields that need to be highlighted at next paint, in |
| // screen coordinates. |
| std::vector<gfx::Rect> form_highlights_; |
| |
| // Whether to render in grayscale or in color. |
| bool render_grayscale_ = false; |
| |
| // Whether to render PDF annotations. |
| bool render_annots_ = true; |
| |
| // Pending progressive paints. |
| class ProgressivePaint { |
| public: |
| ProgressivePaint(uint32_t page_index, const gfx::Rect& rect); |
| ProgressivePaint(ProgressivePaint&& that) noexcept; |
| ProgressivePaint& operator=(ProgressivePaint&& that) noexcept; |
| ~ProgressivePaint(); |
| |
| uint32_t page_index() const { return page_index_; } |
| const gfx::Rect& rect() const { return rect_; } |
| FPDF_BITMAP bitmap() const { return bitmap_.get(); } |
| bool painted() const { return painted_; } |
| |
| void set_painted(bool enable) { painted_ = enable; } |
| void SetBitmapAndImageData(ScopedFPDFBitmap bitmap, SkBitmap image_data); |
| |
| private: |
| uint32_t page_index_; |
| gfx::Rect rect_; // In screen coordinates. |
| SkBitmap image_data_; // Maintains reference while |bitmap_| exists. |
| ScopedFPDFBitmap bitmap_; // Must come after |image_data_|. |
| // Temporary used to figure out if in a series of Paint() calls whether this |
| // pending paint was updated or not. |
| bool painted_ = false; |
| }; |
| std::vector<ProgressivePaint> progressive_paints_; |
| |
| // Keeps track of when we started the last progressive paint, so that in our |
| // callback we can determine if we need to pause. |
| base::Time last_progressive_start_time_; |
| |
| // The timeout to use for the current progressive paint. |
| base::TimeDelta progressive_paint_timeout_; |
| |
| // When this class was created. |
| const base::TimeTicks engine_creation_time_; |
| |
| // Keeps track of sending `PDF.FirstPaintTime` metric. |
| bool first_paint_metric_reported_ = false; |
| |
| // Shadow matrix for generating the page shadow bitmap. |
| std::unique_ptr<draw_utils::ShadowMatrix> page_shadow_; |
| |
| // Pending thumbnail requests. |
| struct PendingThumbnail { |
| PendingThumbnail(); |
| PendingThumbnail(PendingThumbnail&& that) noexcept; |
| PendingThumbnail& operator=(PendingThumbnail&& that) noexcept; |
| ~PendingThumbnail(); |
| |
| float device_pixel_ratio = 1.0f; |
| SendThumbnailCallback send_callback; |
| }; |
| |
| // Map of page indices to pending thumbnail requests. |
| base::flat_map<int, PendingThumbnail> pending_thumbnails_; |
| |
| // A list of information of document attachments. |
| std::vector<DocumentAttachmentInfo> doc_attachment_info_list_; |
| |
| // Stores parsed document metadata. |
| DocumentMetadata doc_metadata_; |
| |
| // While true, the document try to be opened and parsed after download each |
| // part. Else the document will be opened and parsed only on finish of |
| // downloading. |
| bool process_when_pending_request_complete_ = true; |
| |
| enum class RangeSelectionDirection { Left, Right }; |
| RangeSelectionDirection range_selection_direction_ = |
| RangeSelectionDirection::Right; |
| |
| gfx::Point range_selection_base_; |
| |
| bool edit_mode_ = false; |
| |
| // When true, interactive portions of the content, such as forms and links, |
| // are restricted. |
| bool read_only_ = false; |
| |
| PDFiumPrint print_; |
| |
| // The text caret on the PDF, excluding AcroForms. Once initialized, it will |
| // not be destroyed until the destructor is called. The caret needs to store |
| // state, such as its position, blink interval, etc. |
| std::unique_ptr<PdfCaret> caret_; |
| |
| // The list of text fragments to highlight on the PDF. |
| std::vector<PDFiumRange> text_fragment_highlights_; |
| |
| #if BUILDFLAG(ENABLE_PDF_INK2) |
| // Map of zero-based page indices with Ink strokes to page unload preventers. |
| // Pages with Ink strokes have page references in `ink_stroke_data_`, so these |
| // unload preventers ensure those page handles stay valid by keeping the page |
| // in memory. Use one unload preventer per page for simplicity. |
| std::map<int, PDFiumPage::ScopedUnloadPreventer> |
| stroked_pages_unload_preventers_; |
| |
| struct InkStrokeData { |
| InkStrokeData(int page_index, std::vector<FPDF_PAGEOBJECT> page_objects); |
| InkStrokeData(InkStrokeData&&) noexcept; |
| InkStrokeData& operator=(InkStrokeData&&) noexcept; |
| ~InkStrokeData(); |
| |
| int page_index; |
| |
| // The handles for stroke path page objects within the PDF document. |
| // `stroked_pages_unload_preventers_` protects these handles from going |
| // stale. |
| std::vector<FPDF_PAGEOBJECT> page_objects; |
| }; |
| |
| // Data associated for Ink strokes, keyed by stroke IDs. |
| std::map<InkStrokeId, InkStrokeData> ink_stroke_data_; |
| |
| // Tracks the pages which need to be regenerated before saving due to Ink |
| // stroke changes. |
| std::set<int> ink_stroked_pages_needing_regeneration_; |
| |
| #if DCHECK_IS_ON() |
| // Used to keep track of LoadV2InkPathsForPage() calls as a sanity check. |
| // Stores the 0-based page indices for pages that have been loaded. |
| std::set<int> pages_with_loaded_v2_ink_paths_; |
| #endif // DCHECK_IS_ON() |
| |
| // Used to hand out unique IDs of type InkModeledShapeId for the V2 Ink paths |
| // read out of the PDF. It is stored here as the raw type to simplify |
| // management. |
| size_t next_ink_modeled_shape_id_ = 0; |
| |
| // Key: ID to identify a shape. |
| // Value: The PDFium page object associated with the shape. |
| std::map<InkModeledShapeId, FPDF_PAGEOBJECT> ink_modeled_shape_map_; |
| #endif // BUILDFLAG(ENABLE_PDF_INK2) |
| |
| base::WeakPtrFactory<PDFiumEngine> weak_factory_{this}; |
| |
| // Weak pointers from this factory are used to bind the ContinueFind() |
| // function. This allows those weak pointers to be invalidated during |
| // StopFind(), and keeps the invalidation separated from `weak_factory_`. |
| base::WeakPtrFactory<PDFiumEngine> find_weak_factory_{this}; |
| }; |
| |
| } // namespace chrome_pdf |
| |
| #endif // PDF_PDFIUM_PDFIUM_ENGINE_H_ |