1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "pdf/accessibility.h"
7 #include "pdf/pdf_engine.h"
8 #include "ppapi/c/private/ppb_pdf.h"
10 namespace chrome_pdf {
12 bool GetAccessibilityInfo(
15 PP_PrivateAccessibilityPageInfo* page_info,
16 std::vector<PP_PrivateAccessibilityTextRunInfo>* text_runs,
17 std::vector<PP_PrivateAccessibilityCharInfo>* chars) {
18 int page_count = engine->GetNumberOfPages();
19 if (page_index < 0 || page_index >= page_count)
22 int char_count = engine->GetCharCount(page_index);
24 // Treat a char count of -1 (error) as 0 (an empty page), since
25 // other pages might have valid content.
29 page_info->page_index = page_index;
30 page_info->bounds = engine->GetPageBoundsRect(page_index);
31 page_info->char_count = char_count;
33 chars->resize(page_info->char_count);
34 for (uint32_t i = 0; i < page_info->char_count; ++i) {
35 (*chars)[i].unicode_character = engine->GetCharUnicode(page_index, i);
39 while (char_index < char_count) {
40 PP_PrivateAccessibilityTextRunInfo text_run_info;
42 engine->GetTextRunInfo(page_index, char_index, &text_run_info.len,
43 &text_run_info.font_size, &bounds);
44 DCHECK_LE(char_index + text_run_info.len,
45 static_cast<uint32_t>(char_count));
46 text_run_info.direction = PP_PRIVATEDIRECTION_LTR;
47 text_run_info.bounds = bounds;
48 text_runs->push_back(text_run_info);
50 // We need to provide enough information to draw a bounding box
51 // around any arbitrary text range, but the bounding boxes of characters
52 // we get from PDFium don't necessarily "line up". Walk through the
53 // characters in each text run and let the width of each character be
54 // the difference between the x coordinate of one character and the
55 // x coordinate of the next. The rest of the bounds of each character
56 // can be computed from the bounds of the text run.
57 pp::FloatRect char_bounds = engine->GetCharBounds(page_index, char_index);
58 for (uint32_t i = 0; i < text_run_info.len - 1; i++) {
59 DCHECK_LT(char_index + i + 1, static_cast<uint32_t>(char_count));
60 pp::FloatRect next_char_bounds =
61 engine->GetCharBounds(page_index, char_index + i + 1);
62 (*chars)[char_index + i].char_width =
63 next_char_bounds.x() - char_bounds.x();
64 char_bounds = next_char_bounds;
66 (*chars)[char_index + text_run_info.len - 1].char_width =
69 char_index += text_run_info.len;
72 page_info->text_run_count = text_runs->size();
76 } // namespace chrome_pdf