forked from mbk-lab/rui_orig
2
0
Fork 0

Fixed background radial gradient

This commit is contained in:
Alexei Anoshenko 2022-05-01 13:27:04 +03:00
parent 26abd1f632
commit 61ee6c03f2
7 changed files with 181 additions and 62 deletions

View File

@ -67,31 +67,27 @@ func angleUnitSuffixes() map[AngleUnitType]string {
// StringToAngleUnit converts the string argument to AngleUnit // StringToAngleUnit converts the string argument to AngleUnit
func StringToAngleUnit(value string) (AngleUnit, bool) { func StringToAngleUnit(value string) (AngleUnit, bool) {
var angle AngleUnit angle, err := stringToAngleUnit(value)
ok, err := angle.setValue(value) if err != nil {
if !ok { ErrorLog(err.Error())
ErrorLog(err) return angle, false
} }
return angle, ok return angle, true
} }
func (angle *AngleUnit) setValue(value string) (bool, string) { func stringToAngleUnit(value string) (AngleUnit, error) {
value = strings.ToLower(strings.Trim(value, " \t\n\r")) value = strings.ToLower(strings.Trim(value, " \t\n\r"))
setValue := func(suffix string, unitType AngleUnitType) (bool, string) { setValue := func(suffix string, unitType AngleUnitType) (AngleUnit, error) {
val, err := strconv.ParseFloat(value[:len(value)-len(suffix)], 64) val, err := strconv.ParseFloat(value[:len(value)-len(suffix)], 64)
if err != nil { if err != nil {
return false, `AngleUnit.SetValue("` + value + `") error: ` + err.Error() return AngleUnit{}, err
} }
angle.Value = val return AngleUnit{Value: val, Type: unitType}, nil
angle.Type = unitType
return true, ""
} }
if value == "π" { if value == "π" {
angle.Value = 1 return AngleUnit{Value: 1, Type: PiRadian}, nil
angle.Type = PiRadian
return true, ""
} }
if strings.HasSuffix(value, "π") { if strings.HasSuffix(value, "π") {
@ -108,13 +104,12 @@ func (angle *AngleUnit) setValue(value string) (bool, string) {
} }
} }
if val, err := strconv.ParseFloat(value, 64); err == nil { val, err := strconv.ParseFloat(value, 64)
angle.Value = val if err != nil {
angle.Type = Radian return AngleUnit{}, err
return true, ""
} }
return false, `AngleUnit.SetValue("` + value + `") error: invalid argument` return AngleUnit{Value: val, Type: Radian}, nil
} }
// String - convert AngleUnit to string // String - convert AngleUnit to string

View File

