2021-09-07 17:36:50 +03:00
package rui
2024-08-13 13:52:47 +03:00
import (
"fmt"
"math"
"strings"
)
2024-11-18 17:35:21 +03:00
// Constants for [TransformProperty] specific properties
2021-09-07 17:36:50 +03:00
const (
2024-11-18 17:35:21 +03:00
// Transform is the constant for "transform" property tag.
2024-11-13 12:56:39 +03:00
//
2024-12-05 20:15:39 +03:00
// Used by View.
2024-11-24 09:52:43 +03:00
// Specify translation, scale and rotation over x, y and z axes as well as a distortion of a view along x and y axes.
2024-11-13 12:56:39 +03:00
//
2024-12-05 20:15:39 +03:00
// Supported types: TransformProperty, string.
2024-11-13 12:56:39 +03:00
//
2024-12-05 20:15:39 +03:00
// See TransformProperty description for more details.
2024-11-13 12:56:39 +03:00
//
// Conversion rules:
2024-12-05 20:15:39 +03:00
// - TransformProperty - stored as is, no conversion performed.
// - string - string representation of TransformProperty interface. Example: "_{translate-x = 10px, scale-y = 1.1}".
2024-11-18 17:35:21 +03:00
Transform PropertyName = "transform"
2024-11-13 12:56:39 +03:00
2024-09-18 13:50:06 +03:00
// Perspective is the constant for "perspective" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
2024-11-13 12:56:39 +03:00
// Distance between the z-plane and the user in order to give a 3D-positioned element some perspective. Each 3D element
2024-09-18 13:50:06 +03:00
// with z > 0 becomes larger, each 3D-element with z < 0 becomes smaller. The default value is 0 (no 3D effects).
//
2024-12-05 20:15:39 +03:00
// Supported types: SizeUnit, SizeFunc, string, float, int.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Internal type is SizeUnit, other types converted to it during assignment.
// See SizeUnit description for more details.
2024-11-13 12:56:39 +03:00
Perspective PropertyName = "perspective"
2024-08-13 13:52:47 +03:00
2024-09-18 13:50:06 +03:00
// PerspectiveOriginX is the constant for "perspective-origin-x" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View.
2024-11-13 12:56:39 +03:00
// x-coordinate of the position at which the viewer is looking. It is used as the vanishing point by the "perspective"
2024-09-18 13:50:06 +03:00
// property. The default value is 50%.
//
2024-12-05 20:15:39 +03:00
// Supported types: SizeUnit, SizeFunc, string, float, int.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Internal type is SizeUnit, other types converted to it during assignment.
// See SizeUnit description for more details.
2024-11-13 12:56:39 +03:00
PerspectiveOriginX PropertyName = "perspective-origin-x"
2024-08-13 13:52:47 +03:00
2024-09-18 13:50:06 +03:00
// PerspectiveOriginY is the constant for "perspective-origin-y" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View.
2024-11-13 12:56:39 +03:00
// y-coordinate of the position at which the viewer is looking. It is used as the vanishing point by the "perspective"
2024-09-18 13:50:06 +03:00
// property. The default value is 50%.
//
2024-12-05 20:15:39 +03:00
// Supported types: SizeUnit, SizeFunc, string, float, int.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Internal type is SizeUnit, other types converted to it during assignment.
// See SizeUnit description for more details.
2024-11-13 12:56:39 +03:00
PerspectiveOriginY PropertyName = "perspective-origin-y"
2024-08-13 13:52:47 +03:00
2024-09-18 13:50:06 +03:00
// BackfaceVisible is the constant for "backface-visibility" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View.
// Controls whether the back face of a view is visible when turned towards the user. Default value is true.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Supported types: bool, int, string.
2024-09-18 13:50:06 +03:00
//
// Values:
2024-12-05 20:15:39 +03:00
// - true, 1, "true", "yes", "on", "1" - Back face is visible when turned towards the user.
// - false, 0, "false", "no", "off", "0" - Back face is hidden, effectively making the view invisible when turned away from the user.
2024-11-13 12:56:39 +03:00
BackfaceVisible PropertyName = "backface-visibility"
2024-08-13 13:52:47 +03:00
* Added "push-perspective", "push-rotate-x", "push-rotate-y", "push-rotate-z", "push-rotate", "push-skew-x", "push-skew-y", "push-scale-x", "push-scale-y", "push-scale-z", "push-translate-x", "push-translate-y", "push-translate-z" properties.
2024-11-25 13:03:08 +03:00
// TransformOriginX is the constant for "transform-origin-x" property tag.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Used by View.
2024-09-18 13:50:06 +03:00
// x-coordinate of the point around which a view transformation is applied. The default value is 50%.
//
2024-12-05 20:15:39 +03:00
// Supported types: SizeUnit, SizeFunc, string, float, int.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Internal type is SizeUnit, other types converted to it during assignment.
// See SizeUnit description for more details.
2024-11-18 17:20:25 +03:00
TransformOriginX PropertyName = "transform-origin-x"
2024-08-13 13:52:47 +03:00
* Added "push-perspective", "push-rotate-x", "push-rotate-y", "push-rotate-z", "push-rotate", "push-skew-x", "push-skew-y", "push-scale-x", "push-scale-y", "push-scale-z", "push-translate-x", "push-translate-y", "push-translate-z" properties.
2024-11-25 13:03:08 +03:00
// TransformOriginY is the constant for "transform-origin-y" property tag.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Used by View.
2024-09-18 13:50:06 +03:00
// y-coordinate of the point around which a view transformation is applied. The default value is 50%.
//
2024-12-05 20:15:39 +03:00
// Supported types: SizeUnit, SizeFunc, string, float, int.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Internal type is SizeUnit, other types converted to it during assignment.
// See SizeUnit description for more details.
2024-11-18 17:20:25 +03:00
TransformOriginY PropertyName = "transform-origin-y"
2024-08-13 13:52:47 +03:00
* Added "push-perspective", "push-rotate-x", "push-rotate-y", "push-rotate-z", "push-rotate", "push-skew-x", "push-skew-y", "push-scale-x", "push-scale-y", "push-scale-z", "push-translate-x", "push-translate-y", "push-translate-z" properties.
2024-11-25 13:03:08 +03:00
// TransformOriginZ is the constant for "transform-origin-z" property tag.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Used by View.
2024-09-18 13:50:06 +03:00
// z-coordinate of the point around which a view transformation is applied. The default value is 50%.
//
2024-12-05 20:15:39 +03:00
// Supported types: SizeUnit, SizeFunc, string, float, int.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Internal type is SizeUnit, other types converted to it during assignment.
// See SizeUnit description for more details.
2024-11-18 17:20:25 +03:00
TransformOriginZ PropertyName = "transform-origin-z"
2024-08-13 13:52:47 +03:00
2024-09-18 13:50:06 +03:00
// TranslateX is the constant for "translate-x" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
2024-09-18 13:50:06 +03:00
//
// x-axis translation value of a 2D/3D translation.
//
2024-12-05 20:15:39 +03:00
// Supported types: SizeUnit, SizeFunc, string, float, int.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Internal type is SizeUnit, other types converted to it during assignment.
// See SizeUnit description for more details.
2024-11-13 12:56:39 +03:00
TranslateX PropertyName = "translate-x"
2024-08-13 13:52:47 +03:00
2024-09-18 13:50:06 +03:00
// TranslateY is the constant for "translate-y" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
2024-09-18 13:50:06 +03:00
//
// x-axis translation value of a 2D/3D translation.
//
2024-12-05 20:15:39 +03:00
// Supported types: SizeUnit, SizeFunc, string, float, int.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Internal type is SizeUnit, other types converted to it during assignment.
// See SizeUnit description for more details.
2024-11-13 12:56:39 +03:00
TranslateY PropertyName = "translate-y"
2024-08-13 13:52:47 +03:00
2024-09-18 13:50:06 +03:00
// TranslateZ is the constant for "translate-z" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
2024-09-18 13:50:06 +03:00
//
// z-axis translation value of a 3D translation.
//
2024-12-05 20:15:39 +03:00
// Supported types: SizeUnit, SizeFunc, string, float, int.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Internal type is SizeUnit, other types converted to it during assignment.
// See SizeUnit description for more details.
2024-11-13 12:56:39 +03:00
TranslateZ PropertyName = "translate-z"
2024-08-13 13:52:47 +03:00
2024-09-18 13:50:06 +03:00
// ScaleX is the constant for "scale-x" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
2024-09-18 13:50:06 +03:00
//
2024-11-13 12:56:39 +03:00
// x-axis scaling value of a 2D/3D scale. The original scale is 1. Values between 0 and 1 are used to decrease original
2024-09-18 13:50:06 +03:00
// scale, more than 1 - to increase. The default value is 1.
//
2024-12-05 20:15:39 +03:00
// Supported types: float, int, string.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Internal type is float, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
ScaleX PropertyName = "scale-x"
2024-08-13 13:52:47 +03:00
2024-09-18 13:50:06 +03:00
// ScaleY is the constant for "scale-y" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
2024-09-18 13:50:06 +03:00
//
2024-11-13 12:56:39 +03:00
// y-axis scaling value of a 2D/3D scale. The original scale is 1. Values between 0 and 1 are used to decrease original
2024-09-18 13:50:06 +03:00
// scale, more than 1 - to increase. The default value is 1.
//
2024-12-05 20:15:39 +03:00
// Supported types: float, int, string.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Internal type is float, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
ScaleY PropertyName = "scale-y"
2024-08-13 13:52:47 +03:00
2024-09-18 13:50:06 +03:00
// ScaleZ is the constant for "scale-z" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
2024-09-18 13:50:06 +03:00
//
2024-11-13 12:56:39 +03:00
// z-axis scaling value of a 3D scale. The original scale is 1. Values between 0 and 1 are used to decrease original
2024-09-18 13:50:06 +03:00
// scale, more than 1 - to increase. The default value is 1.
//
2024-12-05 20:15:39 +03:00
// Supported types: float, int, string.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Internal type is float, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
ScaleZ PropertyName = "scale-z"
2024-08-13 13:52:47 +03:00
2024-09-18 13:50:06 +03:00
// Rotate is the constant for "rotate" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
2024-09-18 13:50:06 +03:00
//
// Angle of the view rotation. A positive angle denotes a clockwise rotation, a negative angle a counter-clockwise.
//
2024-12-05 20:15:39 +03:00
// Supported types: AngleUnit, string, float, int.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Internal type is AngleUnit, other types will be converted to it during assignment.
// See AngleUnit description for more details.
2024-09-18 13:50:06 +03:00
//
// Conversion rules:
2024-12-05 20:15:39 +03:00
// - AngleUnit - stored as is, no conversion performed.
// - string - must contain string representation of AngleUnit. If numeric value will be provided without any suffix then AngleUnit with value and Radian value type will be created.
// - float - a new AngleUnit value will be created with Radian as a type.
// - int - a new AngleUnit value will be created with Radian as a type.
2024-11-13 12:56:39 +03:00
Rotate PropertyName = "rotate"
2024-08-13 13:52:47 +03:00
2024-09-18 13:50:06 +03:00
// RotateX is the constant for "rotate-x" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
2024-09-18 13:50:06 +03:00
//
// x-coordinate of the vector denoting the axis of rotation in range 0 to 1.
//
2024-12-05 20:15:39 +03:00
// Supported types: float, int, string.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Internal type is float, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
RotateX PropertyName = "rotate-x"
2024-08-13 13:52:47 +03:00
2024-09-18 13:50:06 +03:00
// RotateY is the constant for "rotate-y" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
2024-09-18 13:50:06 +03:00
//
// y-coordinate of the vector denoting the axis of rotation in range 0 to 1.
//
2024-12-05 20:15:39 +03:00
// Supported types: float, int, string.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Internal type is float, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
RotateY PropertyName = "rotate-y"
2024-08-13 13:52:47 +03:00
2024-09-18 13:50:06 +03:00
// RotateZ is the constant for "rotate-z" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
2024-09-18 13:50:06 +03:00
//
// z-coordinate of the vector denoting the axis of rotation in range 0 to 1.
//
2024-12-05 20:15:39 +03:00
// Supported types: float, int, string.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Internal type is float, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
RotateZ PropertyName = "rotate-z"
2024-08-13 13:52:47 +03:00
2024-09-18 13:50:06 +03:00
// SkewX is the constant for "skew-x" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
2024-09-18 13:50:06 +03:00
//
// Angle to use to distort the element along the abscissa. The default value is 0.
//
2024-12-05 20:15:39 +03:00
// Supported types: AngleUnit, string, float, int.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Internal type is AngleUnit, other types will be converted to it during assignment.
// See AngleUnit description for more details.
2024-09-18 13:50:06 +03:00
//
// Conversion rules:
2024-12-05 20:15:39 +03:00
// - AngleUnit - stored as is, no conversion performed.
// - string - must contain string representation of AngleUnit. If numeric value will be provided without any suffix then AngleUnit with value and Radian value type will be created.
// - float - a new AngleUnit value will be created with Radian as a type.
// - int - a new AngleUnit value will be created with Radian as a type.
2024-11-13 12:56:39 +03:00
SkewX PropertyName = "skew-x"
2024-08-13 13:52:47 +03:00
2024-09-18 13:50:06 +03:00
// SkewY is the constant for "skew-y" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
2024-09-18 13:50:06 +03:00
//
// Angle to use to distort the element along the ordinate. The default value is 0.
//
2024-12-05 20:15:39 +03:00
// Supported types: AngleUnit, string, float, int.
2024-09-18 13:50:06 +03:00
//
2024-12-05 20:15:39 +03:00
// Internal type is AngleUnit, other types will be converted to it during assignment.
// See AngleUnit description for more details.
2024-09-18 13:50:06 +03:00
//
// Conversion rules:
2024-12-05 20:15:39 +03:00
// - AngleUnit - stored as is, no conversion performed.
// - string - must contain string representation of AngleUnit. If numeric value will be provided without any suffix then AngleUnit with value and Radian value type will be created.
// - float - a new AngleUnit value will be created with Radian as a type.
// - int - a new AngleUnit value will be created with Radian as a type.
2024-11-13 12:56:39 +03:00
SkewY PropertyName = "skew-y"
2021-09-07 17:36:50 +03:00
)
2024-11-18 17:35:21 +03:00
// TransformProperty interface specifies view transformation parameters: the x-, y-, and z-axis translation values,
2024-08-13 13:52:47 +03:00
// the x-, y-, and z-axis scaling values, the angle to use to distort the element along the abscissa and ordinate,
// the angle of the view rotation.
2024-12-05 20:15:39 +03:00
//
2024-11-13 12:56:39 +03:00
// Valid property tags: Perspective ("perspective"), TranslateX ("translate-x"), TranslateY ("translate-y"), TranslateZ ("translate-z"),
2024-08-13 13:52:47 +03:00
// ScaleX ("scale-x"), ScaleY ("scale-y"), ScaleZ ("scale-z"), Rotate ("rotate"), RotateX ("rotate-x"),
// RotateY ("rotate-y"), RotateZ ("rotate-z"), SkewX ("skew-x"), and SkewY ("skew-y")
2024-11-18 17:35:21 +03:00
type TransformProperty interface {
2024-08-13 13:52:47 +03:00
Properties
fmt . Stringer
stringWriter
2024-11-13 12:56:39 +03:00
transformCSS ( session Session ) string
2024-12-02 15:47:06 +03:00
getSkew ( session Session ) ( AngleUnit , AngleUnit , bool )
getTranslate ( session Session ) ( SizeUnit , SizeUnit , SizeUnit )
2024-08-13 13:52:47 +03:00
}
2024-11-18 17:35:21 +03:00
type transformPropertyData struct {
2024-11-13 12:56:39 +03:00
dataProperty
2024-08-13 13:52:47 +03:00
}
2024-09-12 14:05:11 +03:00
// NewTransform creates a new transform property data and return its interface
2024-12-05 20:15:39 +03:00
//
// The following properties can be used:
//
// Perspective ("perspective"), TranslateX ("translate-x"), TranslateY ("translate-y"), TranslateZ ("translate-z"),
// ScaleX ("scale-x"), ScaleY ("scale-y"), ScaleZ ("scale-z"), Rotate ("rotate"), RotateX ("rotate-x"),
// RotateY ("rotate-y"), RotateZ ("rotate-z"), SkewX ("skew-x"), and SkewY ("skew-y")
2024-11-18 17:35:21 +03:00
func NewTransformProperty ( params Params ) TransformProperty {
transform := new ( transformPropertyData )
2024-11-13 12:56:39 +03:00
transform . init ( )
2024-08-13 13:52:47 +03:00
for tag , value := range params {
transform . Set ( tag , value )
}
return transform
}
2024-11-18 17:35:21 +03:00
func ( transform * transformPropertyData ) init ( ) {
2024-11-13 12:56:39 +03:00
transform . dataProperty . init ( )
* Added "push-perspective", "push-rotate-x", "push-rotate-y", "push-rotate-z", "push-rotate", "push-skew-x", "push-skew-y", "push-scale-x", "push-scale-y", "push-scale-z", "push-translate-x", "push-translate-y", "push-translate-z" properties.
2024-11-25 13:03:08 +03:00
transform . normalize = normalizeTransformTag
2024-11-13 12:56:39 +03:00
transform . set = transformSet
transform . supportedProperties = [ ] PropertyName {
RotateX , RotateY , RotateZ , Rotate , SkewX , SkewY , ScaleX , ScaleY , ScaleZ ,
Perspective , TranslateX , TranslateY , TranslateZ ,
}
}
* Added "push-perspective", "push-rotate-x", "push-rotate-y", "push-rotate-z", "push-rotate", "push-skew-x", "push-skew-y", "push-scale-x", "push-scale-y", "push-scale-z", "push-translate-x", "push-translate-y", "push-translate-z" properties.
2024-11-25 13:03:08 +03:00
func normalizeTransformTag ( tag PropertyName ) PropertyName {
tag = defaultNormalize ( tag )
name := string ( tag )
if strings . HasPrefix ( name , "push-" ) {
tag = PropertyName ( name [ 5 : ] )
}
return tag
}
2024-11-18 17:35:21 +03:00
func ( transform * transformPropertyData ) String ( ) string {
2024-11-13 12:56:39 +03:00
buffer := allocStringBuilder ( )
defer freeStringBuilder ( buffer )
transform . writeString ( buffer , "" )
return buffer . String ( )
}
2024-11-18 17:35:21 +03:00
func ( transform * transformPropertyData ) writeString ( buffer * strings . Builder , indent string ) {
2024-11-13 12:56:39 +03:00
buffer . WriteString ( "_{ " )
comma := false
for _ , tag := range transform . supportedProperties {
if value , ok := transform . properties [ tag ] ; ok {
if comma {
buffer . WriteString ( ", " )
}
buffer . WriteString ( string ( tag ) )
buffer . WriteString ( " = " )
writePropertyValue ( buffer , tag , value , indent )
comma = true
}
}
buffer . WriteString ( " }" )
}
func transformSet ( properties Properties , tag PropertyName , value any ) [ ] PropertyName {
switch tag {
case RotateX , RotateY , RotateZ :
return setFloatProperty ( properties , tag , value , 0 , 1 )
case Rotate , SkewX , SkewY :
return setAngleProperty ( properties , tag , value )
case ScaleX , ScaleY , ScaleZ :
return setFloatProperty ( properties , tag , value , - math . MaxFloat64 , math . MaxFloat64 )
case Perspective , TranslateX , TranslateY , TranslateZ :
return setSizeProperty ( properties , tag , value )
}
return nil
}
2024-11-24 09:52:43 +03:00
func valueToTransformProperty ( value any ) TransformProperty {
2024-08-13 13:52:47 +03:00
2024-11-24 09:52:43 +03:00
parseObject := func ( obj DataObject ) TransformProperty {
2024-11-18 17:35:21 +03:00
transform := NewTransformProperty ( nil )
2024-08-13 13:52:47 +03:00
ok := true
for i := 0 ; i < obj . PropertyCount ( ) ; i ++ {
if prop := obj . Property ( i ) ; prop . Type ( ) == TextNode {
2024-11-13 12:56:39 +03:00
if ! transform . Set ( PropertyName ( prop . Tag ( ) ) , prop . Text ( ) ) {
2024-08-13 13:52:47 +03:00
ok = false
}
} else {
ok = false
}
}
2024-11-13 12:56:39 +03:00
if ! ok && transform . empty ( ) {
2024-11-24 09:52:43 +03:00
return nil
2024-08-13 13:52:47 +03:00
}
2024-11-24 09:52:43 +03:00
return transform
2024-08-13 13:52:47 +03:00
}
switch value := value . ( type ) {
2024-11-18 17:35:21 +03:00
case TransformProperty :
2024-11-24 09:52:43 +03:00
return value
2024-08-13 13:52:47 +03:00
case DataObject :
2024-11-24 09:52:43 +03:00
return parseObject ( value )
2024-08-13 13:52:47 +03:00
case DataNode :
if obj := value . Object ( ) ; obj != nil {
2024-11-24 09:52:43 +03:00
return parseObject ( obj )
2024-08-13 13:52:47 +03:00
}
case string :
if obj := ParseDataText ( value ) ; obj != nil {
2024-11-24 09:52:43 +03:00
return parseObject ( obj )
2024-08-13 13:52:47 +03:00
}
}
2024-11-24 09:52:43 +03:00
return nil
}
func setTransformProperty ( properties Properties , tag PropertyName , value any ) bool {
if transform := valueToTransformProperty ( value ) ; transform != nil {
properties . setRaw ( tag , transform )
return true
}
notCompatibleType ( tag , value )
2024-08-13 13:52:47 +03:00
return false
}
2024-11-24 09:52:43 +03:00
func getTransformProperty ( properties Properties , tag PropertyName ) TransformProperty {
if val := properties . getRaw ( tag ) ; val != nil {
2024-11-18 17:35:21 +03:00
if transform , ok := val . ( TransformProperty ) ; ok {
2024-08-13 13:52:47 +03:00
return transform
}
}
return nil
}
* Added "push-perspective", "push-rotate-x", "push-rotate-y", "push-rotate-z", "push-rotate", "push-skew-x", "push-skew-y", "push-scale-x", "push-scale-y", "push-scale-z", "push-translate-x", "push-translate-y", "push-translate-z" properties.
2024-11-25 13:03:08 +03:00
func setTransformPropertyElement ( properties Properties , tag , transformTag PropertyName , value any ) [ ] PropertyName {
srcTag := tag
tag = normalizeTransformTag ( tag )
2024-08-13 13:52:47 +03:00
switch tag {
2024-11-13 12:56:39 +03:00
case Perspective , RotateX , RotateY , RotateZ , Rotate , SkewX , SkewY , ScaleX , ScaleY , ScaleZ , TranslateX , TranslateY , TranslateZ :
2024-11-18 17:20:25 +03:00
var result [ ] PropertyName = nil
* Added "push-perspective", "push-rotate-x", "push-rotate-y", "push-rotate-z", "push-rotate", "push-skew-x", "push-skew-y", "push-scale-x", "push-scale-y", "push-scale-z", "push-translate-x", "push-translate-y", "push-translate-z" properties.
2024-11-25 13:03:08 +03:00
if transform := getTransformProperty ( properties , transformTag ) ; transform != nil {
2024-11-18 17:20:25 +03:00
if result = transformSet ( transform , tag , value ) ; result != nil {
* Added "push-perspective", "push-rotate-x", "push-rotate-y", "push-rotate-z", "push-rotate", "push-skew-x", "push-skew-y", "push-scale-x", "push-scale-y", "push-scale-z", "push-translate-x", "push-translate-y", "push-translate-z" properties.
2024-11-25 13:03:08 +03:00
result = [ ] PropertyName { srcTag , transformTag }
2024-11-13 12:56:39 +03:00
}
} else {
2024-11-18 17:35:21 +03:00
transform := NewTransformProperty ( nil )
2024-11-18 17:20:25 +03:00
if result = transformSet ( transform , tag , value ) ; result != nil {
* Added "push-perspective", "push-rotate-x", "push-rotate-y", "push-rotate-z", "push-rotate", "push-skew-x", "push-skew-y", "push-scale-x", "push-scale-y", "push-scale-z", "push-translate-x", "push-translate-y", "push-translate-z" properties.
2024-11-25 13:03:08 +03:00
properties . setRaw ( transformTag , transform )
result = [ ] PropertyName { srcTag , transformTag }
2024-08-13 13:52:47 +03:00
}
}
2024-11-18 17:20:25 +03:00
return result
2024-08-13 13:52:47 +03:00
}
* Added "push-perspective", "push-rotate-x", "push-rotate-y", "push-rotate-z", "push-rotate", "push-skew-x", "push-skew-y", "push-scale-x", "push-scale-y", "push-scale-z", "push-translate-x", "push-translate-y", "push-translate-z" properties.
2024-11-25 13:03:08 +03:00
ErrorLogF ( ` "TransformProperty" interface does not support the "%s" property ` , tag )
2024-11-13 12:56:39 +03:00
return nil
2024-08-13 13:52:47 +03:00
}
2021-09-07 17:36:50 +03:00
func getPerspectiveOrigin ( style Properties , session Session ) ( SizeUnit , SizeUnit ) {
x , _ := sizeProperty ( style , PerspectiveOriginX , session )
y , _ := sizeProperty ( style , PerspectiveOriginY , session )
return x , y
}
2024-11-18 17:20:25 +03:00
func getTransformOrigin ( style Properties , session Session ) ( SizeUnit , SizeUnit , SizeUnit ) {
x , _ := sizeProperty ( style , TransformOriginX , session )
y , _ := sizeProperty ( style , TransformOriginY , session )
z , _ := sizeProperty ( style , TransformOriginZ , session )
2021-09-07 17:36:50 +03:00
return x , y , z
}
2024-11-18 17:35:21 +03:00
func ( transform * transformPropertyData ) getSkew ( session Session ) ( AngleUnit , AngleUnit , bool ) {
2024-08-13 13:52:47 +03:00
skewX , okX := angleProperty ( transform , SkewX , session )
skewY , okY := angleProperty ( transform , SkewY , session )
2021-10-04 17:58:17 +03:00
return skewX , skewY , okX || okY
2021-09-07 17:36:50 +03:00
}
2024-11-18 17:35:21 +03:00
func ( transform * transformPropertyData ) getTranslate ( session Session ) ( SizeUnit , SizeUnit , SizeUnit ) {
2024-08-13 13:52:47 +03:00
x , _ := sizeProperty ( transform , TranslateX , session )
y , _ := sizeProperty ( transform , TranslateY , session )
z , _ := sizeProperty ( transform , TranslateZ , session )
2021-09-07 17:36:50 +03:00
return x , y , z
}
2024-11-18 17:35:21 +03:00
func ( transform * transformPropertyData ) transformCSS ( session Session ) string {
2021-09-07 17:36:50 +03:00
buffer := allocStringBuilder ( )
defer freeStringBuilder ( buffer )
2024-11-13 12:56:39 +03:00
if perspective , ok := sizeProperty ( transform , Perspective , session ) ; ok && perspective . Type != Auto && perspective . Value != 0 {
buffer . WriteString ( ` perspective( ` )
buffer . WriteString ( perspective . cssString ( "0" , session ) )
buffer . WriteString ( ") " )
}
2024-08-13 13:52:47 +03:00
skewX , skewY , skewOK := transform . getSkew ( session )
2021-10-04 17:58:17 +03:00
if skewOK {
2021-09-07 17:36:50 +03:00
buffer . WriteString ( ` skew( ` )
buffer . WriteString ( skewX . cssString ( ) )
buffer . WriteRune ( ',' )
buffer . WriteString ( skewY . cssString ( ) )
2024-11-13 12:56:39 +03:00
buffer . WriteString ( ") " )
2021-09-07 17:36:50 +03:00
}
2024-08-13 13:52:47 +03:00
x , y , z := transform . getTranslate ( session )
2024-11-13 12:56:39 +03:00
if z . Type != Auto && z . Value != 0 {
buffer . WriteString ( ` translate3d( ` )
buffer . WriteString ( x . cssString ( "0" , session ) )
buffer . WriteRune ( ',' )
buffer . WriteString ( y . cssString ( "0" , session ) )
buffer . WriteRune ( ',' )
buffer . WriteString ( z . cssString ( "0" , session ) )
buffer . WriteString ( ") " )
} else if ( x . Type != Auto && x . Value != 0 ) || ( y . Type != Auto && y . Value != 0 ) {
buffer . WriteString ( ` translate( ` )
buffer . WriteString ( x . cssString ( "0" , session ) )
buffer . WriteRune ( ',' )
buffer . WriteString ( y . cssString ( "0" , session ) )
buffer . WriteString ( ") " )
}
2022-08-18 18:18:36 +03:00
2024-08-13 13:52:47 +03:00
scaleX , okScaleX := floatTextProperty ( transform , ScaleX , session , 1 )
scaleY , okScaleY := floatTextProperty ( transform , ScaleY , session , 1 )
2024-11-13 12:56:39 +03:00
scaleZ , okScaleZ := floatTextProperty ( transform , ScaleZ , session , 1 )
if okScaleZ {
2022-08-18 18:18:36 +03:00
2024-11-13 12:56:39 +03:00
buffer . WriteString ( ` scale3d( ` )
buffer . WriteString ( scaleX )
buffer . WriteRune ( ',' )
buffer . WriteString ( scaleY )
buffer . WriteRune ( ',' )
buffer . WriteString ( scaleZ )
buffer . WriteString ( ") " )
2021-09-07 17:36:50 +03:00
2024-11-13 12:56:39 +03:00
} else if okScaleX || okScaleY {
2021-09-07 17:36:50 +03:00
2024-11-13 12:56:39 +03:00
buffer . WriteString ( ` scale( ` )
buffer . WriteString ( scaleX )
buffer . WriteRune ( ',' )
buffer . WriteString ( scaleY )
buffer . WriteString ( ") " )
}
if angle , ok := angleProperty ( transform , Rotate , session ) ; ok {
rotateX , xOK := floatTextProperty ( transform , RotateX , session , 1 )
rotateY , yOK := floatTextProperty ( transform , RotateY , session , 1 )
rotateZ , zOK := floatTextProperty ( transform , RotateZ , session , 1 )
if xOK || yOK || zOK {
2022-08-18 18:18:36 +03:00
2021-09-07 17:36:50 +03:00
buffer . WriteString ( ` rotate3d( ` )
2022-08-18 18:18:36 +03:00
buffer . WriteString ( rotateX )
2021-09-07 17:36:50 +03:00
buffer . WriteRune ( ',' )
2022-08-18 18:18:36 +03:00
buffer . WriteString ( rotateY )
2021-09-07 17:36:50 +03:00
buffer . WriteRune ( ',' )
2022-08-18 18:18:36 +03:00
buffer . WriteString ( rotateZ )
2021-09-07 17:36:50 +03:00
buffer . WriteRune ( ',' )
buffer . WriteString ( angle . cssString ( ) )
2024-11-13 12:56:39 +03:00
buffer . WriteString ( ") " )
2021-09-07 17:36:50 +03:00
2024-11-13 12:56:39 +03:00
} else {
2021-09-07 17:36:50 +03:00
buffer . WriteString ( ` rotate( ` )
buffer . WriteString ( angle . cssString ( ) )
2024-11-13 12:56:39 +03:00
buffer . WriteString ( ") " )
2021-09-07 17:36:50 +03:00
}
}
2024-11-13 12:56:39 +03:00
length := buffer . Len ( )
if length == 0 {
return ""
}
result := buffer . String ( )
return result [ : length - 1 ]
2021-09-07 17:36:50 +03:00
}
func ( style * viewStyle ) writeViewTransformCSS ( builder cssBuilder , session Session ) {
2024-11-13 12:56:39 +03:00
x , y := getPerspectiveOrigin ( style , session )
2024-11-18 17:20:25 +03:00
z := AutoSize ( )
if css := transformOriginCSS ( x , y , z , session ) ; css != "" {
builder . add ( ` perspective-origin ` , css )
2024-11-13 12:56:39 +03:00
}
2021-09-07 17:36:50 +03:00
2024-11-13 12:56:39 +03:00
if backfaceVisible , ok := boolProperty ( style , BackfaceVisible , session ) ; ok {
if backfaceVisible {
builder . add ( ` backface-visibility ` , ` visible ` )
} else {
builder . add ( ` backface-visibility ` , ` hidden ` )
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
}
2021-09-07 17:36:50 +03:00
2024-11-18 17:20:25 +03:00
x , y , z = getTransformOrigin ( style , session )
if css := transformOriginCSS ( x , y , z , session ) ; css != "" {
builder . add ( ` transform-origin ` , css )
2021-09-07 17:36:50 +03:00
}
2024-11-24 09:52:43 +03:00
if transform := getTransformProperty ( style , Transform ) ; transform != nil {
2024-11-25 23:13:29 +03:00
builder . add ( ` transform ` , transform . transformCSS ( session ) )
2024-08-13 13:52:47 +03:00
}
2021-09-07 17:36:50 +03:00
}
2024-11-18 17:20:25 +03:00
func transformOriginCSS ( x , y , z SizeUnit , session Session ) string {
if z . Type == Auto && x . Type == Auto && y . Type == Auto {
return ""
}
buffer := allocStringBuilder ( )
defer freeStringBuilder ( buffer )
if x . Type == SizeInPercent {
switch x . Value {
case 0 :
buffer . WriteString ( "left" )
case 50 :
buffer . WriteString ( "center" )
case 100 :
buffer . WriteString ( "right" )
default :
buffer . WriteString ( x . cssString ( "center" , session ) )
}
} else {
buffer . WriteString ( x . cssString ( "center" , session ) )
}
buffer . WriteRune ( ' ' )
if y . Type == SizeInPercent {
switch y . Value {
case 0 :
buffer . WriteString ( "top" )
case 50 :
buffer . WriteString ( "center" )
case 100 :
buffer . WriteString ( "bottom" )
default :
buffer . WriteString ( y . cssString ( "center" , session ) )
}
} else {
buffer . WriteString ( y . cssString ( "center" , session ) )
}
if z . Type != Auto && z . Value != 0 {
buffer . WriteRune ( ' ' )
buffer . WriteString ( z . cssString ( "0" , session ) )
}
return buffer . String ( )
}
2024-12-02 15:47:06 +03:00
// GetTransform returns a view transform: translation, scale and rotation over x, y and z axes as well as a distortion of a view along x and y axes.
// The default value is nil (no transform)
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetTransform ( view View , subviewID ... string ) TransformProperty {
return transformStyledProperty ( view , subviewID , Transform )
}
2021-09-07 17:36:50 +03:00
2024-12-02 15:47:06 +03:00
// GetPerspective returns a distance between the z = 0 plane and the user in order to give a 3D-positioned
// element some perspective. Each 3D element with z > 0 becomes larger; each 3D-element with z < 0 becomes smaller.
// The default value is 0 (no 3D effects).
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetPerspective ( view View , subviewID ... string ) SizeUnit {
return sizeStyledProperty ( view , subviewID , Perspective , false )
}
2021-09-07 17:36:50 +03:00
2024-12-02 15:47:06 +03:00
// GetPerspectiveOrigin returns a x- and y-coordinate of the position at which the viewer is looking.
// It is used as the vanishing point by the Perspective property. The default value is (50%, 50%).
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetPerspectiveOrigin ( view View , subviewID ... string ) ( SizeUnit , SizeUnit ) {
view = getSubview ( view , subviewID )
if view == nil {
return AutoSize ( ) , AutoSize ( )
}
return getPerspectiveOrigin ( view , view . Session ( ) )
}
2021-09-07 17:36:50 +03:00
2024-12-02 15:47:06 +03:00
// GetBackfaceVisible returns a bool property that sets whether the back face of an element is
// visible when turned towards the user. Values:
// true - the back face is visible when turned towards the user (default value).
// false - the back face is hidden, effectively making the element invisible when turned away from the user.
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetBackfaceVisible ( view View , subviewID ... string ) bool {
return boolStyledProperty ( view , subviewID , BackfaceVisible , false )
}
2024-11-13 12:56:39 +03:00
2024-12-02 15:47:06 +03:00
// GetTransformOrigin returns a x-, y-, and z-coordinate of the point around which a view transformation is applied.
// The default value is (50%, 50%, 50%).
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetTransformOrigin ( view View , subviewID ... string ) ( SizeUnit , SizeUnit , SizeUnit ) {
view = getSubview ( view , subviewID )
if view == nil {
return AutoSize ( ) , AutoSize ( ) , AutoSize ( )
}
return getTransformOrigin ( view , view . Session ( ) )
}
2021-09-07 17:36:50 +03:00
2024-12-02 15:47:06 +03:00
// GetTranslate returns a x-, y-, and z-axis translation value of a 2D/3D translation
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetTranslate ( view View , subviewID ... string ) ( SizeUnit , SizeUnit , SizeUnit ) {
if transform := GetTransform ( view , subviewID ... ) ; transform != nil {
return transform . getTranslate ( view . Session ( ) )
}
return AutoSize ( ) , AutoSize ( ) , AutoSize ( )
}
// GetSkew returns a angles to use to distort the element along the abscissa (x-axis)
// and the ordinate (y-axis). The default value is 0.
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetSkew ( view View , subviewID ... string ) ( AngleUnit , AngleUnit ) {
if transform := GetTransform ( view , subviewID ... ) ; transform != nil {
x , y , _ := transform . getSkew ( view . Session ( ) )
return x , y
}
return AngleUnit { Value : 0 , Type : Radian } , AngleUnit { Value : 0 , Type : Radian }
}
2021-09-07 17:36:50 +03:00
2024-12-02 15:47:06 +03:00
// GetScale returns a x-, y-, and z-axis scaling value of a 2D/3D scale. The default value is 1.
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetScale ( view View , subviewID ... string ) ( float64 , float64 , float64 ) {
if transform := GetTransform ( view , subviewID ... ) ; transform != nil {
session := view . Session ( )
x , _ := floatProperty ( transform , ScaleX , session , 1 )
y , _ := floatProperty ( transform , ScaleY , session , 1 )
z , _ := floatProperty ( transform , ScaleZ , session , 1 )
return x , y , z
2021-09-07 17:36:50 +03:00
}
2024-12-02 15:47:06 +03:00
return 1 , 1 , 1
}
2021-09-07 17:36:50 +03:00
2024-12-02 15:47:06 +03:00
// GetRotate returns a x-, y, z-coordinate of the vector denoting the axis of rotation, and the angle of the view rotation
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetRotate ( view View , subviewID ... string ) ( float64 , float64 , float64 , AngleUnit ) {
if transform := GetTransform ( view , subviewID ... ) ; transform != nil {
session := view . Session ( )
angle , _ := angleProperty ( transform , Rotate , view . Session ( ) )
rotateX , _ := floatProperty ( transform , RotateX , session , 1 )
rotateY , _ := floatProperty ( transform , RotateY , session , 1 )
rotateZ , _ := floatProperty ( transform , RotateZ , session , 1 )
return rotateX , rotateY , rotateZ , angle
}
return 0 , 0 , 0 , AngleUnit { Value : 0 , Type : Radian }
2021-09-07 17:36:50 +03:00
}