summaryrefslogtreecommitdiff
path: root/chromium/pdf/pdfium/pdfium_page.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/pdf/pdfium/pdfium_page.cc')
-rw-r--r--chromium/pdf/pdfium/pdfium_page.cc180
1 files changed, 125 insertions, 55 deletions
diff --git a/chromium/pdf/pdfium/pdfium_page.cc b/chromium/pdf/pdfium/pdfium_page.cc
index 4f5f5af65b8..6f95affddc8 100644
--- a/chromium/pdf/pdfium/pdfium_page.cc
+++ b/chromium/pdf/pdfium/pdfium_page.cc
@@ -186,24 +186,6 @@ bool FloatEquals(float f1, float f2) {
kEpsilonScale * fmaxf(fmaxf(fabsf(f1), fabsf(f2)), kEpsilonScale);
}
-using GetFormFieldPropertyFunction =
- base::RepeatingCallback<unsigned long(unsigned short* buffer,
- unsigned long buflen)>;
-
-// Helper method to fetch string properties of form fields.
-std::string GetFormFieldProperty(GetFormFieldPropertyFunction function) {
- base::string16 data;
- size_t buffer_size = function.Run(nullptr, 0);
- if (buffer_size > 0) {
- PDFiumAPIStringBufferSizeInBytesAdapter<base::string16> api_string_adapter(
- &data, buffer_size, true);
- api_string_adapter.Close(function.Run(
- reinterpret_cast<unsigned short*>(api_string_adapter.GetData()),
- buffer_size));
- }
- return base::UTF16ToUTF8(data);
-}
-
// Count overlaps across text annotations.
template <typename T, typename U>
uint32_t CountOverlaps(const std::vector<T>& first_set,
@@ -472,6 +454,18 @@ PDFiumPage::GetTextRunInfo(int start_char_index) {
info.direction = PP_PRIVATEDIRECTION_NONE;
return info;
}
+
+ // If the first character in a text run is a space, we need to start
+ // |text_run_bounds| from the space character instead of the first
+ // non-space unicode character.
+ pp::FloatRect text_run_bounds =
+ actual_start_char_index > start_char_index
+ ? GetFloatCharRectInPixels(page, text_page, start_char_index)
+ : pp::FloatRect();
+
+ // Pdfium trims more than 1 consecutive spaces to 1 space.
+ DCHECK_LE(actual_start_char_index - start_char_index, 1);
+
int char_index = actual_start_char_index;
// Set text run's style info from the first character of the text run.
@@ -494,8 +488,8 @@ PDFiumPage::GetTextRunInfo(int start_char_index) {
AddCharSizeToAverageCharSize(start_char_rect.Floatsize(), &avg_char_size,
&non_whitespace_chars_count);
- // Add first char to text run.
- pp::FloatRect text_run_bounds = start_char_rect;
+ // Add first non-space char to text run.
+ text_run_bounds = text_run_bounds.Union(start_char_rect);
PP_PrivateDirection char_direction =
GetDirectionFromAngle(FPDFText_GetCharAngle(text_page, char_index));
if (char_index < chars_count)
@@ -676,6 +670,7 @@ PDFiumPage::GetHighlightInfo() {
highlight.bounding_rect.x(), highlight.bounding_rect.y(),
highlight.bounding_rect.width(), highlight.bounding_rect.height());
cur_info.color = highlight.color;
+ cur_info.note_text = highlight.note_text;
highlight_info.push_back(std::move(cur_info));
}
return highlight_info;
@@ -900,16 +895,11 @@ gfx::PointF PDFiumPage::TransformPageToScreenXY(const gfx::PointF& xy) {
PDFiumPage::Area PDFiumPage::GetURITarget(FPDF_ACTION uri_action,
LinkTarget* target) const {
if (target) {
- size_t buffer_size =
- FPDFAction_GetURIPath(engine_->doc(), uri_action, nullptr, 0);
- if (buffer_size > 0) {
- PDFiumAPIStringBufferAdapter<std::string> api_string_adapter(
- &target->url, buffer_size, true);
- void* data = api_string_adapter.GetData();
- size_t bytes_written =
- FPDFAction_GetURIPath(engine_->doc(), uri_action, data, buffer_size);
- api_string_adapter.Close(bytes_written);
- }
+ std::string url = CallPDFiumStringBufferApi(
+ base::BindRepeating(&FPDFAction_GetURIPath, engine_->doc(), uri_action),
+ /*check_expected_size=*/true);
+ if (!url.empty())
+ target->url = url;
}
return WEBLINK_AREA;
}
@@ -956,6 +946,8 @@ void PDFiumPage::PopulateWebLinks() {
ScopedFPDFPageLink links(FPDFLink_LoadWebLinks(GetTextPage()));
int count = FPDFLink_CountWebLinks(links.get());
for (int i = 0; i < count; ++i) {
+ // WARNING: FPDFLink_GetURL() is not compatible with
+ // CallPDFiumWideStringBufferApi().
base::string16 url;
int url_length = FPDFLink_GetURL(links.get(), i, nullptr, 0);
if (url_length > 0) {
@@ -1141,16 +1133,11 @@ void PDFiumPage::PopulateImageAltTextForStructElement(
auto it = marked_content_id_image_map.find(marked_content_id);
if (it != marked_content_id_image_map.end() &&
images_[it->second].alt_text.empty()) {
- size_t buffer_size =
- FPDF_StructElement_GetAltText(current_element, nullptr, 0);
- if (buffer_size > 0) {
- base::string16 alt_text;
- PDFiumAPIStringBufferSizeInBytesAdapter<base::string16>
- api_string_adapter(&alt_text, buffer_size, true);
- api_string_adapter.Close(FPDF_StructElement_GetAltText(
- current_element, api_string_adapter.GetData(), buffer_size));
- images_[it->second].alt_text = base::UTF16ToUTF8(alt_text);
- }
+ images_[it->second].alt_text =
+ base::UTF16ToUTF8(CallPDFiumWideStringBufferApi(
+ base::BindRepeating(&FPDF_StructElement_GetAltText,
+ current_element),
+ /*check_expected_size=*/true));
}
}
int children_count = FPDF_StructElement_CountChildren(current_element);
@@ -1182,11 +1169,7 @@ void PDFiumPage::PopulateAnnotations() {
break;
}
case FPDF_ANNOT_WIDGET: {
- // TODO(crbug.com/1030242): Populate other types of form fields too.
- if (FPDFAnnot_GetFormFieldType(engine_->form(), annot.get()) ==
- FPDF_FORMFIELD_TEXTFIELD) {
- PopulateTextField(annot.get());
- }
+ PopulateFormField(annot.get());
break;
}
default:
@@ -1230,6 +1213,14 @@ void PDFiumPage::PopulateHighlight(FPDF_ANNOTATION annot) {
highlight.color = MakeARGB(255, 255, 255, 0);
}
+ // Retrieve the contents of the popup note associated with highlight.
+ // See table 164 in ISO 32000-1 standard for more details around "Contents"
+ // key in a highlight annotation.
+ static constexpr char kContents[] = "Contents";
+ highlight.note_text = base::UTF16ToUTF8(CallPDFiumWideStringBufferApi(
+ base::BindRepeating(&FPDFAnnot_GetStringValue, annot, kContents),
+ /*check_expected_size=*/true));
+
highlights_.push_back(std::move(highlight));
}
@@ -1239,21 +1230,81 @@ void PDFiumPage::PopulateTextField(FPDF_ANNOTATION annot) {
DCHECK_EQ(FPDFAnnot_GetFormFieldType(form_handle, annot),
FPDF_FORMFIELD_TEXTFIELD);
+ TextField text_field;
+ if (!PopulateFormFieldProperties(annot, &text_field))
+ return;
+
+ text_field.value = base::UTF16ToUTF8(CallPDFiumWideStringBufferApi(
+ base::BindRepeating(&FPDFAnnot_GetFormFieldValue, form_handle, annot),
+ /*check_expected_size=*/true));
+ text_fields_.push_back(std::move(text_field));
+}
+
+void PDFiumPage::PopulateChoiceField(FPDF_ANNOTATION annot) {
+ DCHECK(annot);
+ FPDF_FORMHANDLE form_handle = engine_->form();
+ int form_field_type = FPDFAnnot_GetFormFieldType(form_handle, annot);
+ DCHECK(form_field_type == FPDF_FORMFIELD_LISTBOX ||
+ form_field_type == FPDF_FORMFIELD_COMBOBOX);
+
+ ChoiceField choice_field;
+ if (!PopulateFormFieldProperties(annot, &choice_field))
+ return;
+
+ int options_count = FPDFAnnot_GetOptionCount(form_handle, annot);
+ if (options_count < 0)
+ return;
+
+ choice_field.options.resize(options_count);
+ for (int i = 0; i < options_count; ++i) {
+ choice_field.options[i].name =
+ base::UTF16ToUTF8(CallPDFiumWideStringBufferApi(
+ base::BindRepeating(&FPDFAnnot_GetOptionLabel, form_handle, annot,
+ i),
+ /*check_expected_size=*/true));
+ choice_field.options[i].is_selected =
+ FPDFAnnot_IsOptionSelected(form_handle, annot, i);
+ }
+ choice_fields_.push_back(std::move(choice_field));
+}
+
+void PDFiumPage::PopulateFormField(FPDF_ANNOTATION annot) {
+ DCHECK_EQ(FPDFAnnot_GetSubtype(annot), FPDF_ANNOT_WIDGET);
+ int form_field_type = FPDFAnnot_GetFormFieldType(engine_->form(), annot);
+
+ // TODO(crbug.com/1030242): Populate other types of form fields too.
+ switch (form_field_type) {
+ case FPDF_FORMFIELD_COMBOBOX:
+ case FPDF_FORMFIELD_LISTBOX: {
+ PopulateChoiceField(annot);
+ break;
+ }
+ case FPDF_FORMFIELD_TEXTFIELD: {
+ PopulateTextField(annot);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+bool PDFiumPage::PopulateFormFieldProperties(FPDF_ANNOTATION annot,
+ FormField* form_field) {
+ DCHECK(annot);
FS_RECTF rect;
if (!FPDFAnnot_GetRect(annot, &rect))
- return;
+ return false;
- TextField text_field;
- // We use the bounding box of the text field as the bounding rect.
- text_field.bounding_rect =
+ // We use the bounding box of the form field as the bounding rect.
+ form_field->bounding_rect =
PageToScreen(pp::Point(), 1.0, rect.left, rect.top, rect.right,
rect.bottom, PageOrientation::kOriginal);
- text_field.value = GetFormFieldProperty(
- base::BindRepeating(FPDFAnnot_GetFormFieldValue, form_handle, annot));
- text_field.name = GetFormFieldProperty(
- base::BindRepeating(FPDFAnnot_GetFormFieldName, form_handle, annot));
- text_field.flags = FPDFAnnot_GetFormFieldFlags(form_handle, annot);
- text_fields_.push_back(std::move(text_field));
+ FPDF_FORMHANDLE form_handle = engine_->form();
+ form_field->name = base::UTF16ToUTF8(CallPDFiumWideStringBufferApi(
+ base::BindRepeating(&FPDFAnnot_GetFormFieldName, form_handle, annot),
+ /*check_expected_size=*/true));
+ form_field->flags = FPDFAnnot_GetFormFieldFlags(form_handle, annot);
+ return true;
}
bool PDFiumPage::GetUnderlyingTextRangeForRect(const pp::FloatRect& rect,
@@ -1385,12 +1436,31 @@ PDFiumPage::Highlight::Highlight(const Highlight& that) = default;
PDFiumPage::Highlight::~Highlight() = default;
+PDFiumPage::FormField::FormField() = default;
+
+PDFiumPage::FormField::FormField(const FormField& that) = default;
+
+PDFiumPage::FormField::~FormField() = default;
+
PDFiumPage::TextField::TextField() = default;
PDFiumPage::TextField::TextField(const TextField& that) = default;
PDFiumPage::TextField::~TextField() = default;
+PDFiumPage::ChoiceFieldOption::ChoiceFieldOption() = default;
+
+PDFiumPage::ChoiceFieldOption::ChoiceFieldOption(
+ const ChoiceFieldOption& that) = default;
+
+PDFiumPage::ChoiceFieldOption::~ChoiceFieldOption() = default;
+
+PDFiumPage::ChoiceField::ChoiceField() = default;
+
+PDFiumPage::ChoiceField::ChoiceField(const ChoiceField& that) = default;
+
+PDFiumPage::ChoiceField::~ChoiceField() = default;
+
// static
uint32_t PDFiumPage::CountLinkHighlightOverlaps(
const std::vector<Link>& links,