2780static RetainPtr<CGColorRef> colorWithComponents(int r, int g, int b, int a)
2781{
2782 CGFloat components[4] = { CGFloat(r / 255.0), CGFloat(g / 255.0), CGFloat(b / 255.0), CGFloat(a / 100.0) };
2783 return adoptCF(CGColorCreate(sRGBColorSpaceRef(), components));
2784}
2785
2786static RetainPtr<CGColorRef> colorForStyle(DocumentMarkerLineStyle style, bool useDarkMode)
2787{
2788 switch (style) {
2789 // Red.
2790 case DocumentMarkerLineStyle::Spelling:
2791 return useDarkMode ? colorWithComponents(255, 140, 140, 85) : colorWithComponents(255, 59, 48, 75);
2792 // Blue.
2793 case DocumentMarkerLineStyle::DictationAlternatives:
2794 case DocumentMarkerLineStyle::TextCheckingDictationPhraseWithAlternatives:
2795 case DocumentMarkerLineStyle::AutocorrectionReplacement:
2796 return useDarkMode ? colorWithComponents(40, 145, 255, 85) : colorWithComponents(0, 122, 255, 75);
2797 // Green.
2798 case DocumentMarkerLineStyle::Grammar:
2799 return useDarkMode ? colorWithComponents(50, 215, 75, 85) : colorWithComponents(25, 175, 50, 75);
2800 }
2801}
2802
2803void RenderThemeMac::drawLineForDocumentMarker(const RenderText& renderer, GraphicsContext& context, const FloatPoint& origin, float width, DocumentMarkerLineStyle style)
2804{
2805 if (context.paintingDisabled())
2806 return;
2807
2808 auto patternWidth = cMisspellingLinePatternWidth;
2809 auto patternHeight = cMisspellingLineThickness;
2810 auto dotSize = CGSizeMake(patternHeight, patternHeight);
2811 auto circleColor = colorForStyle(style, renderer.page().useSystemAppearance() && renderer.page().useDarkAppearance());
2812
2813 // Make sure to draw only complete dots allowing slightly more considering that the pattern ends with a transparent pixel.
2814 FloatPoint offsetPoint = origin;
2815 float widthMod = fmodf(width, patternWidth);
2816 if (patternWidth - widthMod > cMisspellingLinePatternGapWidth) {
2817 float gapIncludeWidth = 0;
2818 if (width > patternWidth)
2819 gapIncludeWidth = cMisspellingLinePatternGapWidth;
2820 offsetPoint.move(floor((widthMod + gapIncludeWidth) / 2), 0);
2821 width -= widthMod;
2822 }
2823
2824 CGContextRef ctx = context.platformContext();
2825 CGContextStateSaver stateSaver { ctx };
2826 CGContextSetFillColorWithColor(ctx, circleColor.get());
2827 for (int numberOfDots = 0; numberOfDots * patternWidth < width; ++numberOfDots)
2828 CGContextAddEllipseInRect(ctx, CGRectMake(offsetPoint.x() + numberOfDots * patternWidth, offsetPoint.y(), dotSize.width, dotSize.height));
2829 CGContextSetCompositeOperation(ctx, kCGCompositeSover);
2830 CGContextFillPath(ctx);
2831}
2832