Skip to content

Commit ce4915b

Browse files
Jon T Morancopybara-github
authored andcommitted
Switch on new spring model for highlighter and pressure pen v2
PiperOrigin-RevId: 677828345
1 parent 7cfc270 commit ce4915b

File tree

3 files changed

+62
-27
lines changed

3 files changed

+62
-27
lines changed

ink/brush/brush_family.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <cstdint>
1919
#include <optional>
2020
#include <string>
21+
#include <variant>
2122
#include <vector>
2223

2324
#include "absl/status/statusor.h"
@@ -44,6 +45,8 @@ namespace ink {
4445
// out the specification of the stock brushes using the new tip and paint types.
4546
class BrushFamily {
4647
public:
48+
// LINT.IfChange(input_model_types)
49+
4750
// The legacy spring-based input modeler, provided for backwards compatibility
4851
// with existing Ink clients.
4952
struct SpringModelV1 {};
@@ -62,6 +65,8 @@ class BrushFamily {
6265
// `BrushFamily::Create()` when none is specified.
6366
static InputModel DefaultInputModel();
6467

68+
// LINT.ThenChange(../strokes/internal/stroke_input_modeler.cc:input_model_types)
69+
6570
// Returns the maximum number of `BrushCoat`s that a `BrushFamily` is allowed
6671
// to have. Note that this limit may increase in the future.
6772
static uint32_t MaxBrushCoats();

ink/strokes/internal/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ cc_library(
5252
"//ink/types:physical_distance",
5353
"@com_google_absl//absl/cleanup",
5454
"@com_google_absl//absl/log:absl_check",
55+
"@com_google_absl//absl/log:check",
5556
"@com_google_absl//absl/types:span",
5657
"@ink_stroke_modeler//ink_stroke_modeler:params",
5758
"@ink_stroke_modeler//ink_stroke_modeler:stroke_modeler",

ink/strokes/internal/stroke_input_modeler.cc

Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@
1717
#include <algorithm>
1818
#include <cstddef>
1919
#include <optional>
20+
#include <type_traits>
2021
#include <variant>
2122
#include <vector>
2223

2324
#include "absl/cleanup/cleanup.h"
2425
#include "absl/log/absl_check.h"
26+
#include "absl/log/check.h"
2527
#include "ink/brush/brush_family.h"
2628
#include "ink/geometry/angle.h"
2729
#include "ink/geometry/point.h"
@@ -67,41 +69,68 @@ void StrokeInputModeler::StartStroke(const BrushFamily::InputModel& input_model,
6769

6870
namespace {
6971

72+
// LINT.IfChange(input_model_types)
73+
7074
stroke_model::PositionModelerParams::LoopContractionMitigationParameters
71-
GetLoopContractionMitigationParameters(
75+
MakeLoopContractionMitigationParameters(
7276
const BrushFamily::InputModel& input_model, float stroke_unit_length) {
73-
stroke_model::PositionModelerParams::LoopContractionMitigationParameters
74-
params;
75-
if (std::holds_alternative<BrushFamily::SpringModelV2>(input_model)) {
76-
params.is_enabled = true;
77-
params.speed_lower_bound =
78-
kDefaultLoopMitigationSpeedLowerBoundInCmPerSec / stroke_unit_length;
79-
params.speed_upper_bound =
80-
kDefaultLoopMitigationSpeedUpperBoundInCmPerSec / stroke_unit_length;
81-
params.interpolation_strength_at_speed_lower_bound =
82-
kDefaultLoopMitigationInterpolationStrengthAtSpeedLowerBound;
83-
params.interpolation_strength_at_speed_upper_bound =
84-
kDefaultLoopMitigationInterpolationStrengthAtSpeedUpperBound;
85-
params.min_speed_sampling_window =
86-
kDefaultLoopMitigationMinSpeedSamplingWindow;
87-
params.min_discrete_speed_samples =
88-
kDefaultLoopMitigationMinDiscreteSpeedSamples;
89-
} else if (std::holds_alternative<BrushFamily::SpringModelV1>(input_model)) {
90-
params.is_enabled = false;
91-
}
92-
return params;
77+
return std::visit(
78+
[stroke_unit_length](auto&& input_model)
79+
// NOLINTNEXTLINE(whitespace/line_length)
80+
-> stroke_model::PositionModelerParams::LoopContractionMitigationParameters {
81+
using ModelType = std::decay_t<decltype(input_model)>;
82+
if constexpr (std::is_same_v<ModelType, BrushFamily::SpringModelV2>) {
83+
return {
84+
.is_enabled = true,
85+
.speed_lower_bound =
86+
kDefaultLoopMitigationSpeedLowerBoundInCmPerSec /
87+
stroke_unit_length,
88+
.speed_upper_bound =
89+
kDefaultLoopMitigationSpeedUpperBoundInCmPerSec /
90+
stroke_unit_length,
91+
.interpolation_strength_at_speed_lower_bound =
92+
kDefaultLoopMitigationInterpolationStrengthAtSpeedLowerBound,
93+
.interpolation_strength_at_speed_upper_bound =
94+
kDefaultLoopMitigationInterpolationStrengthAtSpeedUpperBound,
95+
.min_speed_sampling_window =
96+
kDefaultLoopMitigationMinSpeedSamplingWindow,
97+
.min_discrete_speed_samples =
98+
kDefaultLoopMitigationMinDiscreteSpeedSamples};
99+
} else if constexpr (std::is_same_v<ModelType,
100+
BrushFamily::SpringModelV1>) {
101+
return {.is_enabled = false};
102+
}
103+
},
104+
input_model);
93105
}
94106

107+
stroke_model::StylusStateModelerParams MakeStylusStateModelerParams(
108+
const BrushFamily::InputModel& input_model) {
109+
return std::visit(
110+
[](auto&& input_model) -> stroke_model::StylusStateModelerParams {
111+
using ModelType = std::decay_t<decltype(input_model)>;
112+
if constexpr (std::is_same_v<ModelType, BrushFamily::SpringModelV2>) {
113+
return {.use_stroke_normal_projection = true,
114+
.min_input_samples = 10,
115+
.min_sample_duration = stroke_model::Duration(0.04)};
116+
} else if constexpr (std::is_same_v<ModelType,
117+
BrushFamily::SpringModelV1>) {
118+
return {.max_input_samples = 10,
119+
.use_stroke_normal_projection = false};
120+
}
121+
},
122+
input_model);
123+
}
124+
125+
// LINT.ThenChange(../../brush/brush_family.h:input_model_types)
126+
95127
void ResetStrokeModeler(stroke_model::StrokeModeler& stroke_modeler,
96128
const BrushFamily::InputModel& input_model,
97129
float brush_epsilon, float stroke_unit_length) {
98130
// The minimum output rate was chosen to match legacy behavior, which was
99131
// in turn chosen to upsample enough to produce relatively smooth-looking
100132
// curves on 60 Hz touchscreens.
101133
constexpr double kMinOutputRateHz = 180;
102-
stroke_model::PositionModelerParams::LoopContractionMitigationParameters
103-
loop_params = GetLoopContractionMitigationParameters(input_model,
104-
stroke_unit_length);
105134
// We use the defaults for `PositionModelerParams` and
106135
// `StylusStateModelerParams`.
107136
ABSL_CHECK_OK(stroke_modeler.Reset(
@@ -112,15 +141,15 @@ void ResetStrokeModeler(stroke_model::StrokeModeler& stroke_modeler,
112141
// We turn off loop contraction mitigation if the input model is not
113142
// spring model v2.
114143
.position_modeler_params = {.loop_contraction_mitigation_params =
115-
loop_params},
144+
MakeLoopContractionMitigationParameters(
145+
input_model, stroke_unit_length)},
116146
// `brush_epsilon` is used for the stopping distance because once end of
117147
// the stroke is with `brush_epsilon` of the final input, further changes
118148
// are not considered visually distinct.
119149
.sampling_params = {.min_output_rate = kMinOutputRateHz,
120150
.end_of_stroke_stopping_distance = brush_epsilon},
121151
// If we use loop mitigation, we need to use the new projection method.
122-
.stylus_state_modeler_params = {.use_stroke_normal_projection =
123-
loop_params.is_enabled},
152+
.stylus_state_modeler_params = MakeStylusStateModelerParams(input_model),
124153
// We disable the internal predictor on the `StrokeModeler`,
125154
// because it performs prediction after modeling. We wish to
126155
// accept external un-modeled prediction, as in the case of

0 commit comments

Comments
 (0)