Index: pdf/pdfium/pdfium_page.cc |
diff --git a/pdf/pdfium/pdfium_page.cc b/pdf/pdfium/pdfium_page.cc |
index af64660a2a8513cc98afc6d42e98fc4f9adf1d9c..c7e53393331ec021073af5f2afc69a08e4354f59 100644 |
--- a/pdf/pdfium/pdfium_page.cc |
+++ b/pdf/pdfium/pdfium_page.cc |
@@ -17,10 +17,15 @@ |
#include "base/values.h" |
#include "pdf/pdfium/pdfium_api_string_buffer_adapter.h" |
#include "pdf/pdfium/pdfium_engine.h" |
+#include "printing/units.h" |
// Used when doing hit detection. |
#define kTolerance 20.0 |
+using printing::ConvertUnitDouble; |
+using printing::kPointsPerInch; |
+using printing::kPixelsPerInch; |
+ |
namespace { |
// Dictionary Value key names for returning the accessible page content as JSON. |
@@ -60,6 +65,33 @@ pp::Rect PageRectToGViewRect(FPDF_PAGE page, const pp::Rect& input) { |
return output_rect; |
} |
+pp::FloatRect FloatPageRectToPixelRect(FPDF_PAGE page, |
+ const pp::FloatRect& input) { |
+ int output_width = FPDF_GetPageWidth(page); |
+ int output_height = FPDF_GetPageHeight(page); |
+ |
+ int min_x; |
+ int min_y; |
+ int max_x; |
+ int max_y; |
+ FPDF_PageToDevice(page, 0, 0, output_width, output_height, 0, input.x(), |
+ input.y(), &min_x, &min_y); |
+ FPDF_PageToDevice(page, 0, 0, output_width, output_height, 0, input.right(), |
+ input.bottom(), &max_x, &max_y); |
+ |
+ if (max_x < min_x) |
+ std::swap(min_x, max_x); |
+ if (max_y < min_y) |
+ std::swap(min_y, max_y); |
+ |
+ pp::FloatRect output_rect( |
+ ConvertUnitDouble(min_x, kPointsPerInch, kPixelsPerInch), |
+ ConvertUnitDouble(min_y, kPointsPerInch, kPixelsPerInch), |
+ ConvertUnitDouble(max_x - min_x, kPointsPerInch, kPixelsPerInch), |
+ ConvertUnitDouble(max_y - min_y, kPointsPerInch, kPixelsPerInch)); |
+ return output_rect; |
+} |
+ |
pp::Rect GetCharRectInGViewCoords(FPDF_PAGE page, FPDF_TEXTPAGE text_page, |
int index) { |
double left, right, bottom, top; |
@@ -72,6 +104,19 @@ pp::Rect GetCharRectInGViewCoords(FPDF_PAGE page, FPDF_TEXTPAGE text_page, |
return PageRectToGViewRect(page, page_coords); |
} |
+pp::FloatRect GetFloatCharRectInPixels(FPDF_PAGE page, |
+ FPDF_TEXTPAGE text_page, |
+ int index) { |
+ double left, right, bottom, top; |
+ FPDFText_GetCharBox(text_page, index, &left, &right, &bottom, &top); |
+ if (right < left) |
+ std::swap(left, right); |
+ if (bottom < top) |
+ std::swap(top, bottom); |
+ pp::FloatRect page_coords(left, top, right - left, bottom - top); |
+ return FloatPageRectToPixelRect(page, page_coords); |
+} |
+ |
// This is the character PDFium inserts where a word is broken across lines. |
const unsigned int kSoftHyphen = 0x02; |
@@ -98,6 +143,11 @@ bool OverlapsOnYAxis(const pp::Rect &a, const pp::Rect& b) { |
a.bottom() < b.y() || b.bottom() < a.y()); |
} |
+bool OverlapsOnYAxis(const pp::FloatRect &a, const pp::FloatRect& b) { |
+ return !(a.IsEmpty() || b.IsEmpty() || |
+ a.bottom() < b.y() || b.bottom() < a.y()); |
+} |
+ |
bool IsEol(unsigned int character) { |
const unsigned int* first = kUnicodeNewlines; |
const unsigned int* last = kUnicodeNewlines + arraysize(kUnicodeNewlines); |
@@ -299,6 +349,60 @@ base::Value* PDFiumPage::GetAccessibleContentAsValue(int rotation) { |
return node; |
} |
+void PDFiumPage::GetTextRunInfo(int start_char_index, |
+ uint32_t* out_len, |
+ double* out_font_size, |
+ pp::FloatRect* out_bounds) { |
+ FPDF_PAGE page = GetPage(); |
+ FPDF_TEXTPAGE text_page = GetTextPage(); |
+ int chars_count = FPDFText_CountChars(text_page); |
+ int char_index = start_char_index; |
+ while ( |
+ char_index < chars_count && |
+ base::IsUnicodeWhitespace(FPDFText_GetUnicode(text_page, char_index))) { |
+ char_index++; |
+ } |
+ int text_run_font_size = FPDFText_GetFontSize(text_page, char_index); |
+ pp::FloatRect text_run_bounds = |
+ GetFloatCharRectInPixels(page, text_page, char_index); |
+ char_index++; |
+ while (char_index < chars_count) { |
+ unsigned int character = FPDFText_GetUnicode(text_page, char_index); |
+ |
+ if (!base::IsUnicodeWhitespace(character)) { |
+ // TODO(dmazzoni): this assumes horizontal text. |
+ // https://crbug.com/580311 |
+ pp::FloatRect char_rect = |
+ GetFloatCharRectInPixels(page, text_page, char_index); |
+ if (!char_rect.IsEmpty() && !OverlapsOnYAxis(text_run_bounds, char_rect)) |
+ break; |
+ |
+ int font_size = FPDFText_GetFontSize(text_page, char_index); |
+ if (font_size != text_run_font_size) |
+ break; |
+ |
+ text_run_bounds = text_run_bounds.Union(char_rect); |
+ } |
+ |
+ char_index++; |
+ } |
+ |
+ *out_len = char_index - start_char_index; |
+ *out_font_size = text_run_font_size; |
+ *out_bounds = text_run_bounds; |
+} |
+ |
+uint32_t PDFiumPage::GetCharUnicode(int char_index) { |
+ FPDF_TEXTPAGE text_page = GetTextPage(); |
+ return FPDFText_GetUnicode(text_page, char_index); |
+} |
+ |
+double PDFiumPage::GetCharWidth(int char_index) { |
+ FPDF_PAGE page = GetPage(); |
+ FPDF_TEXTPAGE text_page = GetTextPage(); |
+ return GetFloatCharRectInPixels(page, text_page, char_index).width(); |
+} |
+ |
PDFiumPage::Area PDFiumPage::GetCharIndex(const pp::Point& point, |
int rotation, |
int* char_index, |