blob: 38ffeede1849992466738a271bf926ab6f20f5c6 [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "pdf/pdf_ink_metrics_handler.h"
#include <optional>
#include "base/containers/fixed_flat_map.h"
#include "base/metrics/histogram_functions.h"
#include "base/notreached.h"
#include "pdf/pdf_ink_brush.h"
#include "pdf/pdf_ink_conversions.h"
namespace chrome_pdf {
namespace {
// LINT.IfChange(PenSizes)
constexpr auto kPenSizes =
base::MakeFixedFlatMap<float, StrokeMetricBrushSize>({
{1.0f, StrokeMetricBrushSize::kExtraThin},
{2.0f, StrokeMetricBrushSize::kThin},
{3.0f, StrokeMetricBrushSize::kMedium},
{6.0f, StrokeMetricBrushSize::kThick},
{8.0f, StrokeMetricBrushSize::kExtraThick},
});
// LINT.ThenChange(//chrome/browser/resources/pdf/elements/ink_size_selector.ts:PenSizes)
// LINT.IfChange(HighlighterSizes)
constexpr auto kHighlighterSizes =
base::MakeFixedFlatMap<float, StrokeMetricBrushSize>({
{4.0f, StrokeMetricBrushSize::kExtraThin},
{6.0f, StrokeMetricBrushSize::kThin},
{8.0f, StrokeMetricBrushSize::kMedium},
{12.0f, StrokeMetricBrushSize::kThick},
{16.0f, StrokeMetricBrushSize::kExtraThick},
});
// LINT.ThenChange(//chrome/browser/resources/pdf/elements/ink_size_selector.ts:HighlighterSizes)
// LINT.IfChange(PenColors)
constexpr auto kPenColors =
base::MakeFixedFlatMap<SkColor, StrokeMetricPenColor>({
{SK_ColorBLACK, StrokeMetricPenColor::kBlack},
{SkColorSetRGB(0x5F, 0x63, 0x68), StrokeMetricPenColor::kDarkGrey2},
{SkColorSetRGB(0x9A, 0xA0, 0xA6), StrokeMetricPenColor::kDarkGrey1},
{SkColorSetRGB(0xDA, 0xDC, 0xE0), StrokeMetricPenColor::kLightGrey},
{SK_ColorWHITE, StrokeMetricPenColor::kWhite},
{SkColorSetRGB(0xF2, 0x8B, 0x82), StrokeMetricPenColor::kRed1},
{SkColorSetRGB(0xFD, 0xD6, 0x63), StrokeMetricPenColor::kYellow1},
{SkColorSetRGB(0x81, 0xC9, 0x95), StrokeMetricPenColor::kGreen1},
{SkColorSetRGB(0x8A, 0xB4, 0xF8), StrokeMetricPenColor::kBlue1},
{SkColorSetRGB(0xEE, 0xC9, 0xAE), StrokeMetricPenColor::kTan1},
{SkColorSetRGB(0xEA, 0x43, 0x35), StrokeMetricPenColor::kRed2},
{SkColorSetRGB(0xFB, 0xBC, 0x04), StrokeMetricPenColor::kYellow2},
{SkColorSetRGB(0x34, 0xA8, 0x53), StrokeMetricPenColor::kGreen2},
{SkColorSetRGB(0x42, 0x85, 0xF4), StrokeMetricPenColor::kBlue2},
{SkColorSetRGB(0xE2, 0xA1, 0x85), StrokeMetricPenColor::kTan2},
{SkColorSetRGB(0xC5, 0x22, 0x1F), StrokeMetricPenColor::kRed3},
{SkColorSetRGB(0xF2, 0x99, 0x00), StrokeMetricPenColor::kYellow3},
{SkColorSetRGB(0x18, 0x80, 0x38), StrokeMetricPenColor::kGreen3},
{SkColorSetRGB(0x19, 0x67, 0xD2), StrokeMetricPenColor::kBlue3},
{SkColorSetRGB(0x88, 0x59, 0x45), StrokeMetricPenColor::kTan3},
});
// LINT.ThenChange(//chrome/browser/resources/pdf/elements//ink_annotation_brush_mixin.ts:PenColors)
// LINT.IfChange(HighlighterColors)
constexpr auto kHighlighterColors =
base::MakeFixedFlatMap<SkColor, StrokeMetricHighlighterColor>({
{SkColorSetRGB(0xF2, 0x8B, 0x82),
StrokeMetricHighlighterColor::kLightRed},
{SkColorSetRGB(0xFD, 0xD6, 0x63),
StrokeMetricHighlighterColor::kLightYellow},
{SkColorSetRGB(0x34, 0xA8, 0x53),
StrokeMetricHighlighterColor::kLightGreen},
{SkColorSetRGB(0x42, 0x85, 0xF4),
StrokeMetricHighlighterColor::kLightBlue},
{SkColorSetRGB(0xFF, 0xAE, 0x80),
StrokeMetricHighlighterColor::kLightOrange},
{SkColorSetRGB(0xD9, 0x30, 0x25), StrokeMetricHighlighterColor::kRed},
{SkColorSetRGB(0xDD, 0xF3, 0x00),
StrokeMetricHighlighterColor::kYellow},
{SkColorSetRGB(0x25, 0xE3, 0x87), StrokeMetricHighlighterColor::kGreen},
{SkColorSetRGB(0x53, 0x79, 0xFF), StrokeMetricHighlighterColor::kBlue},
{SkColorSetRGB(0xFF, 0x63, 0x0C),
StrokeMetricHighlighterColor::kOrange},
});
// LINT.ThenChange(//chrome/browser/resources/pdf/elements//ink_annotation_brush_mixin.ts:HighlighterColors)
constexpr char kStrokeInputDeviceMetricName[] = "PDF.Ink2StrokeInputDeviceType";
void ReportStrokeTypeAndMaybeSize(StrokeMetricBrushType type,
std::optional<StrokeMetricBrushSize> size) {
base::UmaHistogramEnumeration("PDF.Ink2StrokeBrushType", type);
const char* size_metric = nullptr;
switch (type) {
case StrokeMetricBrushType::kPen:
size_metric = "PDF.Ink2StrokePenSize";
break;
case StrokeMetricBrushType::kHighlighter:
size_metric = "PDF.Ink2StrokeHighlighterSize";
break;
case StrokeMetricBrushType::kEraser:
CHECK(!size.has_value());
return;
}
CHECK(size_metric);
base::UmaHistogramEnumeration(size_metric, size.value());
}
StrokeMetricInputDeviceType GetStrokeInputDeviceType(
ink::StrokeInput::ToolType tool_type) {
switch (tool_type) {
case ink::StrokeInput::ToolType::kUnknown:
NOTREACHED();
case ink::StrokeInput::ToolType::kMouse:
return StrokeMetricInputDeviceType::kMouse;
case ink::StrokeInput::ToolType::kTouch:
return StrokeMetricInputDeviceType::kTouch;
case ink::StrokeInput::ToolType::kStylus:
return StrokeMetricInputDeviceType::kPen;
}
NOTREACHED();
}
} // namespace
void ReportDrawStroke(PdfInkBrush::Type type,
const ink::Brush& brush,
ink::StrokeInput::ToolType tool_type) {
bool is_pen = type == PdfInkBrush::Type::kPen;
const base::fixed_flat_map<float, StrokeMetricBrushSize, 5>& sizes =
is_pen ? kPenSizes : kHighlighterSizes;
auto size_iter = sizes.find(brush.GetSize());
CHECK(size_iter != sizes.end());
ReportStrokeTypeAndMaybeSize(is_pen ? StrokeMetricBrushType::kPen
: StrokeMetricBrushType::kHighlighter,
size_iter->second);
base::UmaHistogramEnumeration(kStrokeInputDeviceMetricName,
GetStrokeInputDeviceType(tool_type));
SkColor sk_color = GetSkColorFromInkBrush(brush);
if (is_pen) {
auto color_iter = kPenColors.find(sk_color);
CHECK(color_iter != kPenColors.end());
base::UmaHistogramEnumeration("PDF.Ink2StrokePenColor", color_iter->second);
} else {
auto color_iter = kHighlighterColors.find(sk_color);
CHECK(color_iter != kHighlighterColors.end());
base::UmaHistogramEnumeration("PDF.Ink2StrokeHighlighterColor",
color_iter->second);
}
}
void ReportEraseStroke(ink::StrokeInput::ToolType tool_type) {
ReportStrokeTypeAndMaybeSize(StrokeMetricBrushType::kEraser, std::nullopt);
base::UmaHistogramEnumeration(kStrokeInputDeviceMetricName,
GetStrokeInputDeviceType(tool_type));
}
void ReportTextHighlight(const ink::Brush& brush,
ink::StrokeInput::ToolType tool_type) {
SkColor sk_color = GetSkColorFromInkBrush(brush);
auto color_iter = kHighlighterColors.find(sk_color);
CHECK(color_iter != kHighlighterColors.end());
base::UmaHistogramEnumeration("PDF.Ink2TextHighlighterColor",
color_iter->second);
base::UmaHistogramEnumeration("PDF.Ink2TextHighlightInputDeviceType",
GetStrokeInputDeviceType(tool_type));
}
void RecordPdfLoadedWithV2InkAnnotations(
PDFLoadedWithV2InkAnnotations loaded_with_annotations) {
base::UmaHistogramEnumeration("PDF.LoadedWithV2InkAnnotations2",
loaded_with_annotations);
}
} // namespace chrome_pdf