@ -161,7 +161,8 @@ func (gradient *backgroundGradient) Set(tag string, value interface{}) bool {
return false return false
} }
return gradient.backgroundElement.Set(tag, value) ErrorLogF("Property %s is not supported by a background gradient", tag)
return false
} }
func (point *BackgroundGradientPoint) setValue(text string) bool { func (point *BackgroundGradientPoint) setValue(text string) bool {
@ -303,8 +304,10 @@ func (gradient *backgroundLinearGradient) Set(tag string, value interface{}) boo
return true return true
case string: case string:
var angle AngleUnit if gradient.setSimpleProperty(tag, value) {
if ok, _ := angle.setValue(value); ok { return true
}
if angle, ok := StringToAngleUnit(value); ok {
gradient.properties[Direction] = angle gradient.properties[Direction] = angle
return true return true
} }
@ -404,8 +407,60 @@ func (gradient *backgroundRadialGradient) Set(tag string, value interface{}) boo
switch tag { switch tag {
case RadialGradientRadius: case RadialGradientRadius:
switch value := value.(type) { switch value := value.(type) {
case string, SizeUnit: case []SizeUnit:
return gradient.propertyList.Set(RadialGradientRadius, value) switch len(value) {
case 0:
delete(gradient.properties, RadialGradientRadius)
return true
case 1:
if value[0].Type == Auto {
delete(gradient.properties, RadialGradientRadius)
} else {
gradient.properties[RadialGradientRadius] = value[0]
}
return true
default:
gradient.properties[RadialGradientRadius] = value
return true
}
case []interface{}:
switch len(value) {
case 0:
delete(gradient.properties, RadialGradientRadius)
return true
case 1:
return gradient.Set(RadialGradientRadius, value[0])
default:
gradient.properties[RadialGradientRadius] = value
return true
}
case string:
if gradient.setSimpleProperty(RadialGradientRadius, value) {
return true
}
if size, err := stringToSizeUnit(value); err == nil {
if size.Type == Auto {
delete(gradient.properties, RadialGradientRadius)
} else {
gradient.properties[RadialGradientRadius] = size
}
return true
}
return gradient.setEnumProperty(RadialGradientRadius, value, enumProperties[RadialGradientRadius].values)
case SizeUnit:
if value.Type == Auto {
delete(gradient.properties, RadialGradientRadius)
} else {
gradient.properties[RadialGradientRadius] = value
}
return true
case int: case int:
n := value n := value
@ -415,10 +470,7 @@ func (gradient *backgroundRadialGradient) Set(tag string, value interface{}) boo
} }
ErrorLogF(`Invalid value of "%s" property: %v`, tag, value) ErrorLogF(`Invalid value of "%s" property: %v`, tag, value)
case RadialGradientShape: case RadialGradientShape, CenterX, CenterY:
return gradient.propertyList.Set(RadialGradientShape, value)
case CenterX, CenterY:
return gradient.propertyList.Set(tag, value) return gradient.propertyList.Set(tag, value)
} }
@ -439,10 +491,11 @@ func (gradient *backgroundRadialGradient) cssStyle(session Session) string {
buffer.WriteString(`radial-gradient(`) buffer.WriteString(`radial-gradient(`)
} }
var shapeText string
if shape, ok := enumProperty(gradient, RadialGradientShape, session, EllipseGradient); ok && shape == CircleGradient { if shape, ok := enumProperty(gradient, RadialGradientShape, session, EllipseGradient); ok && shape == CircleGradient {
buffer.WriteString(`circle `) shapeText = `circle `
} else { } else {
buffer.WriteString(`ellipse `) shapeText = `ellipse `
} }
if value, ok := gradient.properties[RadialGradientRadius]; ok { if value, ok := gradient.properties[RadialGradientRadius]; ok {
@ -451,10 +504,16 @@ func (gradient *backgroundRadialGradient) cssStyle(session Session) string {
if text, ok := session.resolveConstants(value); ok { if text, ok := session.resolveConstants(value); ok {
values := enumProperties[RadialGradientRadius] values := enumProperties[RadialGradientRadius]
if n, ok := enumStringToInt(text, values.values, false); ok { if n, ok := enumStringToInt(text, values.values, false); ok {
buffer.WriteString(shapeText)
shapeText = ""
buffer.WriteString(values.cssValues[n]) buffer.WriteString(values.cssValues[n])
buffer.WriteString(" ") buffer.WriteString(" ")
} else { } else {
if r, ok := StringToSizeUnit(text); ok && r.Type != Auto { if r, ok := StringToSizeUnit(text); ok && r.Type != Auto {
buffer.WriteString("ellipse ")
shapeText = ""
buffer.WriteString(r.cssString(""))
buffer.WriteString(" ")
buffer.WriteString(r.cssString("")) buffer.WriteString(r.cssString(""))
buffer.WriteString(" ") buffer.WriteString(" ")
} else { } else {
@ -468,6 +527,8 @@ func (gradient *backgroundRadialGradient) cssStyle(session Session) string {
case int: case int:
values := enumProperties[RadialGradientRadius].cssValues values := enumProperties[RadialGradientRadius].cssValues
if value >= 0 && value < len(values) { if value >= 0 && value < len(values) {
buffer.WriteString(shapeText)
shapeText = ""
buffer.WriteString(values[value]) buffer.WriteString(values[value])
buffer.WriteString(" ") buffer.WriteString(" ")
} else { } else {
@ -476,8 +537,55 @@ func (gradient *backgroundRadialGradient) cssStyle(session Session) string {
case SizeUnit: case SizeUnit:
if value.Type != Auto { if value.Type != Auto {
buffer.WriteString("ellipse ")
shapeText = ""
buffer.WriteString(value.cssString("")) buffer.WriteString(value.cssString(""))
buffer.WriteString(" ") buffer.WriteString(" ")
buffer.WriteString(value.cssString(""))
buffer.WriteString(" ")
}
case []SizeUnit:
count := len(value)
if count > 2 {
count = 2
}
buffer.WriteString("ellipse ")
shapeText = ""
for i := 0; i < count; i++ {
buffer.WriteString(value[i].cssString("50%"))
buffer.WriteString(" ")
}
case []interface{}:
count := len(value)
if count > 2 {
count = 2
}
buffer.WriteString("ellipse ")
shapeText = ""
for i := 0; i < count; i++ {
if value[i] != nil {
switch value := value[i].(type) {
case SizeUnit:
buffer.WriteString(value.cssString("50%"))
buffer.WriteString(" ")
case string:
if text, ok := session.resolveConstants(value); ok {
if size, err := stringToSizeUnit(text); err == nil {
buffer.WriteString(size.cssString("50%"))
buffer.WriteString(" ")
} else {
buffer.WriteString("50% ")
}
} else {
buffer.WriteString("50% ")
}
}
} else {
buffer.WriteString("50% ")
}
} }
} }
} }
@ -485,6 +593,9 @@ func (gradient *backgroundRadialGradient) cssStyle(session Session) string {
x, _ := sizeProperty(gradient, CenterX, session) x, _ := sizeProperty(gradient, CenterX, session)
y, _ := sizeProperty(gradient, CenterX, session) y, _ := sizeProperty(gradient, CenterX, session)
if x.Type != Auto || y.Type != Auto { if x.Type != Auto || y.Type != Auto {
if shapeText != "" {
buffer.WriteString(shapeText)
}
buffer.WriteString("at ") buffer.WriteString("at ")
buffer.WriteString(x.cssString("50%")) buffer.WriteString(x.cssString("50%"))
buffer.WriteString(" ") buffer.WriteString(" ")

View File

@ -2,6 +2,7 @@ package rui
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"strconv" "strconv"
"strings" "strings"
@ -71,43 +72,49 @@ func (color Color) cssString() string {
// StringToColor converts the string argument to Color value // StringToColor converts the string argument to Color value
func StringToColor(text string) (Color, bool) { func StringToColor(text string) (Color, bool) {
color, err := stringToColor(text)
if err != nil {
ErrorLog(err.Error())
return color, false
}
return color, true
}
func stringToColor(text string) (Color, error) {
text = strings.Trim(text, " \t\r\n") text = strings.Trim(text, " \t\r\n")
if text == "" { if text == "" {
ErrorLog(`Invalid color value: ""`) return 0, errors.New(`Invalid color value: ""`)
return 0, false
} }
if text[0] == '#' { if text[0] == '#' {
c, err := strconv.ParseUint(text[1:], 16, 32) c, err := strconv.ParseUint(text[1:], 16, 32)
if err != nil { if err != nil {
ErrorLog("Set color value error: " + err.Error()) return 0, errors.New("Set color value error: " + err.Error())
return 0, false
} }
switch len(text) - 1 { switch len(text) - 1 {
case 8: case 8:
return Color(c), true return Color(c), nil
case 6: case 6:
return Color(c | 0xFF000000), true return Color(c | 0xFF000000), nil
case 4: case 4:
a := (c >> 12) & 0xF a := (c >> 12) & 0xF
r := (c >> 8) & 0xF r := (c >> 8) & 0xF
g := (c >> 4) & 0xF g := (c >> 4) & 0xF
b := c & 0xF b := c & 0xF
return Color((a << 28) | (a << 24) | (r << 20) | (r << 16) | (g << 12) | (g << 8) | (b << 4) | b), true return Color((a << 28) | (a << 24) | (r << 20) | (r << 16) | (g << 12) | (g << 8) | (b << 4) | b), nil
case 3: case 3:
r := (c >> 8) & 0xF r := (c >> 8) & 0xF
g := (c >> 4) & 0xF g := (c >> 4) & 0xF
b := c & 0xF b := c & 0xF
return Color(0xFF000000 | (r << 20) | (r << 16) | (g << 12) | (g << 8) | (b << 4) | b), true return Color(0xFF000000 | (r << 20) | (r << 16) | (g << 12) | (g << 8) | (b << 4) | b), nil
} }
ErrorLog(`Invalid color format: "` + text + `". Valid formats: #AARRGGBB, #RRGGBB, #ARGB, #RGB`) return 0, errors.New(`Invalid color format: "` + text + `". Valid formats: #AARRGGBB, #RRGGBB, #ARGB, #RGB`)
return 0, false
} }
parseRGB := func(args string) []int { parseRGB := func(args string) []int {
@ -155,23 +162,22 @@ func StringToColor(text string) (Color, bool) {
if strings.HasPrefix(text, "rgba") { if strings.HasPrefix(text, "rgba") {
args := parseRGB(text[4:]) args := parseRGB(text[4:])
if len(args) == 4 { if len(args) == 4 {
return Color((args[3] << 24) | (args[0] << 16) | (args[1] << 8) | args[2]), true return Color((args[3] << 24) | (args[0] << 16) | (args[1] << 8) | args[2]), nil
} }
} }
if strings.HasPrefix(text, "rgb") { if strings.HasPrefix(text, "rgb") {
args := parseRGB(text[3:]) args := parseRGB(text[3:])
if len(args) == 3 { if len(args) == 3 {
return Color(0xFF000000 | (args[0] << 16) | (args[1] << 8) | args[2]), true return Color(0xFF000000 | (args[0] << 16) | (args[1] << 8) | args[2]), nil
} }
} }
// TODO hsl(360,100%,50%), hsla(360,100%,50%,.5) // TODO hsl(360,100%,50%), hsla(360,100%,50%,.5)
if color, ok := colorConstants[text]; ok { if color, ok := colorConstants[text]; ok {
return color, true return color, nil
} }
ErrorLog(`Invalid color format: "` + text + `"`) return 0, errors.New(`Invalid color format: "` + text + `"`)
return 0, false
} }

View File

@ -42,7 +42,7 @@ func (style *viewStyle) setGridCellSize(tag string, value interface{}) bool {
val = strings.Trim(val, " \t\n\r") val = strings.Trim(val, " \t\n\r")
if isConstantName(val) { if isConstantName(val) {
sizes[i] = val sizes[i] = val
} else if size, ok := StringToSizeUnit(val); ok { } else if size, err := stringToSizeUnit(val); err == nil {
sizes[i] = size sizes[i] = size
} else { } else {
invalidPropertyValue(tag, value) invalidPropertyValue(tag, value)
@ -52,7 +52,7 @@ func (style *viewStyle) setGridCellSize(tag string, value interface{}) bool {
style.properties[tag] = sizes style.properties[tag] = sizes
} else if isConstantName(values[0]) { } else if isConstantName(values[0]) {
style.properties[tag] = values[0] style.properties[tag] = values[0]
} else if size, ok := StringToSizeUnit(values[0]); ok { } else if size, err := stringToSizeUnit(values[0]); err == nil {
style.properties[tag] = size style.properties[tag] = size
} else { } else {
invalidPropertyValue(tag, value) invalidPropertyValue(tag, value)
@ -110,7 +110,7 @@ func (style *viewStyle) setGridCellSize(tag string, value interface{}) bool {
case string: case string:
if isConstantName(val) { if isConstantName(val) {
sizes[i] = val sizes[i] = val
} else if size, ok := StringToSizeUnit(val); ok { } else if size, err := stringToSizeUnit(val); err == nil {
sizes[i] = size sizes[i] = size
} else { } else {
invalidPropertyValue(tag, value) invalidPropertyValue(tag, value)
@ -291,7 +291,7 @@ func gridCellSizes(properties Properties, tag string, session Session) []SizeUni
case string: case string:
if text, ok := session.resolveConstants(val); ok { if text, ok := session.resolveConstants(val); ok {
result[i], _ = StringToSizeUnit(text) result[i], _ = stringToSizeUnit(text)
} }
} }
} }
@ -302,7 +302,7 @@ func gridCellSizes(properties Properties, tag string, session Session) []SizeUni
values := strings.Split(text, ",") values := strings.Split(text, ",")
result := make([]SizeUnit, len(values)) result := make([]SizeUnit, len(values))
for i, val := range values { for i, val := range values {
result[i], _ = StringToSizeUnit(val) result[i], _ = stringToSizeUnit(val)
} }
return result return result
} }

View File

@ -586,8 +586,8 @@ func (properties *propertyList) setColorProperty(tag string, value interface{})
var result Color var result Color
switch value := value.(type) { switch value := value.(type) {
case string: case string:
var ok bool var err error
if result, ok = StringToColor(value); !ok { if result, err = stringToColor(value); err != nil {
invalidPropertyValue(tag, value) invalidPropertyValue(tag, value)
return false return false
} }

View File

@ -166,9 +166,9 @@ func (session *sessionData) Color(tag string) (Color, bool) {
} }
if len(result) == 0 || result[0] != '@' { if len(result) == 0 || result[0] != '@' {
color, ok := StringToColor(result) color, err := stringToColor(result)
if !ok { if err != nil {
ErrorLogF(`invalid value "%v" of "%v" color constant`, result, tag) ErrorLogF(`invalid value "%v" of "%v" color constant (%s)`, result, tag, err.Error())
return 0, false return 0, false
} }
return color, true return color, true

View File

@ -1,6 +1,7 @@
package rui package rui
import ( import (
"errors"
"fmt" "fmt"
"strconv" "strconv"
"strings" "strings"
@ -120,15 +121,23 @@ func sizeUnitSuffixes() map[SizeUnitType]string {
// StringToSizeUnit converts the string argument to SizeUnit // StringToSizeUnit converts the string argument to SizeUnit
func StringToSizeUnit(value string) (SizeUnit, bool) { func StringToSizeUnit(value string) (SizeUnit, bool) {
size, err := stringToSizeUnit(value)
if err != nil {
ErrorLog(err.Error())
return size, false
}
return size, true
}
func stringToSizeUnit(value string) (SizeUnit, error) {
value = strings.Trim(value, " \t\n\r") value = strings.Trim(value, " \t\n\r")
switch value { switch value {
case "auto", "none", "": case "auto", "none", "":
return SizeUnit{Type: Auto, Value: 0}, true return SizeUnit{Type: Auto, Value: 0}, nil
case "0": case "0":
return SizeUnit{Type: SizeInPixel, Value: 0}, true return SizeUnit{Type: SizeInPixel, Value: 0}, nil
} }
suffixes := sizeUnitSuffixes() suffixes := sizeUnitSuffixes()
@ -137,15 +146,13 @@ func StringToSizeUnit(value string) (SizeUnit, bool) {
var err error var err error
var val float64 var val float64
if val, err = strconv.ParseFloat(value[:len(value)-len(suffix)], 64); err != nil { if val, err = strconv.ParseFloat(value[:len(value)-len(suffix)], 64); err != nil {
ErrorLog(err.Error()) return SizeUnit{Type: Auto, Value: 0}, err
return SizeUnit{Type: Auto, Value: 0}, false
} }
return SizeUnit{Type: unitType, Value: val}, true return SizeUnit{Type: unitType, Value: val}, nil
} }
} }
ErrorLog(`Invalid SizeUnit value: "` + value + `"`) return SizeUnit{Type: Auto, Value: 0}, errors.New(`Invalid SizeUnit value: "` + value + `"`)
return SizeUnit{Type: Auto, Value: 0}, false
} }
// String - convert SizeUnit to string // String - convert SizeUnit to string