chromium/third_party/blink/renderer/core/paint/box_border_painter.cc

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/core/paint/box_border_painter.h"

#include <algorithm>

#include "third_party/blink/renderer/core/paint/box_painter.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_auto_dark_mode.h"
#include "third_party/blink/renderer/core/paint/rounded_border_geometry.h"
#include "third_party/blink/renderer/core/style/border_edge.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/graphics/stroke_data.h"
#include "third_party/blink/renderer/platform/graphics/styled_stroke_data.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/geometry/rect_conversions.h"

namespace blink {

namespace {

enum BorderEdgeFlag {};

inline BorderEdgeFlag EdgeFlagForSide(BoxSide side) {}

inline bool IncludesEdge(BorderEdgeFlags flags, BoxSide side) {}

inline bool IncludesAdjacentEdges(BorderEdgeFlags flags) {}

inline bool StyleRequiresClipPolygon(EBorderStyle style) {}

inline bool BorderStyleFillsBorderArea(EBorderStyle style) {}

inline bool BorderStyleHasInnerDetail(EBorderStyle style) {}

inline bool BorderStyleIsDottedOrDashed(EBorderStyle style) {}

// BorderStyleOutset darkens the bottom and right (and maybe lightens the top
// and left) BorderStyleInset darkens the top and left (and maybe lightens the
// bottom and right).
inline bool BorderStyleHasUnmatchedColorsAtCorner(EBorderStyle style,
                                                  BoxSide side,
                                                  BoxSide adjacent_side) {}

inline bool BorderWillArcInnerEdge(const gfx::SizeF& first_radius,
                                   const gfx::SizeF& second_radius) {}

inline bool WillOverdraw(BoxSide side,
                         EBorderStyle style,
                         BorderEdgeFlags completed_edges) {}

inline bool BorderStylesRequireMiter(BoxSide side,
                                     BoxSide adjacent_side,
                                     EBorderStyle style,
                                     EBorderStyle adjacent_style) {}

void SetToRightSideRect(gfx::Rect& rect, int edge_width) {}

void SetToBottomSideRect(gfx::Rect& rect, int edge_width) {}

gfx::Rect CalculateSideRect(const FloatRoundedRect& outer_border,
                            const BorderEdge& edge,
                            BoxSide side) {}

FloatRoundedRect CalculateAdjustedInnerBorder(
    const FloatRoundedRect& inner_border,
    BoxSide side) {}

void DrawSolidBorderRect(GraphicsContext& context,
                         const gfx::Rect& border_rect,
                         int border_width,
                         const Color& color,
                         const AutoDarkMode& auto_dark_mode) {}

void DrawBleedAdjustedDRRect(GraphicsContext& context,
                             BackgroundBleedAvoidance bleed_avoidance,
                             const FloatRoundedRect& outer,
                             const FloatRoundedRect& inner,
                             Color color,
                             const AutoDarkMode& auto_dark_mode) {}

// The LUTs below assume specific enum values.
static_assert;
static_assert;
static_assert;
static_assert;
static_assert;
static_assert;
static_assert;
static_assert;
static_assert;
static_assert;

static_assert;
static_assert;
static_assert;
static_assert;

// Style-based paint order: non-solid edges (dashed/dotted/double) are painted
// before solid edges (inset/outset/groove/ridge/solid) to maximize overdraw
// opportunities.
const auto kStylePriority =;

// Given the same style, prefer drawing in non-adjacent order to minimize the
// number of sides which require miters.
const auto kSidePriority =;

// Edges sharing the same opacity. Stores both a side list and an edge bitfield
// to support constant time iteration + membership tests.
struct OpacityGroup {};

void ClipPolygon(GraphicsContext& context,
                 base::span<const gfx::PointF> vertices,
                 bool antialiased) {}

void DrawDashedOrDottedBoxSide(GraphicsContext& context,
                               int x1,
                               int y1,
                               int x2,
                               int y2,
                               BoxSide side,
                               Color color,
                               int thickness,
                               EBorderStyle style,
                               bool antialias,
                               const AutoDarkMode& auto_dark_mode) {}

void DrawLineForBoxSide(GraphicsContext& context,
                        int x1,
                        int y1,
                        int x2,
                        int y2,
                        BoxSide side,
                        Color color,
                        EBorderStyle style,
                        int adjacent_width1,
                        int adjacent_width2,
                        bool antialias,
                        const AutoDarkMode& auto_dark_mode);

Color CalculateBorderStyleColor(const EBorderStyle& style,
                                const BoxSide& side,
                                const Color& color) {}

void DrawDoubleBoxSide(GraphicsContext& context,
                       int x1,
                       int y1,
                       int x2,
                       int y2,
                       int length,
                       BoxSide side,
                       Color color,
                       int thickness,
                       int adjacent_width1,
                       int adjacent_width2,
                       bool antialias,
                       const AutoDarkMode& auto_dark_mode) {}

void DrawRidgeOrGrooveBoxSide(GraphicsContext& context,
                              int x1,
                              int y1,
                              int x2,
                              int y2,
                              BoxSide side,
                              Color color,
                              EBorderStyle style,
                              int adjacent_width1,
                              int adjacent_width2,
                              bool antialias,
                              const AutoDarkMode& auto_dark_mode) {}

void FillQuad(GraphicsContext& context,
              const gfx::QuadF& quad,
              const Color& color,
              bool antialias,
              const AutoDarkMode& auto_dark_mode) {}

void DrawSolidBoxSide(GraphicsContext& context,
                      int x1,
                      int y1,
                      int x2,
                      int y2,
                      BoxSide side,
                      Color color,
                      int adjacent_width1,
                      int adjacent_width2,
                      bool antialias,
                      const AutoDarkMode& auto_dark_mode) {}

void DrawLineForBoxSide(GraphicsContext& context,
                        int x1,
                        int y1,
                        int x2,
                        int y2,
                        BoxSide side,
                        Color color,
                        EBorderStyle style,
                        int adjacent_width1,
                        int adjacent_width2,
                        bool antialias,
                        const AutoDarkMode& auto_dark_mode) {}

void FindIntersection(const gfx::PointF& p1,
                      const gfx::PointF& p2,
                      const gfx::PointF& d1,
                      const gfx::PointF& d2,
                      gfx::PointF& intersection) {}

}  // anonymous namespace

// Holds edges grouped by opacity and sorted in paint order.
struct BoxBorderPainter::ComplexBorderInfo {};

void BoxBorderPainter::DrawDoubleBorder() const {}

bool BoxBorderPainter::PaintBorderFastPath() const {}

BoxBorderPainter::BoxBorderPainter(GraphicsContext& context,
                                   const PhysicalRect& border_rect,
                                   const ComputedStyle& style,
                                   BackgroundBleedAvoidance bleed_avoidance,
                                   PhysicalBoxSides sides_to_include)
    :{}

BoxBorderPainter::BoxBorderPainter(GraphicsContext& context,
                                   const ComputedStyle& style,
                                   const PhysicalRect& border_rect,
                                   int width,
                                   const PhysicalBoxStrut& inner_outsets)
    :{}

void BoxBorderPainter::ComputeBorderProperties() {}

void BoxBorderPainter::Paint() const {}

// In order to maximize the use of overdraw as a corner seam avoidance
// technique, we draw translucent border sides using the following algorithm:
//
//   1) cluster sides sharing the same opacity into "opacity groups"
//      [ComplexBorderInfo]
//   2) sort groups in increasing opacity order [ComplexBorderInfo]
//   3) reverse-iterate over groups (decreasing opacity order), pushing nested
//      transparency layers with adjusted/relative opacity [paintOpacityGroup]
//   4) iterate over groups (increasing opacity order), painting actual group
//      contents and then ending their corresponding transparency layer
//      [PaintOpacityGroup]
//
// Layers are created in decreasing opacity order (top -> bottom), while actual
// border sides are drawn in increasing opacity order (bottom -> top). At each
// level, opacity is adjusted to account for accumulated/ancestor layer alpha.
// Because opacity is applied via layers, the actual draw paint is opaque.
//
// As an example, let's consider a border with the following sides/opacities:
//
//   top:    1.0
//   right:  0.25
//   bottom: 0.5
//   left:   0.25
//
// These are grouped and sorted in ComplexBorderInfo as follows:
//
//   group[0]: { alpha: 1.0,  sides: top }
//   group[1]: { alpha: 0.5,  sides: bottom }
//   group[2]: { alpha: 0.25, sides: right, left }
//
// Applying the algorithm yields the following paint sequence:
//
//                                // no layer needed for group 0 (alpha = 1)
//   beginLayer(0.5)              // layer for group 1
//     beginLayer(0.5)            // layer for group 2 (alpha: 0.5 * 0.5 = 0.25)
//       paintSides(right, left)  // paint group 2
//     endLayer
//     paintSides(bottom)         // paint group 1
//   endLayer
//   paintSides(top)              // paint group 0
//
// Note that we're always drawing using opaque paints on top of less-opaque
// content - hence we can use overdraw to mask portions of the previous sides.
//
BorderEdgeFlags BoxBorderPainter::PaintOpacityGroup(
    const ComplexBorderInfo& border_info,
    unsigned index,
    float effective_opacity) const {}

void BoxBorderPainter::PaintSide(const ComplexBorderInfo& border_info,
                                 BoxSide side,
                                 float alpha,
                                 BorderEdgeFlags completed_edges) const {}

BoxBorderPainter::MiterType BoxBorderPainter::ComputeMiter(
    BoxSide side,
    BoxSide adjacent_side,
    BorderEdgeFlags completed_edges) const {}

bool BoxBorderPainter::MitersRequireClipping(MiterType miter1,
                                             MiterType miter2,
                                             EBorderStyle style) {}

void BoxBorderPainter::PaintOneBorderSide(
    const gfx::Rect& side_rect,
    BoxSide side,
    BoxSide adjacent_side1,
    BoxSide adjacent_side2,
    const Path* path,
    Color color,
    BorderEdgeFlags completed_edges) const {}

void BoxBorderPainter::DrawBoxSideFromPath(const Path& border_path,
                                           int border_thickness,
                                           int stroke_thickness,
                                           BoxSide side,
                                           Color color,
                                           EBorderStyle border_style) const {}

void BoxBorderPainter::DrawDashedDottedBoxSideFromPath(
    int border_thickness,
    int stroke_thickness,
    Color color,
    EBorderStyle border_style) const {}

void BoxBorderPainter::DrawWideDottedBoxSideFromPath(
    const Path& border_path,
    int border_thickness) const {}

void BoxBorderPainter::DrawDoubleBoxSideFromPath(const Path& border_path,
                                                 int border_thickness,
                                                 int stroke_thickness,
                                                 BoxSide side,
                                                 Color color) const {}

void BoxBorderPainter::DrawRidgeGrooveBoxSideFromPath(
    const Path& border_path,
    int border_thickness,
    int stroke_thickness,
    BoxSide side,
    Color color,
    EBorderStyle border_style) const {}

gfx::Rect BoxBorderPainter::CalculateSideRectIncludingInner(
    BoxSide side) const {}

void BoxBorderPainter::ClipBorderSidePolygon(BoxSide side,
                                             MiterType first_miter,
                                             MiterType second_miter) const {}

PhysicalBoxStrut BoxBorderPainter::DoubleStripeOutsets(
    BorderEdge::DoubleBorderStripe stripe) const {}

PhysicalBoxStrut BoxBorderPainter::CenterOutsets() const {}

bool BoxBorderPainter::ColorsMatchAtCorner(BoxSide side,
                                           BoxSide adjacent_side) const {}

void BoxBorderPainter::DrawBoxSide(GraphicsContext& context,
                                   const gfx::Rect& snapped_edge_rect,
                                   BoxSide side,
                                   Color color,
                                   EBorderStyle style,
                                   const AutoDarkMode& auto_dark_mode) {}

}  // namespace blink