blob: c6ac8c8ef96d6d435bfd2025e41e3d4f13d3e7b7 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "pdf/accessibility.h"
#include "pdf/pdf_engine.h"
#include "ppapi/c/private/ppb_pdf.h"
namespace chrome_pdf {
bool GetAccessibilityInfo(
PDFEngine* engine,
int32_t page_index,
PP_PrivateAccessibilityPageInfo* page_info,
std::vector<PP_PrivateAccessibilityTextRunInfo>* text_runs,
std::vector<PP_PrivateAccessibilityCharInfo>* chars) {
int page_count = engine->GetNumberOfPages();
if (page_index < 0 || page_index >= page_count)
return false;
int char_count = engine->GetCharCount(page_index);
// Treat a char count of -1 (error) as 0 (an empty page), since
// other pages might have valid content.
if (char_count < 0)
char_count = 0;
page_info->page_index = page_index;
page_info->bounds = engine->GetPageBoundsRect(page_index);
page_info->char_count = char_count;
chars->resize(page_info->char_count);
for (uint32_t i = 0; i < page_info->char_count; ++i) {
(*chars)[i].unicode_character = engine->GetCharUnicode(page_index, i);
}
int char_index = 0;
while (char_index < char_count) {
PP_PrivateAccessibilityTextRunInfo text_run_info;
pp::FloatRect bounds;
engine->GetTextRunInfo(page_index, char_index, &text_run_info.len,
&text_run_info.font_size, &bounds);
DCHECK_LE(char_index + text_run_info.len,
static_cast<uint32_t>(char_count));
text_run_info.direction = PP_PRIVATEDIRECTION_LTR;
text_run_info.bounds = bounds;
text_runs->push_back(text_run_info);
// We need to provide enough information to draw a bounding box
// around any arbitrary text range, but the bounding boxes of characters
// we get from PDFium don't necessarily "line up". Walk through the
// characters in each text run and let the width of each character be
// the difference between the x coordinate of one character and the
// x coordinate of the next. The rest of the bounds of each character
// can be computed from the bounds of the text run.
pp::FloatRect char_bounds = engine->GetCharBounds(page_index, char_index);
for (uint32_t i = 0; i < text_run_info.len - 1; i++) {
DCHECK_LT(char_index + i + 1, static_cast<uint32_t>(char_count));
pp::FloatRect next_char_bounds =
engine->GetCharBounds(page_index, char_index + i + 1);
(*chars)[char_index + i].char_width =
next_char_bounds.x() - char_bounds.x();
char_bounds = next_char_bounds;
}
(*chars)[char_index + text_run_info.len - 1].char_width =
char_bounds.width();
char_index += text_run_info.len;
}
page_info->text_run_count = text_runs->size();
return true;
}
} // namespace chrome_pdf