// Copyright 2016 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_FPDFTEXT_CPDF_TEXTPAGE_H_ #define CORE_FPDFTEXT_CPDF_TEXTPAGE_H_ #include #include #include #include #include "core/fpdfapi/page/cpdf_pageobjectholder.h" #include "core/fxcrt/data_vector.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_memory_wrappers.h" #include "core/fxcrt/unowned_ptr.h" #include "core/fxcrt/widestring.h" #include "core/fxcrt/widetext_buffer.h" class CPDF_FormObject; class CPDF_Page; class CPDF_TextObject; struct TextPageCharSegment { int index; int count; }; FX_DATA_PARTITION_EXCEPTION(TextPageCharSegment); class CPDF_TextPage { public: enum class CharType : uint8_t { kNormal, kGenerated, kNotUnicode, kHyphen, kPiece, }; class CharInfo { public: CharInfo(); CharInfo(CharType char_type, uint32_t char_code, wchar_t unicode, CFX_PointF origin, CFX_FloatRect char_box, CFX_Matrix matrix, CPDF_TextObject* text_object); CharInfo(const CharInfo&); ~CharInfo(); CharType char_type() const { return char_type_; } void set_char_type(CharType char_type) { char_type_ = char_type; } uint32_t char_code() const { return char_code_; } wchar_t unicode() const { return unicode_; } void set_unicode(wchar_t unicode) { unicode_ = unicode; } const CFX_PointF& origin() const { return origin_; } const CFX_FloatRect& char_box() const { return char_box_; } const CFX_FloatRect& loose_char_box() const { return loose_char_box_; } const CFX_Matrix& matrix() const { return matrix_; } const CPDF_TextObject* text_object() const { return text_object_; } CPDF_TextObject* text_object() { return text_object_; } private: CharType char_type_ = CharType::kNormal; wchar_t unicode_ = 0; // Above `char_code_` to potentially pack tighter. uint32_t char_code_ = 0; CFX_PointF origin_; CFX_FloatRect char_box_; CFX_FloatRect loose_char_box_; CFX_Matrix matrix_; UnownedPtr text_object_; }; CPDF_TextPage(const CPDF_Page* page, bool rtl); ~CPDF_TextPage(); int CharIndexFromTextIndex(int text_index) const; int TextIndexFromCharIndex(int char_index) const; size_t size() const { return char_list_.size(); } int CountChars() const; // These methods CHECK() to make sure |index| is within bounds. const CharInfo& GetCharInfo(size_t index) const; CharInfo& GetCharInfo(size_t index); float GetCharFontSize(size_t index) const; CFX_FloatRect GetCharLooseBounds(size_t index) const; std::vector GetRectArray(int start, int count) const; int GetIndexAtPos(const CFX_PointF& point, const CFX_SizeF& tolerance) const; WideString GetTextByRect(const CFX_FloatRect& rect) const; WideString GetTextByObject(const CPDF_TextObject* text_obj) const; // Returns string with the text from |text_buf_| that are covered by the input // range. |start| and |count| are in terms of the |char_indices_|, so the // range will be converted into appropriate indices. WideString GetPageText(int start, int count) const; WideString GetAllPageText() const { return GetPageText(0, CountChars()); } int CountRects(int start, int count); bool GetRect(int rectIndex, CFX_FloatRect* pRect) const; private: enum class TextOrientation { kUnknown, kHorizontal, kVertical, }; enum class GenerateCharacter { kNone, kSpace, kLineBreak, kHyphen, }; enum class MarkedContentState { kPass = 0, kDone, kDelay }; struct TransformedTextObject { TransformedTextObject(); TransformedTextObject(const TransformedTextObject& that); ~TransformedTextObject(); UnownedPtr text_obj_; CFX_Matrix form_matrix_; }; void Init(); bool IsHyphen(wchar_t current_char) const; void ProcessObject(); void ProcessFormObject(CPDF_FormObject* form_obj, const CFX_Matrix& form_matrix); void ProcessTextObject(const TransformedTextObject& obj); void ProcessTextObject(CPDF_TextObject* text_obj, const CFX_Matrix& form_matrix, const CPDF_PageObjectHolder* obj_list, CPDF_PageObjectHolder::const_iterator obj_iter); GenerateCharacter ProcessInsertObject(const CPDF_TextObject* text_obj, const CFX_Matrix& form_matrix); // Returns whether to continue or not. bool ProcessGenerateCharacter(GenerateCharacter type, const CPDF_TextObject* text_object, const CFX_Matrix& form_matrix); // Processes character items in `text_object` and appends character info and // text to `temp_char_list_` and `temp_text_buf_`. // Returns true if the caller needs to call ReverseTempTextBufs() because the // text is RTL with a mirrored transformation matrix, requiring the newly // appended character order to be reversed. bool ProcessTextObjectItems(CPDF_TextObject* text_object, const CFX_Matrix& form_matrix, const CFX_Matrix& matrix); const CharInfo* GetPrevCharInfo() const; std::optional GenerateCharInfo(wchar_t unicode, const CFX_Matrix& form_matrix); bool IsSameAsPreTextObject(CPDF_TextObject* text_obj, const CPDF_PageObjectHolder* obj_list, CPDF_PageObjectHolder::const_iterator iter) const; bool IsSameTextObject(CPDF_TextObject* text_obj1, CPDF_TextObject* text_obj2) const; void CloseTempLine(); MarkedContentState PreMarkedContent(const CPDF_TextObject* text_obj); void ProcessMarkedContent(const TransformedTextObject& obj); void FindPreviousTextObject(); void AddCharInfo(wchar_t wc, const CharInfo& info, bool is_rtl); TextOrientation GetTextObjectWritingMode( const CPDF_TextObject* text_obj) const; TextOrientation FindTextlineFlowOrientation() const; void AppendGeneratedCharacter(wchar_t unicode, const CFX_Matrix& form_matrix, bool use_temp_buffer); // Reverses elements in `temp_char_list_` starting at `char_list_index` and // characters in `temp_text_buf_` starting at `buf_index`. void ReverseTempTextBufs(size_t char_list_index, size_t buf_index); WideString GetTextByPredicate( const std::function& predicate) const; UnownedPtr const page_; DataVector char_indices_; std::vector char_list_; std::vector temp_char_list_; WideTextBuffer text_buf_; WideTextBuffer temp_text_buf_; UnownedPtr prev_text_obj_; CFX_Matrix prev_matrix_; const bool rtl_; const CFX_Matrix display_matrix_; std::vector sel_rects_; std::vector text_objects_; TextOrientation textline_dir_ = TextOrientation::kUnknown; CFX_FloatRect curline_rect_; }; #endif // CORE_FPDFTEXT_CPDF_TEXTPAGE_H_