Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(86)

Side by Side Diff: components/pdf/renderer/pdf_accessibility_tree.cc

Issue 2371483002: Update PDF accessibility when zoom level changes (Closed)
Patch Set: Renamed PDF -> Plugin in content/renderer/ Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <algorithm> 5 #include <algorithm>
6 6
7 #include "base/memory/ptr_util.h" 7 #include "base/memory/ptr_util.h"
8 #include "base/strings/stringprintf.h" 8 #include "base/strings/stringprintf.h"
9 #include "base/strings/utf_string_conversion_utils.h" 9 #include "base/strings/utf_string_conversion_utils.h"
10 #include "components/pdf/renderer/pdf_accessibility_tree.h" 10 #include "components/pdf/renderer/pdf_accessibility_tree.h"
11 #include "content/public/renderer/render_accessibility.h" 11 #include "content/public/renderer/render_accessibility.h"
12 #include "content/public/renderer/render_frame.h" 12 #include "content/public/renderer/render_frame.h"
13 #include "content/public/renderer/render_view.h" 13 #include "content/public/renderer/render_view.h"
14 #include "content/public/renderer/renderer_ppapi_host.h" 14 #include "content/public/renderer/renderer_ppapi_host.h"
15 #include "grit/components_strings.h" 15 #include "grit/components_strings.h"
16 #include "ui/base/l10n/l10n_util.h" 16 #include "ui/base/l10n/l10n_util.h"
17 #include "ui/gfx/geometry/rect_conversions.h" 17 #include "ui/gfx/geometry/rect_conversions.h"
18 #include "ui/gfx/transform.h"
18 19
19 namespace pdf { 20 namespace pdf {
20 21
21 namespace { 22 namespace {
22 23
23 // Don't try to apply font size thresholds to automatically identify headings 24 // Don't try to apply font size thresholds to automatically identify headings
24 // if the median font size is not at least this many points. 25 // if the median font size is not at least this many points.
25 const double kMinimumFontSize = 5; 26 const double kMinimumFontSize = 5;
26 27
27 // Don't try to apply line break thresholds to automatically identify 28 // Don't try to apply line break thresholds to automatically identify
(...skipping 26 matching lines...) Expand all
54 } 55 }
55 56
56 void PdfAccessibilityTree::SetAccessibilityViewportInfo( 57 void PdfAccessibilityTree::SetAccessibilityViewportInfo(
57 const PP_PrivateAccessibilityViewportInfo& viewport_info) { 58 const PP_PrivateAccessibilityViewportInfo& viewport_info) {
58 zoom_ = viewport_info.zoom; 59 zoom_ = viewport_info.zoom;
59 CHECK_GT(zoom_, 0); 60 CHECK_GT(zoom_, 0);
60 scroll_ = ToVector2dF(viewport_info.scroll); 61 scroll_ = ToVector2dF(viewport_info.scroll);
61 scroll_.Scale(1.0 / zoom_); 62 scroll_.Scale(1.0 / zoom_);
62 offset_ = ToVector2dF(viewport_info.offset); 63 offset_ = ToVector2dF(viewport_info.offset);
63 offset_.Scale(1.0 / zoom_); 64 offset_.Scale(1.0 / zoom_);
65
66 content::RenderAccessibility* render_accessibility = GetRenderAccessibility();
67 if (render_accessibility && tree_.size() > 1) {
68 ui::AXNode* root = tree_.root();
69 ui::AXNodeData root_data = root->data();
70 root_data.transform = base::WrapUnique(MakeTransformFromViewInfo());
71 root->SetData(root_data);
72 render_accessibility->OnPluginRootNodeUpdated();
73 }
64 } 74 }
65 75
66 void PdfAccessibilityTree::SetAccessibilityDocInfo( 76 void PdfAccessibilityTree::SetAccessibilityDocInfo(
67 const PP_PrivateAccessibilityDocInfo& doc_info) { 77 const PP_PrivateAccessibilityDocInfo& doc_info) {
68 if (!GetRenderAccessibility()) 78 if (!GetRenderAccessibility())
69 return; 79 return;
70 80
71 doc_info_ = doc_info; 81 doc_info_ = doc_info;
72 doc_node_ = CreateNode(ui::AX_ROLE_GROUP); 82 doc_node_ = CreateNode(ui::AX_ROLE_GROUP);
83
84 // Because all of the coordinates are expressed relative to the
85 // doc's coordinates, the origin of the doc must be (0, 0). Its
86 // width and height will be updated as we add each page so that the
87 // doc's bounding box surrounds all pages.
88 doc_node_->location = gfx::RectF(0, 0, 1, 1);
73 } 89 }
74 90
75 void PdfAccessibilityTree::SetAccessibilityPageInfo( 91 void PdfAccessibilityTree::SetAccessibilityPageInfo(
76 const PP_PrivateAccessibilityPageInfo& page_info, 92 const PP_PrivateAccessibilityPageInfo& page_info,
77 const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs, 93 const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs,
78 const std::vector<PP_PrivateAccessibilityCharInfo>& chars) { 94 const std::vector<PP_PrivateAccessibilityCharInfo>& chars) {
79 content::RenderAccessibility* render_accessibility = GetRenderAccessibility(); 95 content::RenderAccessibility* render_accessibility = GetRenderAccessibility();
80 if (!render_accessibility) 96 if (!render_accessibility)
81 return; 97 return;
82 98
83 uint32_t page_index = page_info.page_index; 99 uint32_t page_index = page_info.page_index;
84 CHECK_GE(page_index, 0U); 100 CHECK_GE(page_index, 0U);
85 CHECK_LT(page_index, doc_info_.page_count); 101 CHECK_LT(page_index, doc_info_.page_count);
86 102
87 ui::AXNodeData* page_node = CreateNode(ui::AX_ROLE_REGION); 103 ui::AXNodeData* page_node = CreateNode(ui::AX_ROLE_REGION);
88 page_node->AddStringAttribute( 104 page_node->AddStringAttribute(
89 ui::AX_ATTR_NAME, 105 ui::AX_ATTR_NAME,
90 l10n_util::GetPluralStringFUTF8( 106 l10n_util::GetPluralStringFUTF8(
91 IDS_PDF_PAGE_INDEX, page_index + 1)); 107 IDS_PDF_PAGE_INDEX, page_index + 1));
92 108
93 gfx::RectF page_bounds = ToRectF(page_info.bounds); 109 gfx::RectF page_bounds = ToRectF(page_info.bounds);
94 page_bounds += offset_;
95 page_bounds -= scroll_;
96 page_bounds.Scale(zoom_ / GetDeviceScaleFactor());
97 page_node->location = page_bounds; 110 page_node->location = page_bounds;
98 doc_node_->location.Union(page_node->location); 111 doc_node_->location.Union(page_node->location);
99 doc_node_->child_ids.push_back(page_node->id); 112 doc_node_->child_ids.push_back(page_node->id);
100 113
101 double heading_font_size_threshold = 0; 114 double heading_font_size_threshold = 0;
102 double line_spacing_threshold = 0; 115 double line_spacing_threshold = 0;
103 ComputeParagraphAndHeadingThresholds(text_runs, 116 ComputeParagraphAndHeadingThresholds(text_runs,
104 &heading_font_size_threshold, 117 &heading_font_size_threshold,
105 &line_spacing_threshold); 118 &line_spacing_threshold);
106 119
(...skipping 28 matching lines...) Expand all
135 para_node->child_ids.push_back(static_text_node->id); 148 para_node->child_ids.push_back(static_text_node->id);
136 } 149 }
137 150
138 // Add this text run to the current static text node. 151 // Add this text run to the current static text node.
139 ui::AXNodeData* inline_text_box_node = CreateNode( 152 ui::AXNodeData* inline_text_box_node = CreateNode(
140 ui::AX_ROLE_INLINE_TEXT_BOX); 153 ui::AX_ROLE_INLINE_TEXT_BOX);
141 static_text_node->child_ids.push_back(inline_text_box_node->id); 154 static_text_node->child_ids.push_back(inline_text_box_node->id);
142 155
143 inline_text_box_node->AddStringAttribute(ui::AX_ATTR_NAME, chars_utf8); 156 inline_text_box_node->AddStringAttribute(ui::AX_ATTR_NAME, chars_utf8);
144 gfx::RectF text_run_bounds = ToGfxRectF(text_run.bounds); 157 gfx::RectF text_run_bounds = ToGfxRectF(text_run.bounds);
145 text_run_bounds.Scale(zoom_ / GetDeviceScaleFactor());
146 text_run_bounds += page_bounds.OffsetFromOrigin(); 158 text_run_bounds += page_bounds.OffsetFromOrigin();
147 inline_text_box_node->location = text_run_bounds; 159 inline_text_box_node->location = text_run_bounds;
148 inline_text_box_node->AddIntListAttribute(ui::AX_ATTR_CHARACTER_OFFSETS, 160 inline_text_box_node->AddIntListAttribute(ui::AX_ATTR_CHARACTER_OFFSETS,
149 char_offsets); 161 char_offsets);
150 162
151 para_node->location.Union(inline_text_box_node->location); 163 para_node->location.Union(inline_text_box_node->location);
152 static_text_node->location.Union(inline_text_box_node->location); 164 static_text_node->location.Union(inline_text_box_node->location);
153 165
154 if (i == text_runs.size() - 1) { 166 if (i == text_runs.size() - 1) {
155 static_text_node->AddStringAttribute(ui::AX_ATTR_NAME, static_text); 167 static_text_node->AddStringAttribute(ui::AX_ATTR_NAME, static_text);
(...skipping 10 matching lines...) Expand all
166 static_text_node = nullptr; 178 static_text_node = nullptr;
167 static_text.clear(); 179 static_text.clear();
168 } 180 }
169 } 181 }
170 182
171 if (page_index == doc_info_.page_count - 1) 183 if (page_index == doc_info_.page_count - 1)
172 Finish(); 184 Finish();
173 } 185 }
174 186
175 void PdfAccessibilityTree::Finish() { 187 void PdfAccessibilityTree::Finish() {
188 doc_node_->transform = base::WrapUnique(MakeTransformFromViewInfo());
189
176 ui::AXTreeUpdate update; 190 ui::AXTreeUpdate update;
177 update.root_id = doc_node_->id; 191 update.root_id = doc_node_->id;
178 for (const auto& node : nodes_) 192 for (const auto& node : nodes_)
179 update.nodes.push_back(*node); 193 update.nodes.push_back(*node);
180 194
181 CHECK(tree_.Unserialize(update)) << update.ToString() << tree_.error(); 195 CHECK(tree_.Unserialize(update)) << update.ToString() << tree_.error();
182 content::RenderAccessibility* render_accessibility = GetRenderAccessibility(); 196 content::RenderAccessibility* render_accessibility = GetRenderAccessibility();
183 if (render_accessibility) 197 if (render_accessibility)
184 render_accessibility->SetPdfTreeSource(this); 198 render_accessibility->SetPluginTreeSource(this);
185 } 199 }
186 200
187 void PdfAccessibilityTree::ComputeParagraphAndHeadingThresholds( 201 void PdfAccessibilityTree::ComputeParagraphAndHeadingThresholds(
188 const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs, 202 const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs,
189 double* out_heading_font_size_threshold, 203 double* out_heading_font_size_threshold,
190 double* out_line_spacing_threshold) { 204 double* out_line_spacing_threshold) {
191 // Scan over the font sizes and line spacing within this page and 205 // Scan over the font sizes and line spacing within this page and
192 // set heuristic thresholds so that text larger than the median font 206 // set heuristic thresholds so that text larger than the median font
193 // size can be marked as a heading, and spacing larger than the median 207 // size can be marked as a heading, and spacing larger than the median
194 // line spacing can be a paragraph break. 208 // line spacing can be a paragraph break.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 } 248 }
235 249
236 std::vector<int32_t> PdfAccessibilityTree::GetTextRunCharOffsets( 250 std::vector<int32_t> PdfAccessibilityTree::GetTextRunCharOffsets(
237 const PP_PrivateAccessibilityTextRunInfo& text_run, 251 const PP_PrivateAccessibilityTextRunInfo& text_run,
238 const std::vector<PP_PrivateAccessibilityCharInfo>& chars, 252 const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
239 int char_index) { 253 int char_index) {
240 std::vector<int32_t> char_offsets(text_run.len); 254 std::vector<int32_t> char_offsets(text_run.len);
241 double offset = 0.0; 255 double offset = 0.0;
242 for (uint32_t j = 0; j < text_run.len; ++j) { 256 for (uint32_t j = 0; j < text_run.len; ++j) {
243 offset += chars[char_index + j].char_width; 257 offset += chars[char_index + j].char_width;
244 char_offsets[j] = floor(offset * zoom_ / GetDeviceScaleFactor()); 258 char_offsets[j] = floor(offset);
245 } 259 }
246 return char_offsets; 260 return char_offsets;
247 } 261 }
248 262
249 gfx::Vector2dF PdfAccessibilityTree::ToVector2dF(const PP_Point& p) { 263 gfx::Vector2dF PdfAccessibilityTree::ToVector2dF(const PP_Point& p) {
250 return gfx::Vector2dF(p.x, p.y); 264 return gfx::Vector2dF(p.x, p.y);
251 } 265 }
252 266
253 gfx::RectF PdfAccessibilityTree::ToRectF(const PP_Rect& r) { 267 gfx::RectF PdfAccessibilityTree::ToRectF(const PP_Rect& r) {
254 return gfx::RectF(r.point.x, r.point.y, r.size.width, r.size.height); 268 return gfx::RectF(r.point.x, r.point.y, r.size.width, r.size.height);
255 } 269 }
256 270
257 ui::AXNodeData* PdfAccessibilityTree::CreateNode(ui::AXRole role) { 271 ui::AXNodeData* PdfAccessibilityTree::CreateNode(ui::AXRole role) {
258 content::RenderAccessibility* render_accessibility = GetRenderAccessibility(); 272 content::RenderAccessibility* render_accessibility = GetRenderAccessibility();
259 DCHECK(render_accessibility); 273 DCHECK(render_accessibility);
260 274
261 ui::AXNodeData* node = new ui::AXNodeData(); 275 ui::AXNodeData* node = new ui::AXNodeData();
262 node->id = render_accessibility->GenerateAXID(); 276 node->id = render_accessibility->GenerateAXID();
263 node->role = role; 277 node->role = role;
264 node->state = 1 << ui::AX_STATE_READ_ONLY; 278 node->state = 1 << ui::AX_STATE_READ_ONLY;
279
280 // All nodes other than the first one have coordinates relative to
281 // the first node.
282 if (nodes_.size() > 0)
283 node->offset_container_id = nodes_[0]->id;
284
265 nodes_.push_back(base::WrapUnique(node)); 285 nodes_.push_back(base::WrapUnique(node));
286
266 return node; 287 return node;
267 } 288 }
268 289
269 float PdfAccessibilityTree::GetDeviceScaleFactor() const { 290 float PdfAccessibilityTree::GetDeviceScaleFactor() const {
270 content::RenderFrame* render_frame = 291 content::RenderFrame* render_frame =
271 host_->GetRenderFrameForInstance(instance_); 292 host_->GetRenderFrameForInstance(instance_);
272 DCHECK(render_frame); 293 DCHECK(render_frame);
273 return render_frame->GetRenderView()->GetDeviceScaleFactor(); 294 return render_frame->GetRenderView()->GetDeviceScaleFactor();
274 } 295 }
275 296
276 content::RenderAccessibility* PdfAccessibilityTree::GetRenderAccessibility() { 297 content::RenderAccessibility* PdfAccessibilityTree::GetRenderAccessibility() {
277 content::RenderFrame* render_frame = 298 content::RenderFrame* render_frame =
278 host_->GetRenderFrameForInstance(instance_); 299 host_->GetRenderFrameForInstance(instance_);
279 return render_frame ? render_frame->GetRenderAccessibility() : nullptr; 300 return render_frame ? render_frame->GetRenderAccessibility() : nullptr;
280 } 301 }
281 302
303 gfx::Transform* PdfAccessibilityTree::MakeTransformFromViewInfo() {
304 gfx::Transform* transform = new gfx::Transform();
305 float scale_factor = zoom_ / GetDeviceScaleFactor();
306 transform->Scale(scale_factor, scale_factor);
307 transform->Translate(offset_);
308 transform->Translate(-scroll_);
309 return transform;
310 }
311
282 // 312 //
283 // AXTreeSource implementation. 313 // AXTreeSource implementation.
284 // 314 //
285 315
286 bool PdfAccessibilityTree::GetTreeData(ui::AXTreeData* tree_data) const { 316 bool PdfAccessibilityTree::GetTreeData(ui::AXTreeData* tree_data) const {
287 return false; 317 return false;
288 } 318 }
289 319
290 ui::AXNode* PdfAccessibilityTree::GetRoot() const { 320 ui::AXNode* PdfAccessibilityTree::GetRoot() const {
291 return tree_.root(); 321 return tree_.root();
(...skipping 30 matching lines...) Expand all
322 const ui::AXNode* PdfAccessibilityTree::GetNull() const { 352 const ui::AXNode* PdfAccessibilityTree::GetNull() const {
323 return nullptr; 353 return nullptr;
324 } 354 }
325 355
326 void PdfAccessibilityTree::SerializeNode( 356 void PdfAccessibilityTree::SerializeNode(
327 const ui::AXNode* node, ui::AXNodeData* out_data) const { 357 const ui::AXNode* node, ui::AXNodeData* out_data) const {
328 *out_data = node->data(); 358 *out_data = node->data();
329 } 359 }
330 360
331 } // namespace pdf 361 } // namespace pdf
OLDNEW
« no previous file with comments | « components/pdf/renderer/pdf_accessibility_tree.h ('k') | content/public/renderer/render_accessibility.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698