diff options
Diffstat (limited to 'chromium/pdf/pdfium/pdfium_page.cc')
-rw-r--r-- | chromium/pdf/pdfium/pdfium_page.cc | 180 |
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, |