pdfium/core/fpdftext/cpdf_textpage.h
Lei Zhang 7bdfa23086 Refactor CPDF_TextPage::ProcessTextObjectItems() to return boolean
Change CPDF_TextPage::ProcessTextObjectItems() to return a boolean to
indicate whether to call ReverseTempTextBufs() or not. Move the RTL and
matrix determinant logic for calculating that boolean from the only
caller into ProcessTextObjectItems(). This refactoring will align
ProcessTextObjectItems() behavior with the upcoming
ProcessMarkedContent() change in
https://pdfium-review.googlesource.com/152751.

TAG=agy
CONV=42897bdc-5c71-4a3e-9f56-a4ef21ac2a39

Change-Id: I15bcd98e3e740ec912c5cf2c39ca9eca777582c4
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/152751
Reviewed-by: Andy Phan <andyphan@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
2026-07-23 18:07:41 -07:00

206 lines
7.2 KiB
C++

// 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 <stdint.h>
#include <functional>
#include <optional>
#include <vector>
#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<CPDF_TextObject> 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<CFX_FloatRect> 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<CPDF_TextObject> 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<CharInfo> 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<bool(const CharInfo&)>& predicate) const;
UnownedPtr<const CPDF_Page> const page_;
DataVector<TextPageCharSegment> char_indices_;
std::vector<CharInfo> char_list_;
std::vector<CharInfo> temp_char_list_;
WideTextBuffer text_buf_;
WideTextBuffer temp_text_buf_;
UnownedPtr<const CPDF_TextObject> prev_text_obj_;
CFX_Matrix prev_matrix_;
const bool rtl_;
const CFX_Matrix display_matrix_;
std::vector<CFX_FloatRect> sel_rects_;
std::vector<TransformedTextObject> text_objects_;
TextOrientation textline_dir_ = TextOrientation::kUnknown;
CFX_FloatRect curline_rect_;
};
#endif // CORE_FPDFTEXT_CPDF_TEXTPAGE_H_