1 // Copyright 2018 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.
4 
5 #include "ash/magnifier/magnifier_utils.h"
6 
7 #include <algorithm>
8 #include <cmath>
9 
10 #include "ash/shell.h"
11 #include "base/check_op.h"
12 #include "base/numerics/ranges.h"
13 #include "ui/aura/window.h"
14 #include "ui/aura/window_tree_host.h"
15 #include "ui/base/ime/chromeos/ime_bridge.h"
16 
17 namespace ash {
18 namespace magnifier_utils {
19 
20 namespace {
21 
22 // Converts the given |scale| to an index such that
23 // `kMagnificationScaleFactor ^ index = scale`.
IndexFromScale(float scale)24 int IndexFromScale(float scale) {
25   // Remember from the Logarithm rules:
26   // logBar(Foo) = log2(Foo) / log2(Bar).
27   return std::round(std::log(scale) / std::log(kMagnificationScaleFactor));
28 }
29 
30 }  // namespace
31 
GetScaleFromScroll(float linear_offset,float current_scale,float min_scale,float max_scale)32 float GetScaleFromScroll(float linear_offset,
33                          float current_scale,
34                          float min_scale,
35                          float max_scale) {
36   DCHECK_GE(current_scale, min_scale);
37   DCHECK_LE(current_scale, max_scale);
38 
39   // Convert the current scale back to its corresponding linear scale according
40   // to the formula `scale = (max - min) * offset ^ 2 + min`.
41   const float scale_range = max_scale - min_scale;
42   float linear_adjustment =
43       std::sqrt((current_scale - min_scale) / scale_range);
44   // Add the new linear offset.
45   linear_adjustment += linear_offset;
46 
47   // Convert back to the exponential scale.
48   return scale_range * linear_adjustment * linear_adjustment + min_scale;
49 }
50 
GetNextMagnifierScaleValue(int delta_index,float current_scale,float min_scale,float max_scale)51 float GetNextMagnifierScaleValue(int delta_index,
52                                  float current_scale,
53                                  float min_scale,
54                                  float max_scale) {
55   const int current_index = IndexFromScale(current_scale);
56   const int new_scale_index = current_index + delta_index;
57   const float new_scale = std::pow(kMagnificationScaleFactor, new_scale_index);
58   return base::ClampToRange(new_scale, min_scale, max_scale);
59 }
60 
GetInputMethod(aura::Window * root_window)61 ui::InputMethod* GetInputMethod(aura::Window* root_window) {
62   ui::IMEBridge* bridge = ui::IMEBridge::Get();
63   if (bridge && bridge->GetInputContextHandler())
64     return bridge->GetInputContextHandler()->GetInputMethod();
65 
66   if (root_window && root_window->GetHost())
67     return root_window->GetHost()->GetInputMethod();
68 
69   // Needed by a handful of browser tests that use MockInputMethod.
70   return Shell::GetRootWindowForNewWindows()->GetHost()->GetInputMethod();
71 }
72 
73 }  // namespace magnifier_utils
74 }  // namespace ash
75