1/*
2 * Copyright (C) 2020 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "GraphicsContextExtras.h"
28
29#include "Color.h"
30#include "FloatRect.h"
31#include "FontCascade.h"
32#include "GraphicsContext.h"
33#include "TextRun.h"
34#include <wtf/text/WTFString.h>
35
36namespace WebCore {
37
38static inline void drawDebugBadgesInternal(GraphicsContext& context, const FloatRect& borderRect, const Vector<DebugBadge>& badges)
39{
40 auto cornerPoint = [](const FloatRect& borderRect, DebugBadge::Corner corner) {
41 auto point = borderRect.location();
42 if (corner == DebugBadge::Corner::TopRight || corner == DebugBadge::Corner::BottomRight)
43 point.move(borderRect.width(), 0);
44 if (corner == DebugBadge::Corner::BottomLeft || corner == DebugBadge::Corner::BottomRight)
45 point.move(0, borderRect.height());
46 return point;
47 };
48
49 auto cornerRect = [&](const FloatRect& borderRect, DebugBadge::Corner corner, const FloatSize size) {
50 auto point = cornerPoint(borderRect, corner);
51 if (corner == DebugBadge::Corner::TopRight || corner == DebugBadge::Corner::BottomRight)
52 point.move(-size.width(), 0);
53 if (corner == DebugBadge::Corner::BottomLeft || corner == DebugBadge::Corner::BottomRight)
54 point.move(0, -size.height());
55 return FloatRect(point, size);
56 };
57
58 auto drawDebugBadge = [&](GraphicsContext& context, const FloatRect& borderRect, const DebugBadge& badge) {
59 FontCascadeDescription fontDescription;
60 fontDescription.setOneFamily("Helvetica");
61 fontDescription.setSpecifiedSize(badge.fontSize);
62 fontDescription.setComputedSize(badge.fontSize);
63
64 FontCascade cascade(WTFMove(fontDescription));
65 cascade.update(nullptr);
66
67 const float horizontalMargin = badge.fontSize / 4;
68 const float verticalMargin = horizontalMargin / 2;
69
70 TextRun textRun(badge.text);
71 float textWidth = cascade.width(textRun);
72
73 FloatSize badgeSize(horizontalMargin * 2 + textWidth, verticalMargin * 2 + badge.fontSize);
74
75 auto badgeRect = cornerRect(borderRect, badge.corner, badgeSize);
76
77 context.setFillColor(badge.color);
78 context.fillRect(badgeRect);
79
80 context.setFillColor(badge.textColor);
81 context.drawText(cascade, textRun, FloatPoint(badgeRect.x() + horizontalMargin, badgeRect.y() + badge.fontSize));
82 };
83
84 for (auto badge : badges)
85 drawDebugBadge(context, borderRect, badge);
86}
87
88void drawDebugBadges(GraphicsContext& context, const FloatRect& borderRect, const Vector<DebugBadge>& badges)
89{
90 GraphicsContextStateSaver stateSaver(context);
91 FloatRect borderRectAdjusted = borderRect;
92 borderRectAdjusted.inflate(-1);
93 drawDebugBadgesInternal(context, borderRectAdjusted, badges);
94}
95
96void drawDebugBorderAndBadges(GraphicsContext& context, const FloatRect& borderRect, const Color& color, const Vector<DebugBadge>& badges)
97{
98 GraphicsContextStateSaver stateSaver(context);
99
100 FloatRect borderRectAdjusted = borderRect;
101 borderRectAdjusted.inflate(-1);
102
103 context.setStrokeColor(color);
104 context.setShouldAntialias(false);
105 context.strokeRect(borderRectAdjusted, 0.5);
106
107 drawDebugBadgesInternal(context, borderRectAdjusted, badges);
108}
109
110} // namespace WebCore