Skip to content

Commit de731ed

Browse files
Ink Open Sourcecopybara-github
authored andcommitted
Introduce a range-based Append function in StrokeInputBatch
This allows appending a specific sub-range of `StrokeInput`s from one batch to another. PiperOrigin-RevId: 826053613
1 parent b146057 commit de731ed

File tree

3 files changed

+138
-0
lines changed

3 files changed

+138
-0
lines changed

ink/strokes/input/stroke_input_batch.cc

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,33 @@ absl::Status StrokeInputBatch::Append(const StrokeInputBatch& inputs) {
357357
return absl::OkStatus();
358358
}
359359

360+
absl::Status StrokeInputBatch::Append(const StrokeInputBatch& inputs,
361+
int start_index, int end_index) {
362+
ABSL_CHECK_GE(start_index, 0);
363+
ABSL_CHECK_LE(end_index, inputs.Size());
364+
if (start_index >= end_index) return absl::OkStatus();
365+
366+
if (!IsEmpty()) {
367+
if (absl::Status status =
368+
ValidateConsecutiveInputs(Last(), inputs.Get(start_index));
369+
!status.ok()) {
370+
return status;
371+
}
372+
} else {
373+
if (!data_.HasValue()) data_.Emplace();
374+
SetInlineFormatMetadata(inputs.Get(start_index));
375+
}
376+
377+
std::vector<float>& data = data_.MutableValue();
378+
const std::vector<float>& append_data = inputs.data_.Value();
379+
int stride = inputs.FloatsPerInput();
380+
data.insert(data.end(), append_data.begin() + start_index * stride,
381+
append_data.begin() + end_index * stride);
382+
size_ += end_index - start_index;
383+
384+
return absl::OkStatus();
385+
}
386+
360387
void StrokeInputBatch::Erase(int start, int count) {
361388
ABSL_DCHECK_GE(start, 0);
362389
ABSL_CHECK_LE(start, Size());

ink/strokes/input/stroke_input_batch.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@ class StrokeInputBatch {
144144
absl::Status Append(absl::Span<const StrokeInput> inputs);
145145
absl::Status Append(const StrokeInputBatch& inputs);
146146

147+
// Validates and appends the range of `inputs` from `start_index` (inclusive)
148+
// to `end_index` (exclusive).
149+
absl::Status Append(const StrokeInputBatch& inputs, int start_index,
150+
int end_index);
151+
147152
// Erases `count` elements beginning at `start`.
148153
//
149154
// If `start` + `count` is greater than `Size()`, then all elements from

ink/strokes/input/stroke_input_batch_test.cc

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,5 +1582,111 @@ TEST(StrokeInputBatchDeathTest, EraseWithStartOutOfBounds) {
15821582
EXPECT_DEATH_IF_SUPPORTED(batch->Erase(batch->Size() + 1, 1), "");
15831583
}
15841584

1585+
TEST(StrokeInputBatchTest, AppendRange) {
1586+
std::vector<StrokeInput> input_vector = MakeValidTestInputSequence();
1587+
absl::StatusOr<StrokeInputBatch> source_batch =
1588+
StrokeInputBatch::Create(input_vector);
1589+
ASSERT_EQ(source_batch.status(), absl::OkStatus());
1590+
1591+
// Append to an empty batch.
1592+
{
1593+
StrokeInputBatch batch;
1594+
EXPECT_EQ(absl::OkStatus(), batch.Append(*source_batch, 1, 4));
1595+
EXPECT_THAT(batch,
1596+
StrokeInputBatchIsArray(absl::MakeSpan(&input_vector[1], 3)));
1597+
}
1598+
1599+
// Append to a non-empty batch.
1600+
{
1601+
absl::StatusOr<StrokeInputBatch> batch =
1602+
StrokeInputBatch::Create({input_vector[0]});
1603+
ASSERT_EQ(batch.status(), absl::OkStatus());
1604+
EXPECT_EQ(absl::OkStatus(), batch->Append(*source_batch, 1, 3));
1605+
EXPECT_THAT(*batch,
1606+
StrokeInputBatchIsArray(absl::MakeSpan(&input_vector[0], 3)));
1607+
}
1608+
1609+
// Append an empty range.
1610+
{
1611+
absl::StatusOr<StrokeInputBatch> batch =
1612+
StrokeInputBatch::Create({input_vector[0]});
1613+
ASSERT_EQ(batch.status(), absl::OkStatus());
1614+
EXPECT_EQ(absl::OkStatus(), batch->Append(*source_batch, 2, 2));
1615+
EXPECT_THAT(*batch, StrokeInputBatchIsArray({input_vector[0]}));
1616+
}
1617+
1618+
// Append an invalid range where start > end.
1619+
{
1620+
absl::StatusOr<StrokeInputBatch> batch =
1621+
StrokeInputBatch::Create({input_vector[0]});
1622+
ASSERT_EQ(batch.status(), absl::OkStatus());
1623+
EXPECT_EQ(absl::OkStatus(), batch->Append(*source_batch, 3, 2));
1624+
EXPECT_THAT(*batch, StrokeInputBatchIsArray({input_vector[0]}));
1625+
}
1626+
1627+
// Append the full range.
1628+
{
1629+
StrokeInputBatch batch;
1630+
EXPECT_EQ(absl::OkStatus(),
1631+
batch.Append(*source_batch, 0, source_batch->Size()));
1632+
EXPECT_THAT(batch, StrokeInputBatchEq(*source_batch));
1633+
}
1634+
1635+
// Append inputs that do not have optional attributes specified.
1636+
{
1637+
StrokeInputBatch batch;
1638+
absl::StatusOr<StrokeInputBatch> source_batch =
1639+
StrokeInputBatch::Create({{.tool_type = StrokeInput::ToolType::kStylus,
1640+
.position = {10, 20},
1641+
.elapsed_time = Duration32::Seconds(5)},
1642+
{.tool_type = StrokeInput::ToolType::kStylus,
1643+
.position = {20, 30},
1644+
.elapsed_time = Duration32::Seconds(5)},
1645+
{.tool_type = StrokeInput::ToolType::kStylus,
1646+
.position = {30, 40},
1647+
.elapsed_time = Duration32::Seconds(5)}});
1648+
ASSERT_EQ(source_batch.status(), absl::OkStatus());
1649+
EXPECT_EQ(absl::OkStatus(), batch.Append(*source_batch, 1, 2));
1650+
EXPECT_THAT(batch, StrokeInputBatchIsArray({source_batch->Get(1)}));
1651+
}
1652+
}
1653+
1654+
TEST(StrokeInputBatchTest, AppendInvalidRange) {
1655+
std::vector<StrokeInput> input_vector = MakeValidTestInputSequence();
1656+
absl::StatusOr<StrokeInputBatch> source_batch =
1657+
StrokeInputBatch::Create(input_vector);
1658+
ASSERT_EQ(source_batch.status(), absl::OkStatus());
1659+
1660+
// Attempt to append a range that fails validation due to non-decreasing
1661+
// `elapsed_time`.
1662+
{
1663+
absl::StatusOr<StrokeInputBatch> batch =
1664+
StrokeInputBatch::Create({input_vector[3]});
1665+
ASSERT_EQ(batch.status(), absl::OkStatus());
1666+
absl::Status status = batch->Append(*source_batch, 1, 3);
1667+
EXPECT_EQ(status.code(), absl::StatusCode::kInvalidArgument);
1668+
EXPECT_THAT(status.message(), HasSubstr("non-decreasing `elapsed_time`"));
1669+
EXPECT_THAT(*batch, StrokeInputBatchIsArray({input_vector[3]}));
1670+
}
1671+
1672+
// Append a range with an incompatible format.
1673+
{
1674+
absl::StatusOr<StrokeInputBatch> batch =
1675+
StrokeInputBatch::Create({input_vector[0]});
1676+
ASSERT_EQ(batch.status(), absl::OkStatus());
1677+
1678+
std::vector<StrokeInput> different_format_vector =
1679+
MakeValidTestInputSequence(StrokeInput::ToolType::kMouse);
1680+
absl::StatusOr<StrokeInputBatch> different_format_batch =
1681+
StrokeInputBatch::Create(different_format_vector);
1682+
ASSERT_EQ(different_format_batch.status(), absl::OkStatus());
1683+
1684+
absl::Status status = batch->Append(*different_format_batch, 1, 3);
1685+
EXPECT_EQ(status.code(), absl::StatusCode::kInvalidArgument);
1686+
EXPECT_THAT(status.message(), HasSubstr("tool_type"));
1687+
EXPECT_THAT(*batch, StrokeInputBatchIsArray({input_vector[0]}));
1688+
}
1689+
}
1690+
15851691
} // namespace
15861692
} // namespace ink

0 commit comments

Comments
 (0)