forked from mbk-lab/rui_orig
Added the background conic gradient
This commit is contained in:
parent
371079e27b
commit
86271a3c6e
53
README-ru.md
53
README-ru.md
|
@ -991,12 +991,12 @@ RadiusProperty, а не структура BoxRadius. Получить стру
|
||||||
или одно из следующих значений типа Int:
|
или одно из следующих значений типа Int:
|
||||||
|
|
||||||
| Значение | Константа | Имя | Описание |
|
| Значение | Константа | Имя | Описание |
|
||||||
|:--------:|-----------------------|-------------------|------------------------------------------------|
|
|:--------:|-----------------------|-------------------|-----------------------------------------|
|
||||||
| 0 | ToTopGradient | "to-top" | Линия идет снизу вверх (значение по умолчанию) |
|
| 0 | ToTopGradient | "to-top" | Линия идет снизу вверх |
|
||||||
| 1 | ToRightTopGradient | "to-right-top" | Из левого нижнего угла в правый верхний |
|
| 1 | ToRightTopGradient | "to-right-top" | Из левого нижнего угла в правый верхний |
|
||||||
| 2 | ToRightGradient | "to-right" | Слева направо |
|
| 2 | ToRightGradient | "to-right" | Слева направо |
|
||||||
| 3 | ToRightBottomGradient | "to-right-bottom" | Из левого верхнего угла в правый нижний |
|
| 3 | ToRightBottomGradient | "to-right-bottom" | Из левого верхнего угла в правый нижний |
|
||||||
| 4 | ToBottomGradient | "to-bottom" | Сверху вних |
|
| 4 | ToBottomGradient | "to-bottom" | Сверху вниз (значение по умолчанию) |
|
||||||
| 5 | ToLeftBottomGradient | "to-left-bottom" | Из правого верхнего угла в левый нижний |
|
| 5 | ToLeftBottomGradient | "to-left-bottom" | Из правого верхнего угла в левый нижний |
|
||||||
| 6 | ToLeftGradient | "to-left" | Справа налево |
|
| 6 | ToLeftGradient | "to-left" | Справа налево |
|
||||||
| 7 | ToLeftTopGradient | "to-left-top" | Из правого нижнего угла в левый верхний |
|
| 7 | ToLeftTopGradient | "to-left-top" | Из правого нижнего угла в левый верхний |
|
||||||
|
@ -1010,12 +1010,12 @@ Pos определяет положение точки относительно
|
||||||
Элементами этого массива могут быть BackgroundGradientPoint, Color, текстовое представление BackgroundGradientPoint
|
Элементами этого массива могут быть BackgroundGradientPoint, Color, текстовое представление BackgroundGradientPoint
|
||||||
или Color и имя константы
|
или Color и имя константы
|
||||||
|
|
||||||
* Repeat ("repeat") - булево значение, определяющее будет ли повторяться градиент после последней
|
* Repeating ("repeating") - булево значение, определяющее будет ли повторяться градиент после последней
|
||||||
ключевой точки. Необязательный параметр. Значение по умолчанию - false (не повторять)
|
ключевой точки. Необязательный параметр. Значение по умолчанию - false (не повторять)
|
||||||
|
|
||||||
Текстовое представление линейного градиента имеет следующий вид:
|
Текстовое представление линейного градиента имеет следующий вид:
|
||||||
|
|
||||||
linear-gradient { gradient = <значение> [, direction = <значение>] [, repeat = <значение>] }
|
linear-gradient { gradient = <значение> [, direction = <значение>] [, repeating = <значение>] }
|
||||||
|
|
||||||
#### Радиальный градиент
|
#### Радиальный градиент
|
||||||
|
|
||||||
|
@ -1028,7 +1028,7 @@ Pos определяет положение точки относительно
|
||||||
* Gradient ("gradient") - массив ключевых точек градиента (обязательный параметр). Идентичен одноименному
|
* Gradient ("gradient") - массив ключевых точек градиента (обязательный параметр). Идентичен одноименному
|
||||||
параметру линейного градиента.
|
параметру линейного градиента.
|
||||||
|
|
||||||
* Repeat ("repeat") - булево значение, определяющее будет ли повторяться градиент после последней
|
* Repeating ("repeating") - булево значение, определяющее будет ли повторяться градиент после последней
|
||||||
ключевой точки. Необязательный параметр. Значение по умолчанию - false (не повторять)
|
ключевой точки. Необязательный параметр. Значение по умолчанию - false (не повторять)
|
||||||
|
|
||||||
* RadialGradientShape ("radial-gradient-shape") или Shape ("shape") - определяет форму градиента.
|
* RadialGradientShape ("radial-gradient-shape") или Shape ("shape") - определяет форму градиента.
|
||||||
|
@ -1051,7 +1051,7 @@ Pos определяет положение точки относительно
|
||||||
| FarthestSideGradient | 2 | "farthest-side" | Схоже с ClosestSideGradient, кроме того что, размер формы определяется самой дальней стороной от своего центра (или вертикальных и горизонтальных сторон) |
|
| FarthestSideGradient | 2 | "farthest-side" | Схоже с ClosestSideGradient, кроме того что, размер формы определяется самой дальней стороной от своего центра (или вертикальных и горизонтальных сторон) |
|
||||||
| FarthestCornerGradient | 3 | "farthest-corner" | Конечная форма градиента определяется таким образом, чтобы он точно соответствовал самому дальнему углу прямоугольника от его центра |
|
| FarthestCornerGradient | 3 | "farthest-corner" | Конечная форма градиента определяется таким образом, чтобы он точно соответствовал самому дальнему углу прямоугольника от его центра |
|
||||||
|
|
||||||
Необязательный параметр. Значение по умолчанию ClosestSideGradient
|
Необязательный параметр. Значение по умолчанию FarthestCornerGradient
|
||||||
|
|
||||||
* CenterX ("center-x"), CenterY ("center-y") - задает центр градиента относительно левого верхнего
|
* CenterX ("center-x"), CenterY ("center-y") - задает центр градиента относительно левого верхнего
|
||||||
угла View. Принимает значение типа SizeUnit. Необязательный параметр.
|
угла View. Принимает значение типа SizeUnit. Необязательный параметр.
|
||||||
|
@ -1059,9 +1059,46 @@ Pos определяет положение точки относительно
|
||||||
|
|
||||||
Текстовое представление линейного градиента имеет следующий вид:
|
Текстовое представление линейного градиента имеет следующий вид:
|
||||||
|
|
||||||
radial-gradient { gradient = <значение> [, repeat = <значение>] [, shape = <значение>]
|
radial-gradient { gradient = <значение> [, repeating = <значение>] [, shape = <значение>]
|
||||||
[, radius = <значение>][, center-x = <значение>][, center-y = <значение>]}
|
[, radius = <значение>][, center-x = <значение>][, center-y = <значение>]}
|
||||||
|
|
||||||
|
#### Конический градиент
|
||||||
|
|
||||||
|
Конический градиент создается с помощью функции
|
||||||
|
|
||||||
|
func NewBackgroundConicGradient(params Params) BackgroundElement
|
||||||
|
|
||||||
|
Радиальный градиент имеет следующие параметры:
|
||||||
|
|
||||||
|
* Gradient ("gradient") - массив ключевых углов градиента (обязательный параметр). Каждая ключевой угол
|
||||||
|
описывается структурой BackgroundGradientAngle:
|
||||||
|
|
||||||
|
type BackgroundGradientAngle struct {
|
||||||
|
Color interface{}
|
||||||
|
Angle interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
где Color задает цвет ключевого угла и может принимать значение типа Color или string (цветовая константа
|
||||||
|
или текстовое описание цвета);
|
||||||
|
Angle задает угол относительно начального угла задаваемого параметром From и может принимать значение типа
|
||||||
|
AngleUnit или string (угловая константа или текстовое описание угла).
|
||||||
|
|
||||||
|
Поле Color является обязательным и не может быть nil. Поле Angle опционально, если оно равно nil, то угол
|
||||||
|
задается как середина между соседними углами. Для первго элемента угол по умолчанию равен 0°, для последнего - 360°.
|
||||||
|
|
||||||
|
* Repeating ("repeating") - булево значение, определяющее будет ли повторяться градиент после последнего
|
||||||
|
ключевого угла. Необязательный параметр. Значение по умолчанию - false (не повторять)
|
||||||
|
|
||||||
|
* CenterX ("center-x"), CenterY ("center-y") - задает центр градиента относительно левого верхнего
|
||||||
|
угла View. Принимает значение типа SizeUnit. Необязательный параметр.
|
||||||
|
Значение по умолчанию "50%", т.е. центр градиента совпадает с центром View.
|
||||||
|
|
||||||
|
Текстовое представление конического градиента имеет следующий вид:
|
||||||
|
|
||||||
|
conic-gradient { gradient = <значение> [, repeating = <значение>] [, from = <значение>]
|
||||||
|
[, center-x = <значение>][, center-y = <значение>]}
|
||||||
|
|
||||||
|
|
||||||
#### Изображение
|
#### Изображение
|
||||||
|
|
||||||
Изображение имеет следующие параметры:
|
Изображение имеет следующие параметры:
|
||||||
|
|
49
README.md
49
README.md
|
@ -972,11 +972,11 @@ Optional parameter. The default direction is from bottom to top. It can be eithe
|
||||||
|
|
||||||
| Value | Constant | Name | Description |
|
| Value | Constant | Name | Description |
|
||||||
|:-----:|-----------------------|-------------------|-----------------------------------------------|
|
|:-----:|-----------------------|-------------------|-----------------------------------------------|
|
||||||
| 0 | ToTopGradient | "to-top" | Line goes from bottom to top (default) |
|
| 0 | ToTopGradient | "to-top" | Line goes from bottom to top |
|
||||||
| 1 | ToRightTopGradient | "to-right-top" | From bottom left to top right |
|
| 1 | ToRightTopGradient | "to-right-top" | From bottom left to top right |
|
||||||
| 2 | ToRightGradient | "to-right" | From left to right |
|
| 2 | ToRightGradient | "to-right" | From left to right |
|
||||||
| 3 | ToRightBottomGradient | "to-right-bottom" | From top left to bottom right |
|
| 3 | ToRightBottomGradient | "to-right-bottom" | From top left to bottom right |
|
||||||
| 4 | ToBottomGradient | "to-bottom" | From top to bottom |
|
| 4 | ToBottomGradient | "to-bottom" | From top to bottom (default) |
|
||||||
| 5 | ToLeftBottomGradient | "to-left-bottom" | From the upper right corner to the lower left |
|
| 5 | ToLeftBottomGradient | "to-left-bottom" | From the upper right corner to the lower left |
|
||||||
| 6 | ToLeftGradient | "to-left" | From right to left |
|
| 6 | ToLeftGradient | "to-left" | From right to left |
|
||||||
| 7 | ToLeftTopGradient | "to-left-top" | From the bottom right corner to the top left |
|
| 7 | ToLeftTopGradient | "to-left-top" | From the bottom right corner to the top left |
|
||||||
|
@ -988,7 +988,7 @@ You can also pass a Color array as the gradient value. In this case, the points
|
||||||
You can also use an array of []interface{} as an array of cue points.
|
You can also use an array of []interface{} as an array of cue points.
|
||||||
The elements of this array can be BackgroundGradientPoint, Color, BackgroundGradientPoint or Color text representation, and the name of the constant
|
The elements of this array can be BackgroundGradientPoint, Color, BackgroundGradientPoint or Color text representation, and the name of the constant
|
||||||
|
|
||||||
* Repeat ("repeat") - a boolean value that determines whether the gradient will repeat after the last key point.
|
* Repeating ("repeating") - a boolean value that determines whether the gradient will repeat after the last key point.
|
||||||
Optional parameter. The default is false (do not repeat)
|
Optional parameter. The default is false (do not repeat)
|
||||||
|
|
||||||
The linear gradient text representation is as follows:
|
The linear gradient text representation is as follows:
|
||||||
|
@ -1005,7 +1005,7 @@ The radial gradient has the following parameters:
|
||||||
|
|
||||||
* Gradient ("gradient") - array of gradient key points (required parameter). Identical to the linear gradient parameter of the same name.
|
* Gradient ("gradient") - array of gradient key points (required parameter). Identical to the linear gradient parameter of the same name.
|
||||||
|
|
||||||
* Repeat ("repeat") - a boolean value that determines whether the gradient will repeat after the last key point.
|
* Repeating ("repeating") - a boolean value that determines whether the gradient will repeat after the last key point.
|
||||||
Optional parameter. The default is false (do not repeat)
|
Optional parameter. The default is false (do not repeat)
|
||||||
|
|
||||||
* RadialGradientShape ("radial-gradient-shape") or Shape ("shape") - defines the shape of the gradient.
|
* RadialGradientShape ("radial-gradient-shape") or Shape ("shape") - defines the shape of the gradient.
|
||||||
|
@ -1028,7 +1028,7 @@ Can be either SizeUnit or one of the following int values:
|
||||||
| 2 | FarthestSideGradient | "farthest-side" | Similar to ClosestSideGradient, except that the size of the shape is determined by the farthest side from its center (or vertical and horizontal sides) |
|
| 2 | FarthestSideGradient | "farthest-side" | Similar to ClosestSideGradient, except that the size of the shape is determined by the farthest side from its center (or vertical and horizontal sides) |
|
||||||
| 3 | FarthestCornerGradient | "farthest-corner" | The final shape of the gradient is defined so that it exactly matches the farthest corner of the rectangle from its center |
|
| 3 | FarthestCornerGradient | "farthest-corner" | The final shape of the gradient is defined so that it exactly matches the farthest corner of the rectangle from its center |
|
||||||
|
|
||||||
Optional parameter. The default is ClosestSideGradient
|
Optional parameter. The default is FarthestCornerGradient
|
||||||
|
|
||||||
* CenterX ("center-x"), CenterY ("center-y") - sets the center of the gradient relative to the upper left corner of the View. Takes in a SizeUnit value. Optional parameter.
|
* CenterX ("center-x"), CenterY ("center-y") - sets the center of the gradient relative to the upper left corner of the View. Takes in a SizeUnit value. Optional parameter.
|
||||||
The default value is "50%", i.e. the center of the gradient is the center of the View.
|
The default value is "50%", i.e. the center of the gradient is the center of the View.
|
||||||
|
@ -1038,6 +1038,45 @@ The linear gradient text representation is as follows:
|
||||||
radial-gradient { gradient = <Value> [, repeat = <Value>] [, shape = <Value>]
|
radial-gradient { gradient = <Value> [, repeat = <Value>] [, shape = <Value>]
|
||||||
[, radius = <Value>][, center-x = <Value>][, center-y = <Value>]}
|
[, radius = <Value>][, center-x = <Value>][, center-y = <Value>]}
|
||||||
|
|
||||||
|
#### Conic gradient
|
||||||
|
|
||||||
|
The conic gradient is created using the function
|
||||||
|
|
||||||
|
func NewBackgroundConicGradient(params Params) BackgroundElement
|
||||||
|
|
||||||
|
The radial gradient has the following options:
|
||||||
|
|
||||||
|
* Gradient ("gradient") - array of gradient key angles (required parameter).
|
||||||
|
Each key angle is described by a BackgroundGradientAngle structure:
|
||||||
|
|
||||||
|
type BackgroundGradientAngle struct {
|
||||||
|
Color interface{}
|
||||||
|
Angle interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
where Color specifies the color of the key corner and can take a value of Color type or
|
||||||
|
string (color constant or textual description of the color);
|
||||||
|
Angle sets the angle relative to the initial angle specified by the From parameter
|
||||||
|
and can take a value of the AngleUnit type or string (an angle constant or a textual description of the angle).
|
||||||
|
|
||||||
|
The Color field is required and cannot be nil.
|
||||||
|
|
||||||
|
The Angle field is optional. If it is nil, then the angle is set as the midpoint between adjacent corners.
|
||||||
|
For the first element, the default angle is 0°, for the last element it is 360°.
|
||||||
|
|
||||||
|
* Repeating ("repeating") is a boolean value that determines whether the gradient will repeat after the last key corner.
|
||||||
|
Optional parameter. Default value is false (don't repeat)
|
||||||
|
|
||||||
|
* CenterX ("center-x"), CenterY ("center-y") - sets the center of the gradient relative to the upper left corner of the View.
|
||||||
|
Takes a value of SizeUnit type. Optional parameter.
|
||||||
|
The default value is "50%", i.e. the center of the gradient is the same as the center of the View.
|
||||||
|
|
||||||
|
The textual representation of a conic gradient looks like this:
|
||||||
|
|
||||||
|
conic-gradient { gradient = <Value> [, repeating = <Value>] [, from = <Value>]
|
||||||
|
[, center-x = <Value>][, center-y = <Value>]}
|
||||||
|
|
||||||
|
|
||||||
#### Image
|
#### Image
|
||||||
|
|
||||||
The image has the following parameters:
|
The image has the following parameters:
|
||||||
|
|
500
background.go
500
background.go
|
@ -56,47 +56,6 @@ const (
|
||||||
// ContentBoxClip is value of the BackgroundClip property:
|
// ContentBoxClip is value of the BackgroundClip property:
|
||||||
// The background is painted within (clipped to) the content box.
|
// The background is painted within (clipped to) the content box.
|
||||||
ContentBoxClip = 2
|
ContentBoxClip = 2
|
||||||
|
|
||||||
// ToTopGradient is value of the Direction property of a linear gradient. The value is equivalent to the 0deg angle
|
|
||||||
ToTopGradient = 0
|
|
||||||
// ToRightTopGradient is value of the Direction property of a linear gradient.
|
|
||||||
ToRightTopGradient = 1
|
|
||||||
// ToRightGradient is value of the Direction property of a linear gradient. The value is equivalent to the 90deg angle
|
|
||||||
ToRightGradient = 2
|
|
||||||
// ToRightBottomGradient is value of the Direction property of a linear gradient.
|
|
||||||
ToRightBottomGradient = 3
|
|
||||||
// ToBottomGradient is value of the Direction property of a linear gradient. The value is equivalent to the 180deg angle
|
|
||||||
ToBottomGradient = 4
|
|
||||||
// ToLeftBottomGradient is value of the Direction property of a linear gradient.
|
|
||||||
ToLeftBottomGradient = 5
|
|
||||||
// ToLeftGradient is value of the Direction property of a linear gradient. The value is equivalent to the 270deg angle
|
|
||||||
ToLeftGradient = 6
|
|
||||||
// ToLeftTopGradient is value of the Direction property of a linear gradient.
|
|
||||||
ToLeftTopGradient = 7
|
|
||||||
|
|
||||||
// EllipseGradient is value of the Shape property of a radial gradient background:
|
|
||||||
// the shape is an axis-aligned ellipse
|
|
||||||
EllipseGradient = 0
|
|
||||||
// CircleGradient is value of the Shape property of a radial gradient background:
|
|
||||||
// the gradient's shape is a circle with constant radius
|
|
||||||
CircleGradient = 1
|
|
||||||
|
|
||||||
// ClosestSideGradient is value of the Radius property of a radial gradient background:
|
|
||||||
// The gradient's ending shape meets the side of the box closest to its center (for circles)
|
|
||||||
// or meets both the vertical and horizontal sides closest to the center (for ellipses).
|
|
||||||
ClosestSideGradient = 0
|
|
||||||
// ClosestCornerGradient is value of the Radius property of a radial gradient background:
|
|
||||||
// The gradient's ending shape is sized so that it exactly meets the closest corner
|
|
||||||
// of the box from its center.
|
|
||||||
ClosestCornerGradient = 1
|
|
||||||
// FarthestSideGradient is value of the Radius property of a radial gradient background:
|
|
||||||
// Similar to closest-side, except the ending shape is sized to meet the side of the box
|
|
||||||
// farthest from its center (or vertical and horizontal sides).
|
|
||||||
FarthestSideGradient = 2
|
|
||||||
// FarthestCornerGradient is value of the Radius property of a radial gradient background:
|
|
||||||
// The default value, the gradient's ending shape is sized so that it exactly meets
|
|
||||||
// the farthest corner of the box from its center.
|
|
||||||
FarthestCornerGradient = 3
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// BackgroundElement describes the background element.
|
// BackgroundElement describes the background element.
|
||||||
|
@ -104,6 +63,7 @@ type BackgroundElement interface {
|
||||||
Properties
|
Properties
|
||||||
cssStyle(session Session) string
|
cssStyle(session Session) string
|
||||||
Tag() string
|
Tag() string
|
||||||
|
Clone() BackgroundElement
|
||||||
}
|
}
|
||||||
|
|
||||||
type backgroundElement struct {
|
type backgroundElement struct {
|
||||||
|
@ -114,26 +74,6 @@ type backgroundImage struct {
|
||||||
backgroundElement
|
backgroundElement
|
||||||
}
|
}
|
||||||
|
|
||||||
// BackgroundGradientPoint define point on gradient straight line
|
|
||||||
type BackgroundGradientPoint struct {
|
|
||||||
// Pos - the distance from the start of the gradient straight line
|
|
||||||
Pos SizeUnit
|
|
||||||
// Color - the color of the point
|
|
||||||
Color Color
|
|
||||||
}
|
|
||||||
|
|
||||||
type backgroundGradient struct {
|
|
||||||
backgroundElement
|
|
||||||
}
|
|
||||||
|
|
||||||
type backgroundLinearGradient struct {
|
|
||||||
backgroundGradient
|
|
||||||
}
|
|
||||||
|
|
||||||
type backgroundRadialGradient struct {
|
|
||||||
backgroundGradient
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBackgroundImage creates the new background image
|
// NewBackgroundImage creates the new background image
|
||||||
func createBackground(obj DataObject) BackgroundElement {
|
func createBackground(obj DataObject) BackgroundElement {
|
||||||
var result BackgroundElement = nil
|
var result BackgroundElement = nil
|
||||||
|
@ -154,6 +94,11 @@ func createBackground(obj DataObject) BackgroundElement {
|
||||||
gradient.properties = map[string]interface{}{}
|
gradient.properties = map[string]interface{}{}
|
||||||
result = gradient
|
result = gradient
|
||||||
|
|
||||||
|
case "conic-gradient":
|
||||||
|
gradient := new(backgroundConicGradient)
|
||||||
|
gradient.properties = map[string]interface{}{}
|
||||||
|
result = gradient
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -180,30 +125,18 @@ func NewBackgroundImage(params Params) BackgroundElement {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBackgroundLinearGradient creates the new background linear gradient
|
|
||||||
func NewBackgroundLinearGradient(params Params) BackgroundElement {
|
|
||||||
result := new(backgroundLinearGradient)
|
|
||||||
result.properties = map[string]interface{}{}
|
|
||||||
for tag, value := range params {
|
|
||||||
result.Set(tag, value)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBackgroundRadialGradient creates the new background radial gradient
|
|
||||||
func NewBackgroundRadialGradient(params Params) BackgroundElement {
|
|
||||||
result := new(backgroundRadialGradient)
|
|
||||||
result.properties = map[string]interface{}{}
|
|
||||||
for tag, value := range params {
|
|
||||||
result.Set(tag, value)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (image *backgroundImage) Tag() string {
|
func (image *backgroundImage) Tag() string {
|
||||||
return "image"
|
return "image"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (image *backgroundImage) Clone() BackgroundElement {
|
||||||
|
result := NewBackgroundImage(nil)
|
||||||
|
for tag, value := range image.properties {
|
||||||
|
result.setRaw(tag, value)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
func (image *backgroundImage) normalizeTag(tag string) string {
|
func (image *backgroundImage) normalizeTag(tag string) string {
|
||||||
tag = strings.ToLower(tag)
|
tag = strings.ToLower(tag)
|
||||||
switch tag {
|
switch tag {
|
||||||
|
@ -306,408 +239,3 @@ func (image *backgroundImage) cssStyle(session Session) string {
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gradient *backgroundGradient) Set(tag string, value interface{}) bool {
|
|
||||||
|
|
||||||
switch tag = strings.ToLower(tag); tag {
|
|
||||||
case Repeat:
|
|
||||||
return gradient.setBoolProperty(tag, value)
|
|
||||||
|
|
||||||
case Gradient:
|
|
||||||
switch value := value.(type) {
|
|
||||||
case string:
|
|
||||||
if value != "" {
|
|
||||||
elements := strings.Split(value, `,`)
|
|
||||||
if count := len(elements); count > 1 {
|
|
||||||
points := make([]interface{}, count)
|
|
||||||
for i, element := range elements {
|
|
||||||
if strings.Contains(element, "@") {
|
|
||||||
points[i] = element
|
|
||||||
} else {
|
|
||||||
var point BackgroundGradientPoint
|
|
||||||
if point.setValue(element) {
|
|
||||||
points[i] = point
|
|
||||||
} else {
|
|
||||||
ErrorLogF("Invalid gradient element #%d: %s", i, element)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gradient.properties[Gradient] = points
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
text := strings.Trim(value, " \n\r\t")
|
|
||||||
if text[0] == '@' {
|
|
||||||
gradient.properties[Gradient] = text
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case []BackgroundGradientPoint:
|
|
||||||
if len(value) >= 2 {
|
|
||||||
gradient.properties[Gradient] = value
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
case []Color:
|
|
||||||
count := len(value)
|
|
||||||
if count >= 2 {
|
|
||||||
points := make([]BackgroundGradientPoint, count)
|
|
||||||
for i, color := range value {
|
|
||||||
points[i].Color = color
|
|
||||||
points[i].Pos = AutoSize()
|
|
||||||
}
|
|
||||||
gradient.properties[Gradient] = points
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
case []GradientPoint:
|
|
||||||
count := len(value)
|
|
||||||
if count >= 2 {
|
|
||||||
points := make([]BackgroundGradientPoint, count)
|
|
||||||
for i, point := range value {
|
|
||||||
points[i].Color = point.Color
|
|
||||||
points[i].Pos = Percent(point.Offset * 100)
|
|
||||||
}
|
|
||||||
gradient.properties[Gradient] = points
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
if count := len(value); count > 1 {
|
|
||||||
points := make([]interface{}, count)
|
|
||||||
for i, element := range value {
|
|
||||||
switch element := element.(type) {
|
|
||||||
case string:
|
|
||||||
if strings.Contains(element, "@") {
|
|
||||||
points[i] = element
|
|
||||||
} else {
|
|
||||||
var point BackgroundGradientPoint
|
|
||||||
if !point.setValue(element) {
|
|
||||||
ErrorLogF("Invalid gradient element #%d: %s", i, element)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
points[i] = point
|
|
||||||
}
|
|
||||||
|
|
||||||
case BackgroundGradientPoint:
|
|
||||||
points[i] = element
|
|
||||||
|
|
||||||
case GradientPoint:
|
|
||||||
points[i] = BackgroundGradientPoint{Color: element.Color, Pos: Percent(element.Offset * 100)}
|
|
||||||
|
|
||||||
case Color:
|
|
||||||
points[i] = BackgroundGradientPoint{Color: element, Pos: AutoSize()}
|
|
||||||
|
|
||||||
default:
|
|
||||||
ErrorLogF("Invalid gradient element #%d: %v", i, element)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gradient.properties[Gradient] = points
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
ErrorLogF("Invalid gradient %v", value)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return gradient.backgroundElement.Set(tag, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (point *BackgroundGradientPoint) setValue(value string) bool {
|
|
||||||
var ok bool
|
|
||||||
|
|
||||||
switch elements := strings.Split(value, `:`); len(elements) {
|
|
||||||
case 2:
|
|
||||||
if point.Color, ok = StringToColor(elements[0]); !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if point.Pos, ok = StringToSizeUnit(elements[1]); !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
if point.Color, ok = StringToColor(elements[0]); !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
point.Pos = AutoSize()
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gradient *backgroundGradient) writeGradient(session Session, buffer *strings.Builder) bool {
|
|
||||||
|
|
||||||
value, ok := gradient.properties[Gradient]
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
points := []BackgroundGradientPoint{}
|
|
||||||
|
|
||||||
switch value := value.(type) {
|
|
||||||
case string:
|
|
||||||
if text, ok := session.resolveConstants(value); ok && text != "" {
|
|
||||||
elements := strings.Split(text, `,`)
|
|
||||||
points := make([]BackgroundGradientPoint, len(elements))
|
|
||||||
for i, element := range elements {
|
|
||||||
if !points[i].setValue(element) {
|
|
||||||
ErrorLogF(`Invalid gradient point #%d: "%s"`, i, element)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ErrorLog(`Invalid gradient: ` + value)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
case []BackgroundGradientPoint:
|
|
||||||
points = value
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
points = make([]BackgroundGradientPoint, len(value))
|
|
||||||
for i, element := range value {
|
|
||||||
switch element := element.(type) {
|
|
||||||
case string:
|
|
||||||
if text, ok := session.resolveConstants(element); ok && text != "" {
|
|
||||||
if !points[i].setValue(text) {
|
|
||||||
ErrorLogF(`Invalid gradient point #%d: "%s"`, i, text)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ErrorLogF(`Invalid gradient point #%d: "%s"`, i, text)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
case BackgroundGradientPoint:
|
|
||||||
points[i] = element
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(points) > 0 {
|
|
||||||
for i, point := range points {
|
|
||||||
if i > 0 {
|
|
||||||
buffer.WriteString(`, `)
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.WriteString(point.Color.cssString())
|
|
||||||
if point.Pos.Type != Auto {
|
|
||||||
buffer.WriteRune(' ')
|
|
||||||
buffer.WriteString(point.Pos.cssString(""))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gradient *backgroundLinearGradient) Tag() string {
|
|
||||||
return "linear-gradient"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gradient *backgroundLinearGradient) Set(tag string, value interface{}) bool {
|
|
||||||
if tag == Direction {
|
|
||||||
switch value := value.(type) {
|
|
||||||
case AngleUnit:
|
|
||||||
gradient.properties[Direction] = value
|
|
||||||
return true
|
|
||||||
|
|
||||||
case string:
|
|
||||||
var angle AngleUnit
|
|
||||||
if ok, _ := angle.setValue(value); ok {
|
|
||||||
gradient.properties[Direction] = angle
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return gradient.setEnumProperty(tag, value, enumProperties[Direction].values)
|
|
||||||
}
|
|
||||||
|
|
||||||
return gradient.backgroundGradient.Set(tag, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gradient *backgroundLinearGradient) cssStyle(session Session) string {
|
|
||||||
buffer := allocStringBuilder()
|
|
||||||
defer freeStringBuilder(buffer)
|
|
||||||
|
|
||||||
if repeating, _ := boolProperty(gradient, Repeating, session); repeating {
|
|
||||||
buffer.WriteString(`repeating-linear-gradient(`)
|
|
||||||
} else {
|
|
||||||
buffer.WriteString(`linear-gradient(`)
|
|
||||||
}
|
|
||||||
|
|
||||||
if value, ok := gradient.properties[Direction]; ok {
|
|
||||||
switch value := value.(type) {
|
|
||||||
case string:
|
|
||||||
if text, ok := session.resolveConstants(value); ok {
|
|
||||||
direction := enumProperties[Direction]
|
|
||||||
if n, ok := enumStringToInt(text, direction.values, false); ok {
|
|
||||||
buffer.WriteString(direction.cssValues[n])
|
|
||||||
buffer.WriteString(", ")
|
|
||||||
} else {
|
|
||||||
if angle, ok := StringToAngleUnit(text); ok {
|
|
||||||
buffer.WriteString(angle.cssString())
|
|
||||||
buffer.WriteString(", ")
|
|
||||||
} else {
|
|
||||||
ErrorLog(`Invalid linear gradient direction: ` + text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ErrorLog(`Invalid linear gradient direction: ` + value)
|
|
||||||
}
|
|
||||||
|
|
||||||
case int:
|
|
||||||
values := enumProperties[Direction].cssValues
|
|
||||||
if value >= 0 && value < len(values) {
|
|
||||||
buffer.WriteString(values[value])
|
|
||||||
buffer.WriteString(", ")
|
|
||||||
} else {
|
|
||||||
ErrorLogF(`Invalid linear gradient direction: %d`, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
case AngleUnit:
|
|
||||||
buffer.WriteString(value.cssString())
|
|
||||||
buffer.WriteString(", ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !gradient.writeGradient(session, buffer) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.WriteString(") ")
|
|
||||||
return buffer.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gradient *backgroundRadialGradient) Tag() string {
|
|
||||||
return "radial-gradient"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gradient *backgroundRadialGradient) normalizeTag(tag string) string {
|
|
||||||
tag = strings.ToLower(tag)
|
|
||||||
switch tag {
|
|
||||||
case Radius:
|
|
||||||
tag = RadialGradientRadius
|
|
||||||
|
|
||||||
case Shape:
|
|
||||||
tag = RadialGradientShape
|
|
||||||
|
|
||||||
case "x-center":
|
|
||||||
tag = CenterX
|
|
||||||
|
|
||||||
case "y-center":
|
|
||||||
tag = CenterY
|
|
||||||
}
|
|
||||||
|
|
||||||
return tag
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gradient *backgroundRadialGradient) Set(tag string, value interface{}) bool {
|
|
||||||
tag = gradient.normalizeTag(tag)
|
|
||||||
switch tag {
|
|
||||||
case RadialGradientRadius:
|
|
||||||
switch value := value.(type) {
|
|
||||||
case string, SizeUnit:
|
|
||||||
return gradient.propertyList.Set(RadialGradientRadius, value)
|
|
||||||
|
|
||||||
case int:
|
|
||||||
n := value
|
|
||||||
if n >= 0 && n < len(enumProperties[RadialGradientRadius].values) {
|
|
||||||
return gradient.propertyList.Set(RadialGradientRadius, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ErrorLogF(`Invalid value of "%s" property: %v`, tag, value)
|
|
||||||
|
|
||||||
case RadialGradientShape:
|
|
||||||
return gradient.propertyList.Set(RadialGradientShape, value)
|
|
||||||
|
|
||||||
case CenterX, CenterY:
|
|
||||||
return gradient.propertyList.Set(tag, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
return gradient.backgroundGradient.Set(tag, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gradient *backgroundRadialGradient) Get(tag string) interface{} {
|
|
||||||
return gradient.backgroundGradient.Get(gradient.normalizeTag(tag))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gradient *backgroundRadialGradient) cssStyle(session Session) string {
|
|
||||||
buffer := allocStringBuilder()
|
|
||||||
defer freeStringBuilder(buffer)
|
|
||||||
|
|
||||||
if repeating, _ := boolProperty(gradient, Repeating, session); repeating {
|
|
||||||
buffer.WriteString(`repeating-radial-gradient(`)
|
|
||||||
} else {
|
|
||||||
buffer.WriteString(`radial-gradient(`)
|
|
||||||
}
|
|
||||||
|
|
||||||
if shape, ok := enumProperty(gradient, RadialGradientShape, session, EllipseGradient); ok && shape == CircleGradient {
|
|
||||||
buffer.WriteString(`circle `)
|
|
||||||
} else {
|
|
||||||
buffer.WriteString(`ellipse `)
|
|
||||||
}
|
|
||||||
|
|
||||||
if value, ok := gradient.properties[RadialGradientRadius]; ok {
|
|
||||||
switch value := value.(type) {
|
|
||||||
case string:
|
|
||||||
if text, ok := session.resolveConstants(value); ok {
|
|
||||||
values := enumProperties[RadialGradientRadius]
|
|
||||||
if n, ok := enumStringToInt(text, values.values, false); ok {
|
|
||||||
buffer.WriteString(values.cssValues[n])
|
|
||||||
buffer.WriteString(" ")
|
|
||||||
} else {
|
|
||||||
if r, ok := StringToSizeUnit(text); ok && r.Type != Auto {
|
|
||||||
buffer.WriteString(r.cssString(""))
|
|
||||||
buffer.WriteString(" ")
|
|
||||||
} else {
|
|
||||||
ErrorLog(`Invalid linear gradient radius: ` + text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ErrorLog(`Invalid linear gradient radius: ` + value)
|
|
||||||
}
|
|
||||||
|
|
||||||
case int:
|
|
||||||
values := enumProperties[RadialGradientRadius].cssValues
|
|
||||||
if value >= 0 && value < len(values) {
|
|
||||||
buffer.WriteString(values[value])
|
|
||||||
buffer.WriteString(" ")
|
|
||||||
} else {
|
|
||||||
ErrorLogF(`Invalid linear gradient radius: %d`, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
case SizeUnit:
|
|
||||||
if value.Type != Auto {
|
|
||||||
buffer.WriteString(value.cssString(""))
|
|
||||||
buffer.WriteString(" ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
x, _ := sizeProperty(gradient, CenterX, session)
|
|
||||||
y, _ := sizeProperty(gradient, CenterX, session)
|
|
||||||
if x.Type != Auto || y.Type != Auto {
|
|
||||||
buffer.WriteString("at ")
|
|
||||||
buffer.WriteString(x.cssString("50%"))
|
|
||||||
buffer.WriteString(" ")
|
|
||||||
buffer.WriteString(y.cssString("50%"))
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.WriteString(", ")
|
|
||||||
if !gradient.writeGradient(session, buffer) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.WriteString(") ")
|
|
||||||
|
|
||||||
return buffer.String()
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,416 @@
|
||||||
|
package rui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type backgroundConicGradient struct {
|
||||||
|
backgroundElement
|
||||||
|
}
|
||||||
|
|
||||||
|
// BackgroundGradientAngle defined an element of the conic gradient
|
||||||
|
type BackgroundGradientAngle struct {
|
||||||
|
// Color - the color of the key angle. Must not be nil.
|
||||||
|
// Can take a value of Color type or string (color constant or textual description of the color)
|
||||||
|
Color interface{}
|
||||||
|
// Angle - the key angle. Optional (may be nil).
|
||||||
|
// Can take a value of AngleUnit type or string (angle constant or textual description of the angle)
|
||||||
|
Angle interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBackgroundConicGradient creates the new background conic gradient
|
||||||
|
func NewBackgroundConicGradient(params Params) BackgroundElement {
|
||||||
|
result := new(backgroundConicGradient)
|
||||||
|
result.properties = map[string]interface{}{}
|
||||||
|
for tag, value := range params {
|
||||||
|
result.Set(tag, value)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (point *BackgroundGradientAngle) String() string {
|
||||||
|
result := "black"
|
||||||
|
if point.Color != nil {
|
||||||
|
switch color := point.Color.(type) {
|
||||||
|
case string:
|
||||||
|
result = color
|
||||||
|
|
||||||
|
case Color:
|
||||||
|
result = color.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if point.Angle != nil {
|
||||||
|
switch value := point.Angle.(type) {
|
||||||
|
case string:
|
||||||
|
result += " " + value
|
||||||
|
|
||||||
|
case AngleUnit:
|
||||||
|
result += " " + value.String()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (point *BackgroundGradientAngle) color(session Session) (Color, bool) {
|
||||||
|
if point.Color != nil {
|
||||||
|
switch color := point.Color.(type) {
|
||||||
|
case string:
|
||||||
|
if color != "" {
|
||||||
|
if color[0] == '@' {
|
||||||
|
if clr, ok := session.Color(color[1:]); ok {
|
||||||
|
return clr, true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if clr, ok := StringToColor(color); ok {
|
||||||
|
return clr, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case Color:
|
||||||
|
return color, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (point *BackgroundGradientAngle) isValid(session Session) bool {
|
||||||
|
_, ok := point.color(session)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (point *BackgroundGradientAngle) cssString(session Session, buffer *strings.Builder) {
|
||||||
|
if color, ok := point.color(session); ok {
|
||||||
|
buffer.WriteString(color.cssString())
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if point.Angle != nil {
|
||||||
|
switch value := point.Angle.(type) {
|
||||||
|
case string:
|
||||||
|
if value != "" {
|
||||||
|
if value[0] == '@' {
|
||||||
|
if val, ok := session.Constant(value[1:]); ok {
|
||||||
|
value = val
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if angle, ok := StringToAngleUnit(value); ok {
|
||||||
|
buffer.WriteRune(' ')
|
||||||
|
buffer.WriteString(angle.cssString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case AngleUnit:
|
||||||
|
buffer.WriteRune(' ')
|
||||||
|
buffer.WriteString(value.cssString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundConicGradient) Tag() string {
|
||||||
|
return "conic-gradient"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (image *backgroundConicGradient) Clone() BackgroundElement {
|
||||||
|
result := NewBackgroundConicGradient(nil)
|
||||||
|
for tag, value := range image.properties {
|
||||||
|
result.setRaw(tag, value)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundConicGradient) normalizeTag(tag string) string {
|
||||||
|
tag = strings.ToLower(tag)
|
||||||
|
switch tag {
|
||||||
|
case "x-center":
|
||||||
|
tag = CenterX
|
||||||
|
|
||||||
|
case "y-center":
|
||||||
|
tag = CenterY
|
||||||
|
}
|
||||||
|
|
||||||
|
return tag
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundConicGradient) Set(tag string, value interface{}) bool {
|
||||||
|
tag = gradient.normalizeTag(tag)
|
||||||
|
switch tag {
|
||||||
|
case CenterX, CenterY, Repeating, From:
|
||||||
|
return gradient.propertyList.Set(tag, value)
|
||||||
|
|
||||||
|
case Gradient:
|
||||||
|
return gradient.setGradient(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorLogF(`"%s" property is not supported by BackgroundConicGradient`, tag)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundConicGradient) stringToAngle(text string) (interface{}, bool) {
|
||||||
|
if text == "" {
|
||||||
|
return nil, false
|
||||||
|
} else if text[0] == '@' {
|
||||||
|
return text, true
|
||||||
|
}
|
||||||
|
return StringToAngleUnit(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundConicGradient) stringToGradientPoint(text string) (BackgroundGradientAngle, bool) {
|
||||||
|
var result BackgroundGradientAngle
|
||||||
|
colorText := ""
|
||||||
|
pointText := ""
|
||||||
|
|
||||||
|
if index := strings.Index(text, " "); index > 0 {
|
||||||
|
colorText = text[:index]
|
||||||
|
pointText = strings.Trim(text[index+1:], " ")
|
||||||
|
} else {
|
||||||
|
colorText = text
|
||||||
|
}
|
||||||
|
|
||||||
|
if colorText == "" {
|
||||||
|
return result, false
|
||||||
|
}
|
||||||
|
|
||||||
|
if colorText[0] == '@' {
|
||||||
|
result.Color = colorText
|
||||||
|
} else if color, ok := StringToColor(colorText); ok {
|
||||||
|
result.Color = color
|
||||||
|
} else {
|
||||||
|
return result, false
|
||||||
|
}
|
||||||
|
|
||||||
|
if pointText != "" {
|
||||||
|
if angle, ok := gradient.stringToAngle(pointText); ok {
|
||||||
|
result.Angle = angle
|
||||||
|
} else {
|
||||||
|
return result, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundConicGradient) parseGradientText(value string) []BackgroundGradientAngle {
|
||||||
|
elements := strings.Split(value, ",")
|
||||||
|
count := len(elements)
|
||||||
|
if count < 2 {
|
||||||
|
ErrorLog("The gradient must contain at least 2 points")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
vector := make([]BackgroundGradientAngle, count)
|
||||||
|
for i, element := range elements {
|
||||||
|
var ok bool
|
||||||
|
if vector[i], ok = gradient.stringToGradientPoint(strings.Trim(element, " ")); !ok {
|
||||||
|
ErrorLogF(`Ivalid %d element of the conic gradient: "%s"`, i, element)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vector
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundConicGradient) setGradient(value interface{}) bool {
|
||||||
|
if value == nil {
|
||||||
|
delete(gradient.properties, Gradient)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
switch value := value.(type) {
|
||||||
|
case string:
|
||||||
|
if value == "" {
|
||||||
|
delete(gradient.properties, Gradient)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(value, ",") || strings.Contains(value, " ") {
|
||||||
|
if vector := gradient.parseGradientText(value); vector != nil {
|
||||||
|
gradient.properties[Gradient] = vector
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
} else if value[0] == '@' {
|
||||||
|
gradient.properties[Gradient] = value
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorLogF(`Ivalid conic gradient: "%s"`, value)
|
||||||
|
return false
|
||||||
|
|
||||||
|
case []interface{}:
|
||||||
|
count := len(value)
|
||||||
|
if count < 2 {
|
||||||
|
ErrorLog("The gradient must contain at least 2 points")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
vector := make([]BackgroundGradientAngle, len(value))
|
||||||
|
for i, point := range value {
|
||||||
|
if point == nil {
|
||||||
|
ErrorLogF("Ivalid %d element of the conic gradient: nil", i)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch element := point.(type) {
|
||||||
|
case string:
|
||||||
|
if data, ok := gradient.stringToGradientPoint(element); ok {
|
||||||
|
vector[i] = data
|
||||||
|
} else {
|
||||||
|
ErrorLogF("Ivalid %d element of the conic gradient: %s", i, element)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
case Color:
|
||||||
|
vector[i].Color = element
|
||||||
|
|
||||||
|
case BackgroundGradientAngle:
|
||||||
|
if element.Color == nil {
|
||||||
|
ErrorLogF("Ivalid %d element of the conic gradient: Color is nil", i)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
switch color := element.Color.(type) {
|
||||||
|
case string:
|
||||||
|
if color == "" {
|
||||||
|
ErrorLogF("Ivalid %d element of the conic gradient: empty Color text", i)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if color[0] != '@' {
|
||||||
|
if clr, ok := StringToColor(color); ok {
|
||||||
|
element.Color = clr
|
||||||
|
} else {
|
||||||
|
ErrorLogF("Ivalid %d element of the conic gradient: invalid Color text", i)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case Color:
|
||||||
|
// do nothing
|
||||||
|
|
||||||
|
default:
|
||||||
|
ErrorLogF("Ivalid %d element of the conic gradient: unsupported Color type", i)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if element.Angle != nil {
|
||||||
|
switch point := element.Angle.(type) {
|
||||||
|
case string:
|
||||||
|
if angle, ok := gradient.stringToAngle(point); ok {
|
||||||
|
element.Angle = angle
|
||||||
|
} else {
|
||||||
|
ErrorLogF("Ivalid %d element of the conic gradient: invalid Point text", i)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
case AngleUnit:
|
||||||
|
// do nothing
|
||||||
|
|
||||||
|
default:
|
||||||
|
ErrorLogF("Ivalid %d element of the conic gradient: unsupported Point type", i)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector[i] = element
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gradient.properties[Gradient] = vector
|
||||||
|
return true
|
||||||
|
|
||||||
|
case []BackgroundGradientAngle:
|
||||||
|
count := len(value)
|
||||||
|
if count < 2 {
|
||||||
|
ErrorLog("The gradient must contain at least 2 points")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, point := range value {
|
||||||
|
if point.Color == nil {
|
||||||
|
ErrorLogF("Ivalid %d element of the conic gradient: Color is nil", i)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gradient.properties[Gradient] = value
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundConicGradient) Get(tag string) interface{} {
|
||||||
|
return gradient.backgroundElement.Get(gradient.normalizeTag(tag))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundConicGradient) cssStyle(session Session) string {
|
||||||
|
|
||||||
|
points := []BackgroundGradientAngle{}
|
||||||
|
if value, ok := gradient.properties[Gradient]; ok {
|
||||||
|
switch value := value.(type) {
|
||||||
|
case string:
|
||||||
|
if text, ok := session.resolveConstants(value); ok && text != "" {
|
||||||
|
if points = gradient.parseGradientText(text); points == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ErrorLog(`Invalid conic gradient: ` + value)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
case []BackgroundGradientAngle:
|
||||||
|
points = value
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(points) < 2 {
|
||||||
|
ErrorLog("The gradient must contain at least 2 points")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer := allocStringBuilder()
|
||||||
|
defer freeStringBuilder(buffer)
|
||||||
|
|
||||||
|
if repeating, _ := boolProperty(gradient, Repeating, session); repeating {
|
||||||
|
buffer.WriteString(`repeating-conic-gradient(`)
|
||||||
|
} else {
|
||||||
|
buffer.WriteString(`conic-gradient(`)
|
||||||
|
}
|
||||||
|
|
||||||
|
comma := false
|
||||||
|
if angle, ok := angleProperty(gradient, From, session); ok {
|
||||||
|
buffer.WriteString("from ")
|
||||||
|
buffer.WriteString(angle.cssString())
|
||||||
|
comma = true
|
||||||
|
}
|
||||||
|
|
||||||
|
x, _ := sizeProperty(gradient, CenterX, session)
|
||||||
|
y, _ := sizeProperty(gradient, CenterX, session)
|
||||||
|
if x.Type != Auto || y.Type != Auto {
|
||||||
|
if comma {
|
||||||
|
buffer.WriteRune(' ')
|
||||||
|
}
|
||||||
|
buffer.WriteString("at ")
|
||||||
|
buffer.WriteString(x.cssString("50%"))
|
||||||
|
buffer.WriteString(" ")
|
||||||
|
buffer.WriteString(y.cssString("50%"))
|
||||||
|
comma = true
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, point := range points {
|
||||||
|
if point.isValid(session) {
|
||||||
|
if comma {
|
||||||
|
buffer.WriteString(`, `)
|
||||||
|
}
|
||||||
|
point.cssString(session, buffer)
|
||||||
|
comma = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.WriteString(") ")
|
||||||
|
|
||||||
|
return buffer.String()
|
||||||
|
}
|
|
@ -0,0 +1,508 @@
|
||||||
|
package rui
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
const (
|
||||||
|
|
||||||
|
// ToTopGradient is value of the Direction property of a linear gradient. The value is equivalent to the 0deg angle
|
||||||
|
ToTopGradient = 0
|
||||||
|
// ToRightTopGradient is value of the Direction property of a linear gradient.
|
||||||
|
ToRightTopGradient = 1
|
||||||
|
// ToRightGradient is value of the Direction property of a linear gradient. The value is equivalent to the 90deg angle
|
||||||
|
ToRightGradient = 2
|
||||||
|
// ToRightBottomGradient is value of the Direction property of a linear gradient.
|
||||||
|
ToRightBottomGradient = 3
|
||||||
|
// ToBottomGradient is value of the Direction property of a linear gradient. The value is equivalent to the 180deg angle
|
||||||
|
ToBottomGradient = 4
|
||||||
|
// ToLeftBottomGradient is value of the Direction property of a linear gradient.
|
||||||
|
ToLeftBottomGradient = 5
|
||||||
|
// ToLeftGradient is value of the Direction property of a linear gradient. The value is equivalent to the 270deg angle
|
||||||
|
ToLeftGradient = 6
|
||||||
|
// ToLeftTopGradient is value of the Direction property of a linear gradient.
|
||||||
|
ToLeftTopGradient = 7
|
||||||
|
|
||||||
|
// EllipseGradient is value of the Shape property of a radial gradient background:
|
||||||
|
// the shape is an axis-aligned ellipse
|
||||||
|
EllipseGradient = 0
|
||||||
|
// CircleGradient is value of the Shape property of a radial gradient background:
|
||||||
|
// the gradient's shape is a circle with constant radius
|
||||||
|
CircleGradient = 1
|
||||||
|
|
||||||
|
// ClosestSideGradient is value of the Radius property of a radial gradient background:
|
||||||
|
// The gradient's ending shape meets the side of the box closest to its center (for circles)
|
||||||
|
// or meets both the vertical and horizontal sides closest to the center (for ellipses).
|
||||||
|
ClosestSideGradient = 0
|
||||||
|
// ClosestCornerGradient is value of the Radius property of a radial gradient background:
|
||||||
|
// The gradient's ending shape is sized so that it exactly meets the closest corner
|
||||||
|
// of the box from its center.
|
||||||
|
ClosestCornerGradient = 1
|
||||||
|
// FarthestSideGradient is value of the Radius property of a radial gradient background:
|
||||||
|
// Similar to closest-side, except the ending shape is sized to meet the side of the box
|
||||||
|
// farthest from its center (or vertical and horizontal sides).
|
||||||
|
FarthestSideGradient = 2
|
||||||
|
// FarthestCornerGradient is value of the Radius property of a radial gradient background:
|
||||||
|
// The default value, the gradient's ending shape is sized so that it exactly meets
|
||||||
|
// the farthest corner of the box from its center.
|
||||||
|
FarthestCornerGradient = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
// BackgroundGradientPoint define point on gradient straight line
|
||||||
|
type BackgroundGradientPoint struct {
|
||||||
|
// Pos - the distance from the start of the gradient straight line
|
||||||
|
Pos SizeUnit
|
||||||
|
// Color - the color of the point
|
||||||
|
Color Color
|
||||||
|
}
|
||||||
|
|
||||||
|
type backgroundGradient struct {
|
||||||
|
backgroundElement
|
||||||
|
}
|
||||||
|
|
||||||
|
type backgroundLinearGradient struct {
|
||||||
|
backgroundGradient
|
||||||
|
}
|
||||||
|
|
||||||
|
type backgroundRadialGradient struct {
|
||||||
|
backgroundGradient
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBackgroundLinearGradient creates the new background linear gradient
|
||||||
|
func NewBackgroundLinearGradient(params Params) BackgroundElement {
|
||||||
|
result := new(backgroundLinearGradient)
|
||||||
|
result.properties = map[string]interface{}{}
|
||||||
|
for tag, value := range params {
|
||||||
|
result.Set(tag, value)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBackgroundRadialGradient creates the new background radial gradient
|
||||||
|
func NewBackgroundRadialGradient(params Params) BackgroundElement {
|
||||||
|
result := new(backgroundRadialGradient)
|
||||||
|
result.properties = map[string]interface{}{}
|
||||||
|
for tag, value := range params {
|
||||||
|
result.Set(tag, value)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundGradient) Set(tag string, value interface{}) bool {
|
||||||
|
|
||||||
|
switch tag = strings.ToLower(tag); tag {
|
||||||
|
case Repeating:
|
||||||
|
return gradient.setBoolProperty(tag, value)
|
||||||
|
|
||||||
|
case Gradient:
|
||||||
|
switch value := value.(type) {
|
||||||
|
case string:
|
||||||
|
if value != "" {
|
||||||
|
elements := strings.Split(value, `,`)
|
||||||
|
if count := len(elements); count > 1 {
|
||||||
|
points := make([]interface{}, count)
|
||||||
|
for i, element := range elements {
|
||||||
|
if strings.Contains(element, "@") {
|
||||||
|
points[i] = element
|
||||||
|
} else {
|
||||||
|
var point BackgroundGradientPoint
|
||||||
|
if point.setValue(element) {
|
||||||
|
points[i] = point
|
||||||
|
} else {
|
||||||
|
ErrorLogF("Invalid gradient element #%d: %s", i, element)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gradient.properties[Gradient] = points
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
text := strings.Trim(value, " \n\r\t")
|
||||||
|
if text[0] == '@' {
|
||||||
|
gradient.properties[Gradient] = text
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case []BackgroundGradientPoint:
|
||||||
|
if len(value) >= 2 {
|
||||||
|
gradient.properties[Gradient] = value
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
case []Color:
|
||||||
|
count := len(value)
|
||||||
|
if count >= 2 {
|
||||||
|
points := make([]BackgroundGradientPoint, count)
|
||||||
|
for i, color := range value {
|
||||||
|
points[i].Color = color
|
||||||
|
points[i].Pos = AutoSize()
|
||||||
|
}
|
||||||
|
gradient.properties[Gradient] = points
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
case []GradientPoint:
|
||||||
|
count := len(value)
|
||||||
|
if count >= 2 {
|
||||||
|
points := make([]BackgroundGradientPoint, count)
|
||||||
|
for i, point := range value {
|
||||||
|
points[i].Color = point.Color
|
||||||
|
points[i].Pos = Percent(point.Offset * 100)
|
||||||
|
}
|
||||||
|
gradient.properties[Gradient] = points
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
case []interface{}:
|
||||||
|
if count := len(value); count > 1 {
|
||||||
|
points := make([]interface{}, count)
|
||||||
|
for i, element := range value {
|
||||||
|
switch element := element.(type) {
|
||||||
|
case string:
|
||||||
|
if strings.Contains(element, "@") {
|
||||||
|
points[i] = element
|
||||||
|
} else {
|
||||||
|
var point BackgroundGradientPoint
|
||||||
|
if !point.setValue(element) {
|
||||||
|
ErrorLogF("Invalid gradient element #%d: %s", i, element)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
points[i] = point
|
||||||
|
}
|
||||||
|
|
||||||
|
case BackgroundGradientPoint:
|
||||||
|
points[i] = element
|
||||||
|
|
||||||
|
case GradientPoint:
|
||||||
|
points[i] = BackgroundGradientPoint{Color: element.Color, Pos: Percent(element.Offset * 100)}
|
||||||
|
|
||||||
|
case Color:
|
||||||
|
points[i] = BackgroundGradientPoint{Color: element, Pos: AutoSize()}
|
||||||
|
|
||||||
|
default:
|
||||||
|
ErrorLogF("Invalid gradient element #%d: %v", i, element)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gradient.properties[Gradient] = points
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
ErrorLogF("Invalid gradient %v", value)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return gradient.backgroundElement.Set(tag, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (point *BackgroundGradientPoint) setValue(value string) bool {
|
||||||
|
var ok bool
|
||||||
|
|
||||||
|
switch elements := strings.Split(value, `:`); len(elements) {
|
||||||
|
case 2:
|
||||||
|
if point.Color, ok = StringToColor(elements[0]); !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if point.Pos, ok = StringToSizeUnit(elements[1]); !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
if point.Color, ok = StringToColor(elements[0]); !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
point.Pos = AutoSize()
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundGradient) writeGradient(session Session, buffer *strings.Builder) bool {
|
||||||
|
|
||||||
|
value, ok := gradient.properties[Gradient]
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
points := []BackgroundGradientPoint{}
|
||||||
|
|
||||||
|
switch value := value.(type) {
|
||||||
|
case string:
|
||||||
|
if text, ok := session.resolveConstants(value); ok && text != "" {
|
||||||
|
elements := strings.Split(text, `,`)
|
||||||
|
points := make([]BackgroundGradientPoint, len(elements))
|
||||||
|
for i, element := range elements {
|
||||||
|
if !points[i].setValue(element) {
|
||||||
|
ErrorLogF(`Invalid gradient point #%d: "%s"`, i, element)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ErrorLog(`Invalid gradient: ` + value)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
case []BackgroundGradientPoint:
|
||||||
|
points = value
|
||||||
|
|
||||||
|
case []interface{}:
|
||||||
|
points = make([]BackgroundGradientPoint, len(value))
|
||||||
|
for i, element := range value {
|
||||||
|
switch element := element.(type) {
|
||||||
|
case string:
|
||||||
|
if text, ok := session.resolveConstants(element); ok && text != "" {
|
||||||
|
if !points[i].setValue(text) {
|
||||||
|
ErrorLogF(`Invalid gradient point #%d: "%s"`, i, text)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ErrorLogF(`Invalid gradient point #%d: "%s"`, i, text)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
case BackgroundGradientPoint:
|
||||||
|
points[i] = element
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(points) > 0 {
|
||||||
|
for i, point := range points {
|
||||||
|
if i > 0 {
|
||||||
|
buffer.WriteString(`, `)
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.WriteString(point.Color.cssString())
|
||||||
|
if point.Pos.Type != Auto {
|
||||||
|
buffer.WriteRune(' ')
|
||||||
|
buffer.WriteString(point.Pos.cssString(""))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundLinearGradient) Tag() string {
|
||||||
|
return "linear-gradient"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (image *backgroundLinearGradient) Clone() BackgroundElement {
|
||||||
|
result := NewBackgroundLinearGradient(nil)
|
||||||
|
for tag, value := range image.properties {
|
||||||
|
result.setRaw(tag, value)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundLinearGradient) Set(tag string, value interface{}) bool {
|
||||||
|
if strings.ToLower(tag) == Direction {
|
||||||
|
switch value := value.(type) {
|
||||||
|
case AngleUnit:
|
||||||
|
gradient.properties[Direction] = value
|
||||||
|
return true
|
||||||
|
|
||||||
|
case string:
|
||||||
|
var angle AngleUnit
|
||||||
|
if ok, _ := angle.setValue(value); ok {
|
||||||
|
gradient.properties[Direction] = angle
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return gradient.setEnumProperty(tag, value, enumProperties[Direction].values)
|
||||||
|
}
|
||||||
|
|
||||||
|
return gradient.backgroundGradient.Set(tag, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundLinearGradient) cssStyle(session Session) string {
|
||||||
|
buffer := allocStringBuilder()
|
||||||
|
defer freeStringBuilder(buffer)
|
||||||
|
|
||||||
|
if repeating, _ := boolProperty(gradient, Repeating, session); repeating {
|
||||||
|
buffer.WriteString(`repeating-linear-gradient(`)
|
||||||
|
} else {
|
||||||
|
buffer.WriteString(`linear-gradient(`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if value, ok := gradient.properties[Direction]; ok {
|
||||||
|
switch value := value.(type) {
|
||||||
|
case string:
|
||||||
|
if text, ok := session.resolveConstants(value); ok {
|
||||||
|
direction := enumProperties[Direction]
|
||||||
|
if n, ok := enumStringToInt(text, direction.values, false); ok {
|
||||||
|
buffer.WriteString(direction.cssValues[n])
|
||||||
|
buffer.WriteString(", ")
|
||||||
|
} else {
|
||||||
|
if angle, ok := StringToAngleUnit(text); ok {
|
||||||
|
buffer.WriteString(angle.cssString())
|
||||||
|
buffer.WriteString(", ")
|
||||||
|
} else {
|
||||||
|
ErrorLog(`Invalid linear gradient direction: ` + text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ErrorLog(`Invalid linear gradient direction: ` + value)
|
||||||
|
}
|
||||||
|
|
||||||
|
case int:
|
||||||
|
values := enumProperties[Direction].cssValues
|
||||||
|
if value >= 0 && value < len(values) {
|
||||||
|
buffer.WriteString(values[value])
|
||||||
|
buffer.WriteString(", ")
|
||||||
|
} else {
|
||||||
|
ErrorLogF(`Invalid linear gradient direction: %d`, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
case AngleUnit:
|
||||||
|
buffer.WriteString(value.cssString())
|
||||||
|
buffer.WriteString(", ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !gradient.writeGradient(session, buffer) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.WriteString(") ")
|
||||||
|
return buffer.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundRadialGradient) Tag() string {
|
||||||
|
return "radial-gradient"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (image *backgroundRadialGradient) Clone() BackgroundElement {
|
||||||
|
result := NewBackgroundRadialGradient(nil)
|
||||||
|
for tag, value := range image.properties {
|
||||||
|
result.setRaw(tag, value)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundRadialGradient) normalizeTag(tag string) string {
|
||||||
|
tag = strings.ToLower(tag)
|
||||||
|
switch tag {
|
||||||
|
case Radius:
|
||||||
|
tag = RadialGradientRadius
|
||||||
|
|
||||||
|
case Shape:
|
||||||
|
tag = RadialGradientShape
|
||||||
|
|
||||||
|
case "x-center":
|
||||||
|
tag = CenterX
|
||||||
|
|
||||||
|
case "y-center":
|
||||||
|
tag = CenterY
|
||||||
|
}
|
||||||
|
|
||||||
|
return tag
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundRadialGradient) Set(tag string, value interface{}) bool {
|
||||||
|
tag = gradient.normalizeTag(tag)
|
||||||
|
switch tag {
|
||||||
|
case RadialGradientRadius:
|
||||||
|
switch value := value.(type) {
|
||||||
|
case string, SizeUnit:
|
||||||
|
return gradient.propertyList.Set(RadialGradientRadius, value)
|
||||||
|
|
||||||
|
case int:
|
||||||
|
n := value
|
||||||
|
if n >= 0 && n < len(enumProperties[RadialGradientRadius].values) {
|
||||||
|
return gradient.propertyList.Set(RadialGradientRadius, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ErrorLogF(`Invalid value of "%s" property: %v`, tag, value)
|
||||||
|
|
||||||
|
case RadialGradientShape:
|
||||||
|
return gradient.propertyList.Set(RadialGradientShape, value)
|
||||||
|
|
||||||
|
case CenterX, CenterY:
|
||||||
|
return gradient.propertyList.Set(tag, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return gradient.backgroundGradient.Set(tag, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundRadialGradient) Get(tag string) interface{} {
|
||||||
|
return gradient.backgroundGradient.Get(gradient.normalizeTag(tag))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gradient *backgroundRadialGradient) cssStyle(session Session) string {
|
||||||
|
buffer := allocStringBuilder()
|
||||||
|
defer freeStringBuilder(buffer)
|
||||||
|
|
||||||
|
if repeating, _ := boolProperty(gradient, Repeating, session); repeating {
|
||||||
|
buffer.WriteString(`repeating-radial-gradient(`)
|
||||||
|
} else {
|
||||||
|
buffer.WriteString(`radial-gradient(`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if shape, ok := enumProperty(gradient, RadialGradientShape, session, EllipseGradient); ok && shape == CircleGradient {
|
||||||
|
buffer.WriteString(`circle `)
|
||||||
|
} else {
|
||||||
|
buffer.WriteString(`ellipse `)
|
||||||
|
}
|
||||||
|
|
||||||
|
if value, ok := gradient.properties[RadialGradientRadius]; ok {
|
||||||
|
switch value := value.(type) {
|
||||||
|
case string:
|
||||||
|
if text, ok := session.resolveConstants(value); ok {
|
||||||
|
values := enumProperties[RadialGradientRadius]
|
||||||
|
if n, ok := enumStringToInt(text, values.values, false); ok {
|
||||||
|
buffer.WriteString(values.cssValues[n])
|
||||||
|
buffer.WriteString(" ")
|
||||||
|
} else {
|
||||||
|
if r, ok := StringToSizeUnit(text); ok && r.Type != Auto {
|
||||||
|
buffer.WriteString(r.cssString(""))
|
||||||
|
buffer.WriteString(" ")
|
||||||
|
} else {
|
||||||
|
ErrorLog(`Invalid radial gradient radius: ` + text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ErrorLog(`Invalid radial gradient radius: ` + value)
|
||||||
|
}
|
||||||
|
|
||||||
|
case int:
|
||||||
|
values := enumProperties[RadialGradientRadius].cssValues
|
||||||
|
if value >= 0 && value < len(values) {
|
||||||
|
buffer.WriteString(values[value])
|
||||||
|
buffer.WriteString(" ")
|
||||||
|
} else {
|
||||||
|
ErrorLogF(`Invalid radial gradient radius: %d`, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
case SizeUnit:
|
||||||
|
if value.Type != Auto {
|
||||||
|
buffer.WriteString(value.cssString(""))
|
||||||
|
buffer.WriteString(" ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
x, _ := sizeProperty(gradient, CenterX, session)
|
||||||
|
y, _ := sizeProperty(gradient, CenterX, session)
|
||||||
|
if x.Type != Auto || y.Type != Auto {
|
||||||
|
buffer.WriteString("at ")
|
||||||
|
buffer.WriteString(x.cssString("50%"))
|
||||||
|
buffer.WriteString(" ")
|
||||||
|
buffer.WriteString(y.cssString("50%"))
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.WriteString(", ")
|
||||||
|
if !gradient.writeGradient(session, buffer) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.WriteString(") ")
|
||||||
|
|
||||||
|
return buffer.String()
|
||||||
|
}
|
|
@ -359,6 +359,8 @@ const (
|
||||||
Direction = "direction"
|
Direction = "direction"
|
||||||
// Repeating is the constant for the "repeating" property tag.
|
// Repeating is the constant for the "repeating" property tag.
|
||||||
Repeating = "repeating"
|
Repeating = "repeating"
|
||||||
|
// Repeating is the constant for the "repeating" property tag.
|
||||||
|
From = "from"
|
||||||
// RadialGradientRadius is the constant for the "radial-gradient-radius" property tag.
|
// RadialGradientRadius is the constant for the "radial-gradient-radius" property tag.
|
||||||
RadialGradientRadius = "radial-gradient-radius"
|
RadialGradientRadius = "radial-gradient-radius"
|
||||||
// RadialGradientShape is the constant for the "radial-gradient-shape" property tag.
|
// RadialGradientShape is the constant for the "radial-gradient-shape" property tag.
|
||||||
|
|
|
@ -33,6 +33,7 @@ var angleProperties = []string{
|
||||||
Rotate,
|
Rotate,
|
||||||
SkewX,
|
SkewX,
|
||||||
SkewY,
|
SkewY,
|
||||||
|
From,
|
||||||
}
|
}
|
||||||
|
|
||||||
var boolProperties = []string{
|
var boolProperties = []string{
|
||||||
|
@ -58,6 +59,7 @@ var boolProperties = []string{
|
||||||
AnimationPaused,
|
AnimationPaused,
|
||||||
Multiple,
|
Multiple,
|
||||||
TabCloseButton,
|
TabCloseButton,
|
||||||
|
Repeating,
|
||||||
}
|
}
|
||||||
|
|
||||||
var intProperties = []string{
|
var intProperties = []string{
|
||||||
|
|
Loading…
Reference in New Issue