rui_orig/clipShape.go

691 lines
17 KiB
Go
Raw Normal View History

2021-09-07 17:36:50 +03:00
package rui
import (
"fmt"
"strings"
)
2024-12-06 18:38:43 +03:00
type ClipShape string
const (
InsetClip ClipShape = "inset"
CircleClip ClipShape = "circle"
EllipseClip ClipShape = "ellipse"
PolygonClip ClipShape = "polygon"
)
// ClipShapeProperty defines a View clipping area
type ClipShapeProperty interface {
2021-09-07 17:36:50 +03:00
Properties
fmt.Stringer
2022-05-22 12:54:02 +03:00
stringWriter
2024-12-06 18:38:43 +03:00
// Shape returns the clip shape type
Shape() ClipShape
2021-09-07 17:36:50 +03:00
cssStyle(session Session) string
valid(session Session) bool
}
2024-12-06 18:38:43 +03:00
type insetClipData struct {
2024-11-13 12:56:39 +03:00
dataProperty
2021-09-07 17:36:50 +03:00
}
2024-12-06 18:38:43 +03:00
type ellipseClipData struct {
2024-11-13 12:56:39 +03:00
dataProperty
2021-09-07 17:36:50 +03:00
}
2024-12-06 18:38:43 +03:00
type circleClipData struct {
2024-11-13 12:56:39 +03:00
dataProperty
2022-05-22 12:54:02 +03:00
}
2024-12-06 18:38:43 +03:00
type polygonClipData struct {
2024-11-13 12:56:39 +03:00
dataProperty
2021-09-07 17:36:50 +03:00
}
2024-12-06 18:38:43 +03:00
// NewClipShapeProperty creates ClipShapeProperty.
//
// The following properties can be used for shapes:
//
// InsetClip:
// - "top" (Top) - offset (SizeUnit) from the top border of a View;
// - "right" (Right) - offset (SizeUnit) from the right border of a View;
// - "bottom" (Bottom) - offset (SizeUnit) from the bottom border of a View;
// - "left" (Left) - offset (SizeUnit) from the left border of a View;
// - "radius" (Radius) - corner radius (RadiusProperty).
//
// CircleClip:
// - "x" (X) - x-axis position (SizeUnit) of the circle clip center;
// - "y" (Y) - y-axis position (SizeUnit) of the circle clip center;
// - "radius" (Radius) - radius (SizeUnit) of the circle clip center.
//
// EllipseClip:
// - "x" (X) - x-axis position (SizeUnit) of the ellipse clip center;
// - "y" (Y) - y-axis position (SizeUnit) of the ellipse clip center;
// - "radius-x" (RadiusX) - x-axis radius (SizeUnit) of the ellipse clip center;
// - "radius-y" (RadiusY) - y-axis radius (SizeUnit) of the ellipse clip center.
//
// PolygonClip:
// - "points" (Points) - an array ([]SizeUnit) of corner points of the polygon in the following order: x1, y1, x2, y2, ….
//
// The function will return nil if no properties are specified, unsupported properties are specified, or at least one property has an invalid value.
func NewClipShapeProperty(shape ClipShape, params Params) ClipShapeProperty {
if len(params) == 0 {
ErrorLog("No ClipShapeProperty params")
return nil
}
var result ClipShapeProperty
switch shape {
case InsetClip:
clip := new(insetClipData)
clip.init()
result = clip
case CircleClip:
clip := new(circleClipData)
clip.init()
result = clip
case EllipseClip:
clip := new(ellipseClipData)
clip.init()
result = clip
case PolygonClip:
clip := new(polygonClipData)
clip.init()
result = clip
default:
ErrorLog("Unknown ClipShape: " + string(shape))
return nil
}
for tag, value := range params {
if !result.Set(tag, value) {
return nil
}
}
return result
}
// NewInsetClip creates a rectangle View clipping area.
2024-12-05 20:15:39 +03:00
// - top - offset from the top border of a View;
// - right - offset from the right border of a View;
// - bottom - offset from the bottom border of a View;
// - left - offset from the left border of a View;
// - radius - corner radius, pass nil if you don't need to round corners
2024-12-06 18:38:43 +03:00
func NewInsetClip(top, right, bottom, left SizeUnit, radius RadiusProperty) ClipShapeProperty {
clip := new(insetClipData)
2021-09-07 17:36:50 +03:00
clip.init()
2024-11-13 12:56:39 +03:00
clip.setRaw(Top, top)
clip.setRaw(Right, right)
clip.setRaw(Bottom, bottom)
clip.setRaw(Left, left)
2021-09-07 17:36:50 +03:00
if radius != nil {
2024-11-13 12:56:39 +03:00
clip.setRaw(Radius, radius)
2021-09-07 17:36:50 +03:00
}
return clip
}
2024-12-06 18:38:43 +03:00
// NewCircleClip creates a circle View clipping area.
// - x - x-axis position of the circle clip center;
// - y - y-axis position of the circle clip center;
// - radius - radius of the circle clip center.
func NewCircleClip(x, y, radius SizeUnit) ClipShapeProperty {
clip := new(circleClipData)
2021-09-07 17:36:50 +03:00
clip.init()
2024-11-13 12:56:39 +03:00
clip.setRaw(X, x)
clip.setRaw(Y, y)
clip.setRaw(Radius, radius)
2021-09-07 17:36:50 +03:00
return clip
}
2024-12-06 18:38:43 +03:00
// NewEllipseClip creates a ellipse View clipping area.
// - x - x-axis position of the ellipse clip center;
// - y - y-axis position of the ellipse clip center;
// - rx - x-axis radius of the ellipse clip center;
// - ry - y-axis radius of the ellipse clip center.
func NewEllipseClip(x, y, rx, ry SizeUnit) ClipShapeProperty {
clip := new(ellipseClipData)
2021-09-07 17:36:50 +03:00
clip.init()
2024-11-13 12:56:39 +03:00
clip.setRaw(X, x)
clip.setRaw(Y, y)
clip.setRaw(RadiusX, rx)
clip.setRaw(RadiusY, ry)
2021-09-07 17:36:50 +03:00
return clip
}
2024-12-06 18:38:43 +03:00
// NewPolygonClip creates a polygon View clipping area.
// - points - an array of corner points of the polygon in the following order: x1, y1, x2, y2, …
2024-12-05 20:15:39 +03:00
//
2021-09-07 17:36:50 +03:00
// The elements of the function argument can be or text constants,
// or the text representation of SizeUnit, or elements of SizeUnit type.
2024-12-06 18:38:43 +03:00
func NewPolygonClip(points []any) ClipShapeProperty {
clip := new(polygonClipData)
2024-11-13 12:56:39 +03:00
clip.init()
2024-12-06 18:38:43 +03:00
if polygonClipDataSet(clip, Points, points) != nil {
2021-09-07 17:36:50 +03:00
return clip
}
return nil
}
2024-12-06 18:38:43 +03:00
// NewPolygonPointsClip creates a polygon View clipping area.
// - points - an array of corner points of the polygon in the following order: x1, y1, x2, y2, …
func NewPolygonPointsClip(points []SizeUnit) ClipShapeProperty {
clip := new(polygonClipData)
2024-11-13 12:56:39 +03:00
clip.init()
2024-12-06 18:38:43 +03:00
if polygonClipDataSet(clip, Points, points) != nil {
2021-09-07 17:36:50 +03:00
return clip
}
return nil
}
2024-12-06 18:38:43 +03:00
func (clip *insetClipData) init() {
2024-11-13 12:56:39 +03:00
clip.dataProperty.init()
2024-12-06 18:38:43 +03:00
clip.set = insetClipDataSet
2024-11-13 12:56:39 +03:00
clip.supportedProperties = []PropertyName{
Top, Right, Bottom, Left, Radius,
RadiusX, RadiusY, RadiusTopLeft, RadiusTopLeftX, RadiusTopLeftY,
RadiusTopRight, RadiusTopRightX, RadiusTopRightY,
RadiusBottomLeft, RadiusBottomLeftX, RadiusBottomLeftY,
RadiusBottomRight, RadiusBottomRightX, RadiusBottomRightY,
}
}
2024-12-06 18:38:43 +03:00
func (clip *insetClipData) Shape() ClipShape {
return InsetClip
}
func insetClipDataSet(properties Properties, tag PropertyName, value any) []PropertyName {
2024-11-13 12:56:39 +03:00
switch tag {
2021-09-07 17:36:50 +03:00
case Top, Right, Bottom, Left:
2024-11-13 12:56:39 +03:00
return setSizeProperty(properties, tag, value)
2021-09-07 17:36:50 +03:00
case Radius:
2024-11-13 12:56:39 +03:00
return setRadiusProperty(properties, value)
2021-09-07 17:36:50 +03:00
case RadiusX, RadiusY, RadiusTopLeft, RadiusTopLeftX, RadiusTopLeftY,
RadiusTopRight, RadiusTopRightX, RadiusTopRightY,
RadiusBottomLeft, RadiusBottomLeftX, RadiusBottomLeftY,
RadiusBottomRight, RadiusBottomRightX, RadiusBottomRightY:
2024-11-13 12:56:39 +03:00
if setRadiusPropertyElement(properties, tag, value) {
return []PropertyName{tag, Radius}
}
return nil
2021-09-07 17:36:50 +03:00
}
ErrorLogF(`"%s" property is not supported by the inset clip shape`, tag)
2024-11-13 12:56:39 +03:00
return nil
2021-09-07 17:36:50 +03:00
}
2024-12-06 18:38:43 +03:00
func (clip *insetClipData) String() string {
2022-05-22 12:54:02 +03:00
return runStringWriter(clip)
2021-09-07 17:36:50 +03:00
}
2024-12-06 18:38:43 +03:00
func (clip *insetClipData) writeString(buffer *strings.Builder, indent string) {
2022-05-22 12:54:02 +03:00
buffer.WriteString("inset { ")
comma := false
2024-11-13 12:56:39 +03:00
for _, tag := range []PropertyName{Top, Right, Bottom, Left, Radius} {
2021-09-07 17:36:50 +03:00
if value, ok := clip.properties[tag]; ok {
2022-05-22 12:54:02 +03:00
if comma {
buffer.WriteString(", ")
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
buffer.WriteString(string(tag))
2022-05-22 12:54:02 +03:00
buffer.WriteString(" = ")
writePropertyValue(buffer, tag, value, indent)
comma = true
2021-09-07 17:36:50 +03:00
}
}
2022-05-22 12:54:02 +03:00
buffer.WriteString(" }")
2021-09-07 17:36:50 +03:00
}
2024-12-06 18:38:43 +03:00
func (clip *insetClipData) cssStyle(session Session) string {
2021-09-07 17:36:50 +03:00
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
leadText := "inset("
2024-11-13 12:56:39 +03:00
for _, tag := range []PropertyName{Top, Right, Bottom, Left} {
2021-09-07 17:36:50 +03:00
value, _ := sizeProperty(clip, tag, session)
buffer.WriteString(leadText)
buffer.WriteString(value.cssString("0px", session))
2021-09-07 17:36:50 +03:00
leadText = " "
}
if radius := getRadiusProperty(clip); radius != nil {
buffer.WriteString(" round ")
buffer.WriteString(radius.BoxRadius(session).cssString(session))
2021-09-07 17:36:50 +03:00
}
buffer.WriteRune(')')
return buffer.String()
}
2024-12-06 18:38:43 +03:00
func (clip *insetClipData) valid(session Session) bool {
2024-11-13 12:56:39 +03:00
for _, tag := range []PropertyName{Top, Right, Bottom, Left, Radius, RadiusX, RadiusY} {
2021-09-07 17:36:50 +03:00
if value, ok := sizeProperty(clip, tag, session); ok && value.Type != Auto && value.Value != 0 {
return true
}
}
return false
}
2024-12-06 18:38:43 +03:00
func (clip *circleClipData) init() {
2024-11-13 12:56:39 +03:00
clip.dataProperty.init()
2024-12-06 18:38:43 +03:00
clip.set = circleClipDataSet
2024-11-13 12:56:39 +03:00
clip.supportedProperties = []PropertyName{X, Y, Radius}
}
2021-09-07 17:36:50 +03:00
2024-12-06 18:38:43 +03:00
func (clip *circleClipData) Shape() ClipShape {
return CircleClip
}
func circleClipDataSet(properties Properties, tag PropertyName, value any) []PropertyName {
2024-11-13 12:56:39 +03:00
switch tag {
2022-05-22 12:54:02 +03:00
case X, Y, Radius:
2024-11-13 12:56:39 +03:00
return setSizeProperty(properties, tag, value)
2022-05-22 12:54:02 +03:00
}
2021-09-07 17:36:50 +03:00
2022-05-22 12:54:02 +03:00
ErrorLogF(`"%s" property is not supported by the circle clip shape`, tag)
2024-11-13 12:56:39 +03:00
return nil
2022-05-22 12:54:02 +03:00
}
2024-12-06 18:38:43 +03:00
func (clip *circleClipData) String() string {
2022-05-22 12:54:02 +03:00
return runStringWriter(clip)
}
2024-12-06 18:38:43 +03:00
func (clip *circleClipData) writeString(buffer *strings.Builder, indent string) {
2022-05-22 12:54:02 +03:00
buffer.WriteString("circle { ")
comma := false
2024-11-13 12:56:39 +03:00
for _, tag := range []PropertyName{Radius, X, Y} {
2022-05-22 12:54:02 +03:00
if value, ok := clip.properties[tag]; ok {
if comma {
buffer.WriteString(", ")
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
buffer.WriteString(string(tag))
2022-05-22 12:54:02 +03:00
buffer.WriteString(" = ")
writePropertyValue(buffer, tag, value, indent)
comma = true
2021-09-07 17:36:50 +03:00
}
}
2022-05-22 12:54:02 +03:00
buffer.WriteString(" }")
2021-09-07 17:36:50 +03:00
}
2024-12-06 18:38:43 +03:00
func (clip *circleClipData) cssStyle(session Session) string {
2022-05-22 12:54:02 +03:00
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
buffer.WriteString("circle(")
r, _ := sizeProperty(clip, Radius, session)
buffer.WriteString(r.cssString("50%", session))
2022-05-22 12:54:02 +03:00
buffer.WriteString(" at ")
x, _ := sizeProperty(clip, X, session)
buffer.WriteString(x.cssString("50%", session))
2022-05-22 12:54:02 +03:00
buffer.WriteRune(' ')
y, _ := sizeProperty(clip, Y, session)
buffer.WriteString(y.cssString("50%", session))
2022-05-22 12:54:02 +03:00
buffer.WriteRune(')')
return buffer.String()
2021-09-07 17:36:50 +03:00
}
2024-12-06 18:38:43 +03:00
func (clip *circleClipData) valid(session Session) bool {
2022-05-22 12:54:02 +03:00
if value, ok := sizeProperty(clip, Radius, session); ok && value.Value == 0 {
return false
}
return true
}
2021-09-07 17:36:50 +03:00
2024-12-06 18:38:43 +03:00
func (clip *ellipseClipData) init() {
2024-11-13 12:56:39 +03:00
clip.dataProperty.init()
2024-12-06 18:38:43 +03:00
clip.set = ellipseClipDataSet
2024-11-13 12:56:39 +03:00
clip.supportedProperties = []PropertyName{X, Y, Radius, RadiusX, RadiusY}
}
2021-09-07 17:36:50 +03:00
2024-12-06 18:38:43 +03:00
func (clip *ellipseClipData) Shape() ClipShape {
return EllipseClip
}
func ellipseClipDataSet(properties Properties, tag PropertyName, value any) []PropertyName {
2024-11-13 12:56:39 +03:00
switch tag {
2022-05-22 12:54:02 +03:00
case X, Y, RadiusX, RadiusY:
2024-11-13 12:56:39 +03:00
return setSizeProperty(properties, tag, value)
2022-05-22 12:54:02 +03:00
case Radius:
2024-11-13 12:56:39 +03:00
if result := setSizeProperty(properties, RadiusX, value); result != nil {
properties.setRaw(RadiusY, properties.getRaw(RadiusX))
return append(result, RadiusY)
}
return nil
2021-09-07 17:36:50 +03:00
}
2022-05-22 12:54:02 +03:00
ErrorLogF(`"%s" property is not supported by the ellipse clip shape`, tag)
2024-11-13 12:56:39 +03:00
return nil
2022-05-22 12:54:02 +03:00
}
2024-12-06 18:38:43 +03:00
func (clip *ellipseClipData) String() string {
2022-05-22 12:54:02 +03:00
return runStringWriter(clip)
}
2024-12-06 18:38:43 +03:00
func (clip *ellipseClipData) writeString(buffer *strings.Builder, indent string) {
2022-05-22 12:54:02 +03:00
buffer.WriteString("ellipse { ")
comma := false
2024-11-13 12:56:39 +03:00
for _, tag := range []PropertyName{RadiusX, RadiusY, X, Y} {
2021-09-07 17:36:50 +03:00
if value, ok := clip.properties[tag]; ok {
2022-05-22 12:54:02 +03:00
if comma {
buffer.WriteString(", ")
}
2024-11-13 12:56:39 +03:00
buffer.WriteString(string(tag))
2022-05-22 12:54:02 +03:00
buffer.WriteString(" = ")
writePropertyValue(buffer, tag, value, indent)
comma = true
2021-09-07 17:36:50 +03:00
}
}
2022-05-22 12:54:02 +03:00
buffer.WriteString(" }")
2021-09-07 17:36:50 +03:00
}
2024-12-06 18:38:43 +03:00
func (clip *ellipseClipData) cssStyle(session Session) string {
2021-09-07 17:36:50 +03:00
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
2022-05-22 12:54:02 +03:00
rx, _ := sizeProperty(clip, RadiusX, session)
ry, _ := sizeProperty(clip, RadiusX, session)
buffer.WriteString("ellipse(")
buffer.WriteString(rx.cssString("50%", session))
2022-05-22 12:54:02 +03:00
buffer.WriteRune(' ')
buffer.WriteString(ry.cssString("50%", session))
2021-09-07 17:36:50 +03:00
buffer.WriteString(" at ")
x, _ := sizeProperty(clip, X, session)
buffer.WriteString(x.cssString("50%", session))
2021-09-07 17:36:50 +03:00
buffer.WriteRune(' ')
y, _ := sizeProperty(clip, Y, session)
buffer.WriteString(y.cssString("50%", session))
2021-09-07 17:36:50 +03:00
buffer.WriteRune(')')
return buffer.String()
}
2024-12-06 18:38:43 +03:00
func (clip *ellipseClipData) valid(session Session) bool {
2022-05-22 12:54:02 +03:00
rx, _ := sizeProperty(clip, RadiusX, session)
ry, _ := sizeProperty(clip, RadiusY, session)
return rx.Value != 0 && ry.Value != 0
2021-09-07 17:36:50 +03:00
}
2024-12-06 18:38:43 +03:00
func (clip *polygonClipData) init() {
2024-11-13 12:56:39 +03:00
clip.dataProperty.init()
2024-12-06 18:38:43 +03:00
clip.set = polygonClipDataSet
2024-11-13 12:56:39 +03:00
clip.supportedProperties = []PropertyName{Points}
2021-09-07 17:36:50 +03:00
}
2024-12-06 18:38:43 +03:00
func (clip *polygonClipData) Shape() ClipShape {
return PolygonClip
}
func polygonClipDataSet(properties Properties, tag PropertyName, value any) []PropertyName {
2024-11-13 12:56:39 +03:00
if Points == tag {
2021-09-07 17:36:50 +03:00
switch value := value.(type) {
2022-07-26 18:36:00 +03:00
case []any:
2024-11-13 12:56:39 +03:00
points := make([]any, len(value))
2021-09-07 17:36:50 +03:00
for i, val := range value {
switch val := val.(type) {
case string:
if isConstantName(val) {
2024-11-13 12:56:39 +03:00
points[i] = val
2021-09-07 17:36:50 +03:00
} else if size, ok := StringToSizeUnit(val); ok {
2024-11-13 12:56:39 +03:00
points[i] = size
2021-09-07 17:36:50 +03:00
} else {
notCompatibleType(tag, val)
2024-11-13 12:56:39 +03:00
return nil
2021-09-07 17:36:50 +03:00
}
case SizeUnit:
2024-11-13 12:56:39 +03:00
points[i] = val
2021-09-07 17:36:50 +03:00
default:
notCompatibleType(tag, val)
2024-11-13 12:56:39 +03:00
points[i] = AutoSize()
return nil
2021-09-07 17:36:50 +03:00
}
}
2024-11-13 12:56:39 +03:00
properties.setRaw(Points, points)
return []PropertyName{tag}
2021-09-07 17:36:50 +03:00
case []SizeUnit:
2024-11-13 12:56:39 +03:00
points := make([]any, len(value))
2021-09-07 17:36:50 +03:00
for i, point := range value {
2024-11-13 12:56:39 +03:00
points[i] = point
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
properties.setRaw(Points, points)
return []PropertyName{tag}
2021-09-07 17:36:50 +03:00
case string:
values := strings.Split(value, ",")
2024-11-13 12:56:39 +03:00
points := make([]any, len(values))
2021-09-07 17:36:50 +03:00
for i, val := range values {
val = strings.Trim(val, " \t\n\r")
if isConstantName(val) {
2024-11-13 12:56:39 +03:00
points[i] = val
2021-09-07 17:36:50 +03:00
} else if size, ok := StringToSizeUnit(val); ok {
2024-11-13 12:56:39 +03:00
points[i] = size
2021-09-07 17:36:50 +03:00
} else {
notCompatibleType(tag, val)
2024-11-13 12:56:39 +03:00
return nil
2021-09-07 17:36:50 +03:00
}
}
2024-11-13 12:56:39 +03:00
properties.setRaw(Points, points)
return []PropertyName{tag}
2021-09-07 17:36:50 +03:00
}
}
2024-11-13 12:56:39 +03:00
return nil
2021-09-07 17:36:50 +03:00
}
2024-12-06 18:38:43 +03:00
func (clip *polygonClipData) String() string {
2024-11-13 12:56:39 +03:00
return runStringWriter(clip)
2021-09-07 17:36:50 +03:00
}
2024-12-06 18:38:43 +03:00
func (clip *polygonClipData) points() []any {
2024-11-13 12:56:39 +03:00
if value := clip.getRaw(Points); value != nil {
if points, ok := value.([]any); ok {
return points
}
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
return nil
2021-09-07 17:36:50 +03:00
}
2024-12-06 18:38:43 +03:00
func (clip *polygonClipData) writeString(buffer *strings.Builder, indent string) {
2021-09-07 17:36:50 +03:00
2022-05-22 12:54:02 +03:00
buffer.WriteString("inset { ")
2021-09-07 17:36:50 +03:00
2024-11-13 12:56:39 +03:00
if points := clip.points(); points != nil {
buffer.WriteString(string(Points))
2022-05-22 12:54:02 +03:00
buffer.WriteString(` = "`)
2024-11-13 12:56:39 +03:00
for i, value := range points {
2021-09-07 17:36:50 +03:00
if i > 0 {
buffer.WriteString(", ")
}
2022-05-22 12:54:02 +03:00
writePropertyValue(buffer, "", value, indent)
2021-09-07 17:36:50 +03:00
}
2022-05-22 12:54:02 +03:00
buffer.WriteString(`" `)
2021-09-07 17:36:50 +03:00
}
2022-05-22 12:54:02 +03:00
buffer.WriteRune('}')
2021-09-07 17:36:50 +03:00
}
2024-12-06 18:38:43 +03:00
func (clip *polygonClipData) cssStyle(session Session) string {
2021-09-07 17:36:50 +03:00
2024-11-13 12:56:39 +03:00
points := clip.points()
count := len(points)
2021-09-07 17:36:50 +03:00
if count < 2 {
return ""
}
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
2022-07-26 18:36:00 +03:00
writePoint := func(value any) {
2021-09-07 17:36:50 +03:00
switch value := value.(type) {
case string:
if val, ok := session.resolveConstants(value); ok {
if size, ok := StringToSizeUnit(val); ok {
buffer.WriteString(size.cssString("0px", session))
2021-09-07 17:36:50 +03:00
return
}
}
case SizeUnit:
buffer.WriteString(value.cssString("0px", session))
2021-09-07 17:36:50 +03:00
return
}
buffer.WriteString("0px")
}
leadText := "polygon("
for i := 1; i < count; i += 2 {
buffer.WriteString(leadText)
2024-11-13 12:56:39 +03:00
writePoint(points[i-1])
2021-09-07 17:36:50 +03:00
buffer.WriteRune(' ')
2024-11-13 12:56:39 +03:00
writePoint(points[i])
2021-09-07 17:36:50 +03:00
leadText = ", "
}
buffer.WriteRune(')')
return buffer.String()
}
2024-12-06 18:38:43 +03:00
func (clip *polygonClipData) valid(session Session) bool {
2024-11-13 12:56:39 +03:00
return len(clip.points()) > 0
2021-09-07 17:36:50 +03:00
}
2024-12-06 18:38:43 +03:00
func parseClipShapeProperty(obj DataObject) ClipShapeProperty {
2021-09-07 17:36:50 +03:00
switch obj.Tag() {
case "inset":
2024-12-06 18:38:43 +03:00
clip := new(insetClipData)
2024-11-13 12:56:39 +03:00
clip.init()
for _, tag := range []PropertyName{Top, Right, Bottom, Left, Radius, RadiusX, RadiusY} {
if value, ok := obj.PropertyValue(string(tag)); ok {
2024-12-06 18:38:43 +03:00
insetClipDataSet(clip, tag, value)
2021-09-07 17:36:50 +03:00
}
}
return clip
case "circle":
2024-12-06 18:38:43 +03:00
clip := new(circleClipData)
2024-11-13 12:56:39 +03:00
clip.init()
for _, tag := range []PropertyName{X, Y, Radius} {
if value, ok := obj.PropertyValue(string(tag)); ok {
2024-12-06 18:38:43 +03:00
circleClipDataSet(clip, tag, value)
2021-09-07 17:36:50 +03:00
}
}
return clip
case "ellipse":
2024-12-06 18:38:43 +03:00
clip := new(ellipseClipData)
2024-11-13 12:56:39 +03:00
clip.init()
for _, tag := range []PropertyName{X, Y, RadiusX, RadiusY} {
if value, ok := obj.PropertyValue(string(tag)); ok {
2024-12-06 18:38:43 +03:00
ellipseClipDataSet(clip, tag, value)
2021-09-07 17:36:50 +03:00
}
}
return clip
case "polygon":
2024-12-06 18:38:43 +03:00
clip := new(polygonClipData)
2024-11-13 12:56:39 +03:00
clip.init()
if value, ok := obj.PropertyValue(string(Points)); ok {
2024-12-06 18:38:43 +03:00
polygonClipDataSet(clip, Points, value)
2021-09-07 17:36:50 +03:00
}
return clip
}
return nil
}
2024-12-06 18:38:43 +03:00
func setClipShapePropertyProperty(properties Properties, tag PropertyName, value any) []PropertyName {
2021-09-07 17:36:50 +03:00
switch value := value.(type) {
2024-12-06 18:38:43 +03:00
case ClipShapeProperty:
2024-11-13 12:56:39 +03:00
properties.setRaw(tag, value)
return []PropertyName{tag}
2021-09-07 17:36:50 +03:00
case string:
if isConstantName(value) {
2024-11-13 12:56:39 +03:00
properties.setRaw(tag, value)
return []PropertyName{tag}
2021-09-07 17:36:50 +03:00
}
if obj := NewDataObject(value); obj == nil {
2024-12-06 18:38:43 +03:00
if clip := parseClipShapeProperty(obj); clip != nil {
2024-11-13 12:56:39 +03:00
properties.setRaw(tag, clip)
return []PropertyName{tag}
2021-09-07 17:36:50 +03:00
}
}
case DataObject:
2024-12-06 18:38:43 +03:00
if clip := parseClipShapeProperty(value); clip != nil {
2024-11-13 12:56:39 +03:00
properties.setRaw(tag, clip)
return []PropertyName{tag}
2021-09-07 17:36:50 +03:00
}
case DataValue:
if value.IsObject() {
2024-12-06 18:38:43 +03:00
if clip := parseClipShapeProperty(value.Object()); clip != nil {
2024-11-13 12:56:39 +03:00
properties.setRaw(tag, clip)
return []PropertyName{tag}
2021-09-07 17:36:50 +03:00
}
}
}
notCompatibleType(tag, value)
2024-11-13 12:56:39 +03:00
return nil
2021-09-07 17:36:50 +03:00
}
2024-12-06 18:38:43 +03:00
func getClipShapeProperty(prop Properties, tag PropertyName, session Session) ClipShapeProperty {
2021-09-07 17:36:50 +03:00
if value := prop.getRaw(tag); value != nil {
switch value := value.(type) {
2024-12-06 18:38:43 +03:00
case ClipShapeProperty:
2021-09-07 17:36:50 +03:00
return value
case string:
if text, ok := session.resolveConstants(value); ok {
if obj := NewDataObject(text); obj == nil {
2024-12-06 18:38:43 +03:00
return parseClipShapeProperty(obj)
2021-09-07 17:36:50 +03:00
}
}
}
}
return nil
}
// GetClip returns a View clipping area.
// If the second argument (subviewID) is not specified or it is "" then a top position of the first argument (view) is returned
2024-12-06 18:38:43 +03:00
func GetClip(view View, subviewID ...string) ClipShapeProperty {
2024-11-24 16:43:31 +03:00
if view = getSubview(view, subviewID); view != nil {
2024-12-06 18:38:43 +03:00
return getClipShapeProperty(view, Clip, view.Session())
2021-09-07 17:36:50 +03:00
}
return nil
}
// GetShapeOutside returns a shape around which adjacent inline content.
// If the second argument (subviewID) is not specified or it is "" then a top position of the first argument (view) is returned
2024-12-06 18:38:43 +03:00
func GetShapeOutside(view View, subviewID ...string) ClipShapeProperty {
2024-11-24 16:43:31 +03:00
if view = getSubview(view, subviewID); view != nil {
2024-12-06 18:38:43 +03:00
return getClipShapeProperty(view, ShapeOutside, view.Session())
2021-09-07 17:36:50 +03:00
}
return nil
}