Skip to content

Commit

Permalink
[css] optimize text-decoration-line (for #2)
Browse files Browse the repository at this point in the history
  • Loading branch information
benoitkugler committed Jan 17, 2025
1 parent 409b1f0 commit 64a278f
Show file tree
Hide file tree
Showing 9 changed files with 37 additions and 29 deletions.
2 changes: 1 addition & 1 deletion css/properties/properties.go
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ var InitialValues = Properties{
PRowGap: DimOrS{S: "normal"},

// Text Decoration Module 3 (CR): https://www.w3.org/TR/css-text-decor-3/
PTextDecorationLine: Decorations{},
PTextDecorationLine: Decorations(0),
PTextDecorationColor: CurrentColor,
PTextDecorationStyle: String("solid"),

Expand Down
21 changes: 10 additions & 11 deletions css/properties/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"

pa "github.com/benoitkugler/webrender/css/parser"
"github.com/benoitkugler/webrender/utils"
)

// ------------- Top levels types, implementing CssProperty ------------
Expand Down Expand Up @@ -44,16 +43,18 @@ type SContent struct {

type Display [3]string

type Decorations utils.Set
// Decorations zero value means "none"
type Decorations uint8

const (
Underline Decorations = 1 << iota
Overline
LineThrough
Blink
)

// Union return the union of [s] and [other]
func (dec Decorations) Union(other Decorations) Decorations {
out := utils.Set(dec).Copy()
for k := range other {
out[k] = utils.Has
}
return Decorations(out)
}
func (dec Decorations) Union(other Decorations) Decorations { return dec | other }

type Transforms []SDimensions

Expand Down Expand Up @@ -475,8 +476,6 @@ func (v Marks) IsNone() bool {
return v == Marks{}
}

func (v Decorations) IsNone() bool { return len(v) == 0 }

func (v NamedString) IsNone() bool {
return v == NamedString{}
}
Expand Down
9 changes: 4 additions & 5 deletions css/validation/expanders_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"testing"

pr "github.com/benoitkugler/webrender/css/properties"
"github.com/benoitkugler/webrender/utils"
tu "github.com/benoitkugler/webrender/utils/testutils"
)

Expand All @@ -25,17 +24,17 @@ func TestTextDecoration(t *testing.T) {
defer tu.CaptureLogs().AssertNoLogs(t)

assertValidDict(t, "text-decoration: none", toValidated(pr.Properties{
pr.PTextDecorationLine: pr.Decorations{},
pr.PTextDecorationLine: pr.Decorations(0),
}))
assertValidDict(t, "text-decoration: overline", toValidated(pr.Properties{
pr.PTextDecorationLine: pr.Decorations(utils.NewSet("overline")),
pr.PTextDecorationLine: pr.Overline,
}))
assertValidDict(t, "text-decoration: overline solid", toValidated(pr.Properties{
pr.PTextDecorationLine: pr.Decorations(utils.NewSet("overline")),
pr.PTextDecorationLine: pr.Overline,
pr.PTextDecorationStyle: pr.String("solid"),
}))
assertValidDict(t, "text-decoration: overline blink line-through", toValidated(pr.Properties{
pr.PTextDecorationLine: pr.Decorations(utils.NewSet("blink", "line-through", "overline")),
pr.PTextDecorationLine: pr.Blink | pr.LineThrough | pr.Overline,
}))
assertValidDict(t, "text-decoration: red", toValidated(pr.Properties{
pr.PTextDecorationColor: pr.NewColor(1, 0, 0, 1),
Expand Down
16 changes: 13 additions & 3 deletions css/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -2561,19 +2561,29 @@ func textAlignLast(tokens []Token, _ string) pr.CssProperty {
// “text-decoration-line“ property validation.
func textDecorationLine(tokens []Token, _ string) pr.CssProperty {
uniqKeywords := utils.Set{}
var out pr.Decorations
valid := true
for _, token := range tokens {
keyword := getKeyword(token)
if !(keyword == "underline" || keyword == "overline" || keyword == "line-through" || keyword == "blink") {
switch keyword {
case "underline":
out |= pr.Underline
case "overline":
out |= pr.Overline
case "line-through":
out |= pr.LineThrough
case "blink":
out |= pr.Blink
default:
valid = false
}
uniqKeywords.Add(keyword)
}
if _, in := uniqKeywords["none"]; len(uniqKeywords) == 1 && in { // then uniqKeywords == {"none"}
return pr.Decorations{}
return out
}
if valid && len(uniqKeywords) == len(tokens) {
return pr.Decorations(uniqKeywords)
return out
}
return nil
}
Expand Down
6 changes: 3 additions & 3 deletions css/validation/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,14 @@ func TestSpacing(t *testing.T) {
func TestDecoration(t *testing.T) {
capt := tu.CaptureLogs()
assertValidDict(t, "text-decoration-line: none", toValidated(pr.Properties{
pr.PTextDecorationLine: pr.Decorations{},
pr.PTextDecorationLine: pr.Decorations(0),
}))
assertValidDict(t, "text-decoration-line: overline", toValidated(pr.Properties{
pr.PTextDecorationLine: pr.Decorations(utils.NewSet("overline")),
pr.PTextDecorationLine: pr.Overline,
}))
// blink is accepted but ignored
assertValidDict(t, "text-decoration-line: overline blink line-through", toValidated(pr.Properties{
pr.PTextDecorationLine: pr.Decorations(utils.NewSet("blink", "line-through", "overline")),
pr.PTextDecorationLine: pr.Blink | pr.LineThrough | pr.Overline,
}))

assertValidDict(t, "text-decoration-style: solid", toValidated(pr.Properties{
Expand Down
6 changes: 3 additions & 3 deletions html/document/draw.go
Original file line number Diff line number Diff line change
Expand Up @@ -1562,12 +1562,12 @@ func (ctx drawContext) drawText(textbox *bo.TextBox, offsetX fl, textOverflow st

metrics := textbox.TextLayout.Metrics()

if utils.Set(decoration).Has("overline") {
if decoration&pr.Overline != 0 {
thickness := metrics.UnderlineThickness
offsetY = textbox.Baseline.V() - pr.Float(metrics.Ascent) + pr.Float(thickness)/2
ctx.drawTextDecoration(textbox, offsetX, pr.Fl(offsetY), thickness, color.RGBA)
}
if utils.Set(decoration).Has("underline") {
if decoration&pr.Underline != 0 {
thickness := metrics.UnderlineThickness
offsetY = textbox.Baseline.V() - pr.Float(metrics.UnderlinePosition) + pr.Float(thickness)/2
ctx.drawTextDecoration(textbox, offsetX, pr.Fl(offsetY), thickness, color.RGBA)
Expand All @@ -1579,7 +1579,7 @@ func (ctx drawContext) drawText(textbox *bo.TextBox, offsetX fl, textOverflow st
textbox.TextLayout.ApplyJustification()
ctx.drawFirstLine(textbox, textOverflow, blockEllipsis, x, y)

if utils.Set(decoration).Has("line-through") {
if decoration&pr.LineThrough != 0 {
thickness := metrics.StrikethroughThickness
offsetY = textbox.Baseline.V() - pr.Float(metrics.StrikethroughPosition)
ctx.drawTextDecoration(textbox, offsetX, pr.Fl(offsetY), thickness, color.RGBA)
Expand Down
2 changes: 1 addition & 1 deletion html/tree/style_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ func TestAnnotateDocument(t *testing.T) {
assertProp(t, li0, pr.PMarginBottom, pr.Dimension{Value: 16, Unit: pr.Px}.ToValue())
assertProp(t, li0, pr.PMarginLeft, pr.Dimension{Value: 32, Unit: pr.Px}.ToValue()) // 4em)

assertProp(t, a, pr.PTextDecorationLine, pr.Decorations(utils.NewSet("underline")))
assertProp(t, a, pr.PTextDecorationLine, pr.Underline)
assertProp(t, a, pr.PFontWeight, pr.IntString{Int: 900})
assertProp(t, a, pr.PFontSize, pr.FToV(24)) // 300% of 8px)
assertProp(t, a, pr.PPaddingTop, pr.Dimension{Value: 1, Unit: pr.Px}.ToValue())
Expand Down
2 changes: 1 addition & 1 deletion text/engine_pango.go
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ func (p *TextLayoutPango) setup(fonts FontConfiguration, style *TextStyle) {
p.Layout = *pango.NewLayout(pc)
p.Layout.SetFontDescription(&fontDesc)

if !style.TextDecorationLine.IsNone() {
if style.TextDecorationLine != 0 {
metrics := pc.GetMetrics(&fontDesc, lang)
p.metrics = &LineMetrics{
Ascent: PangoUnitsToFloat(metrics.Ascent),
Expand Down
2 changes: 1 addition & 1 deletion text/style_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestDefaultValues(t *testing.T) {

tu.AssertEqual(t, ts.FontLanguageOverride, fontLanguageOverride{})
tu.AssertEqual(t, ts.Lang, "")
tu.AssertEqual(t, ts.TextDecorationLine, pr.Decorations{})
tu.AssertEqual(t, ts.TextDecorationLine, pr.Decorations(0))
tu.AssertEqual(t, ts.WhiteSpace, WNormal)
tu.AssertEqual(t, ts.LetterSpacing, pr.Fl(0))
tu.AssertEqual(t, ts.FontFeatures, []Feature(nil))
Expand Down

0 comments on commit 64a278f

Please sign in to comment.