• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16interface Frame {
17  x: number;
18  y: number;
19  width: number;
20  height: number;
21}
22
23interface Vector2 {
24  x: number
25  y: number
26}
27
28interface Vector3 {
29  x: number;
30  y: number;
31  z: number;
32}
33
34type Transform = [
35  number,
36  number,
37  number,
38  number,
39  number,
40  number,
41  number,
42  number,
43  number,
44  number,
45  number,
46  number,
47  number,
48  number,
49  number,
50  number
51];
52
53enum BorderStyle {
54  SOLID = 0,
55  DASHED,
56  DOTTED,
57  NONE
58}
59
60type EdgeStyles = {
61  top?: BorderStyle;
62  right?: BorderStyle;
63  bottom?: BorderStyle;
64  left?: BorderStyle;
65};
66
67interface EdgesT<T> {
68  left: T,
69  right: T,
70  top: T,
71  bottom: T,
72}
73interface SizeT<T> {
74  width: T;
75  height: T;
76}
77
78enum LengthUnit {
79  PX = 0,
80  VP = 1,
81  FP = 2,
82  PERCENT = 3,
83  LPX = 4,
84}
85
86enum LengthMetricsUnit {
87  DEFAULT = 0,
88  PX = 1,
89}
90
91type EdgeWidths = EdgesT<Number>;
92
93type EdgeColors = EdgesT<Number>;
94
95interface Corners {
96  topLeft: number,
97  topRight: number,
98  bottomLeft: number,
99  bottomRight: number
100}
101
102type BorderRadiuses = Corners;
103
104interface Rect {
105  left: number,
106  right: number,
107  top: number,
108  bottom: number
109}
110
111interface CornerRadius {
112  topLeft: Vector2,
113  topRight: Vector2,
114  bottomLeft: Vector2,
115  bottomRight: Vector2
116}
117
118interface RoundRect {
119  rect: Rect,
120  corners: CornerRadius
121}
122
123interface Circle {
124  centerX: number,
125  centerY: number,
126  radius: number
127}
128
129interface CommandPath {
130  commands: string
131}
132
133class LengthMetrics {
134  public unit: LengthUnit;
135  public value: number;
136  public res: Resource;
137  constructor(value: number, unit?: LengthUnit, res?: Resource) {
138      if (unit in LengthUnit) {
139          this.unit = unit;
140          this.value = value;
141      } else {
142          this.unit = LengthUnit.VP;
143          this.value = unit === undefined? value : 0;
144      }
145      this.res = res === undefined ? undefined : res;
146  }
147  static px(value: number) {
148      return new LengthMetrics(value, LengthUnit.PX);
149  }
150  static vp(value: number) {
151      return new LengthMetrics(value, LengthUnit.VP);
152  }
153  static fp(value: number) {
154      return new LengthMetrics(value, LengthUnit.FP);
155  }
156  static percent(value: number) {
157      return new LengthMetrics(value, LengthUnit.PERCENT);
158  }
159  static lpx(value: number) {
160      return new LengthMetrics(value, LengthUnit.LPX);
161  }
162  static resource(res: Resource) {
163    let length:Array<number> = getUINativeModule().nativeUtils.resoureToLengthMetrics(res);
164    return new LengthMetrics(length[0], length[1], res);
165  }
166}
167
168declare interface Resource {}
169declare type BusinessError = any
170
171declare enum Color {
172  White,
173  Black,
174  Blue,
175  Brown,
176  Gray,
177  Green,
178  Grey,
179  Orange,
180  Pink,
181  Red,
182  Yellow,
183  Transparent,
184}
185
186declare enum ColorSpace {
187  SRGB = 0,
188  DISPLAY_P3 = 1,
189}
190
191declare type ResourceColor = Color | number | string | Resource;
192
193const MAX_CHANNEL_VALUE = 0xFF;
194const MAX_ALPHA_VALUE = 1;
195const ERROR_CODE_RESOURCE_GET_FAILED = 180003;
196const ERROR_CODE_COLOR_PARAMETER_INCORRECT = 401;
197
198class ColorMetrics {
199  private red_: number;
200  private green_: number;
201  private blue_: number;
202  private alpha_: number;
203  private resourceId_: number;
204  private colorSpace_: ColorSpace;
205  private res_: Resource | undefined;
206  private static clamp(value: number): number {
207    return Math.min(Math.max(value, 0), MAX_CHANNEL_VALUE);
208  }
209  private constructor(red: number, green: number, blue: number, alpha: number = MAX_CHANNEL_VALUE, res?: Resource) {
210    this.red_ = ColorMetrics.clamp(red);
211    this.green_ = ColorMetrics.clamp(green);
212    this.blue_ = ColorMetrics.clamp(blue);
213    this.alpha_ = ColorMetrics.clamp(alpha);
214    this.res_ = res === undefined ? undefined : res;
215  }
216  private toNumeric(): number {
217    return (this.alpha_ << 24) + (this.red_ << 16) + (this.green_ << 8) + this.blue_;
218  }
219  static numeric(value: number): ColorMetrics {
220    const red = (value >> 16) & 0x000000FF;
221    const green = (value >> 8) & 0x000000FF;
222    const blue = value & 0x000000FF;
223    const alpha = (value >> 24) & 0x000000FF;
224    if (alpha === 0) {
225      return new ColorMetrics(red, green, blue);
226    }
227    return new ColorMetrics(red, green, blue, alpha);
228  }
229  static rgba(red: number, green: number, blue: number, alpha: number = MAX_ALPHA_VALUE): ColorMetrics {
230    return new ColorMetrics(red, green, blue, alpha * MAX_CHANNEL_VALUE);
231  }
232  static colorWithSpace(colorSpace: ColorSpace, red: number, green: number, blue: number, alpha: number = MAX_ALPHA_VALUE): ColorMetrics {
233    let redInt = Math.round(red * MAX_CHANNEL_VALUE);
234    let greenInt = Math.round(green * MAX_CHANNEL_VALUE);
235    let blueInt = Math.round(blue * MAX_CHANNEL_VALUE);
236    let alphaInt = Math.round(alpha * MAX_CHANNEL_VALUE);
237    const colorMetrics = new ColorMetrics(redInt, greenInt, blueInt, alphaInt);
238    colorMetrics.setColorSpace(colorSpace);
239    return colorMetrics;
240  }
241
242  private static rgbOrRGBA(format: string): ColorMetrics {
243    const rgbPattern = /^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i;
244    const rgbaPattern = /^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+(\.\d+)?)\s*\)$/i;
245
246    const rgbMatch = rgbPattern.exec(format);
247    const rgbaMatch = rgbaPattern.exec(format);
248
249    if (rgbMatch) {
250      const [, red, green, blue] = rgbMatch;
251      return new ColorMetrics(Number.parseInt(red, 10), Number.parseInt(green, 10), Number.parseInt(blue, 10));
252    } else if (rgbaMatch) {
253      const [, red, green, blue, alpha] = rgbaMatch;
254      return new ColorMetrics(Number.parseInt(red, 10), Number.parseInt(green, 10), Number.parseInt(blue, 10), Number.parseFloat(alpha) * MAX_CHANNEL_VALUE);
255    } else {
256      const error = new Error('Parameter error. The format of the input color string is not RGB or RGBA.') as BusinessError;
257      error.code = ERROR_CODE_COLOR_PARAMETER_INCORRECT;
258      throw error;
259    }
260  }
261
262  static resourceColor(color: ResourceColor): ColorMetrics {
263    if (color === undefined || color === null) {
264      const error = new Error('Parameter error. The type of the input color parameter is not ResourceColor.') as BusinessError;
265      error.code = ERROR_CODE_COLOR_PARAMETER_INCORRECT;
266      throw error;
267    }
268    let chanels: Array<number> = [];
269    if (typeof color === 'object') {
270      chanels = getUINativeModule().nativeUtils.parseResourceColor(color);
271      if (chanels === undefined) {
272        const error = new Error('Failed to obtain the color resource.') as BusinessError;
273        error.code = ERROR_CODE_RESOURCE_GET_FAILED;
274        throw error;
275      }
276      const red = chanels[0];
277      const green = chanels[1];
278      const blue = chanels[2];
279      const alpha = chanels[3];
280      const resourceId = chanels[4];
281      const colorMetrics = new ColorMetrics(red, green, blue, alpha, color);
282      colorMetrics.setResourceId(resourceId);
283      return colorMetrics;
284    } else if (typeof color === 'number') {
285      return ColorMetrics.numeric(color);
286    } else if (typeof color === 'string') {
287      if (ColorMetrics.isHexFormat(color)) {
288        return ColorMetrics.hex(color);
289      } else {
290        return ColorMetrics.rgbOrRGBA(color);
291      }
292    } else {
293      const error = new Error('Parameter error. The type of the input color parameter is not ResourceColor.') as BusinessError;
294      error.code = ERROR_CODE_COLOR_PARAMETER_INCORRECT;
295      throw error;
296    }
297  }
298  private static isHexFormat(format: string): boolean {
299    return /#(([0-9A-Fa-f]{3})|([0-9A-Fa-f]{6})|([0-9A-Fa-f]{4})|([0-9A-Fa-f]{8}))/.test(format);
300  }
301
302  private static hex(hexFormat: string): ColorMetrics {
303    let r: number = 0;
304    let g: number = 0;
305    let b: number = 0;
306    let a: number = 255;
307    if (hexFormat.length === 4) {
308      r = parseInt(hexFormat.slice(1, 2).repeat(2), 16);
309      g = parseInt(hexFormat.slice(2, 3).repeat(2), 16);
310      b = parseInt(hexFormat.slice(3).repeat(2), 16);
311    } else if (hexFormat.length === 7) {
312      r = parseInt(hexFormat.slice(1, 3), 16);
313      g = parseInt(hexFormat.slice(3, 5), 16);
314      b = parseInt(hexFormat.slice(5), 16);
315    } else if (hexFormat.length === 5) {
316      a = parseInt(hexFormat.slice(1, 2).repeat(2), 16);
317      r = parseInt(hexFormat.slice(2, 3).repeat(2), 16);
318      g = parseInt(hexFormat.slice(3, 4).repeat(2), 16);
319      b = parseInt(hexFormat.slice(4).repeat(2), 16);
320    } else if (hexFormat.length === 9) {
321      a = parseInt(hexFormat.slice(1, 3), 16);
322      r = parseInt(hexFormat.slice(3, 5), 16);
323      g = parseInt(hexFormat.slice(5, 7), 16);
324      b = parseInt(hexFormat.slice(7), 16);
325    }
326    return new ColorMetrics(r, g, b, a);
327  }
328  blendColor(overlayColor: ColorMetrics): ColorMetrics {
329    if (overlayColor === undefined || overlayColor === null) {
330      const error = new Error('Parameter error. The type of the input parameter is not ColorMetrics.') as BusinessError;
331      error.code = ERROR_CODE_COLOR_PARAMETER_INCORRECT;
332      throw error;
333    }
334    const chanels = getUINativeModule().nativeUtils.blendColor(this.toNumeric(), overlayColor.toNumeric());
335    if (chanels === undefined) {
336      const error = new Error('Parameter error. The type of the input parameter is not ColorMetrics.') as BusinessError;
337      error.code = ERROR_CODE_COLOR_PARAMETER_INCORRECT;
338      throw error;
339    }
340    const red = chanels[0];
341    const green = chanels[1];
342    const blue = chanels[2];
343    const alpha = chanels[3];
344    return new ColorMetrics(red, green, blue, alpha);
345  }
346  get color(): string {
347    return `rgba(${this.red_}, ${this.green_}, ${this.blue_}, ${this.alpha_ / MAX_CHANNEL_VALUE})`;
348  }
349  get red(): number {
350    return this.red_;
351  }
352  get green(): number {
353    return this.green_;
354  }
355  get blue(): number {
356    return this.blue_;
357  }
358  get alpha(): number {
359    return this.alpha_;
360  }
361  setResourceId(resourceId: number): void {
362    this.resourceId_ = resourceId;
363  }
364  getResourceId(): number {
365    return this.resourceId_;
366  }
367  setColorSpace(colorSpace: ColorSpace): void {
368    if (ColorSpace.DISPLAY_P3 === colorSpace || ColorSpace.SRGB === colorSpace) {
369      this.colorSpace_ = colorSpace;
370    }
371  }
372  getColorSpace(): ColorSpace {
373    return this.colorSpace_;
374  }
375}
376
377class BaseShape {
378  public rect: Rect | null = null;
379  public roundRect: RoundRect | null = null;
380  public circle: Circle | null = null;
381  public oval: Rect | null = null;
382  public path: CommandPath | null = null;
383  setRectShape(rect: Rect) {
384    this.rect = rect;
385    this.roundRect = null;
386    this.circle = null;
387    this.oval = null;
388    this.path = null;
389  }
390  setRoundRectShape(roundRect: RoundRect) {
391    this.roundRect = roundRect;
392    this.rect = null;
393    this.circle = null;
394    this.oval = null;
395    this.path = null;
396  }
397  setCircleShape(circle: Circle) {
398    this.circle = circle;
399    this.rect = null;
400    this.roundRect = null;
401    this.oval = null;
402    this.path = null;
403  }
404  setOvalShape(oval: Rect) {
405    this.oval = oval;
406    this.rect = null;
407    this.circle = null;
408    this.roundRect = null;
409    this.path = null;
410  }
411  setCommandPath(path: CommandPath) {
412    this.path = path;
413    this.oval = null;
414    this.rect = null;
415    this.circle = null;
416    this.roundRect = null;
417  }
418}
419
420class ShapeClip extends BaseShape { }
421
422class ShapeMask extends BaseShape {
423  public fillColor: number = 0XFF000000;
424  public strokeColor: number = 0XFF000000;
425  public strokeWidth: number = 0;
426}
427
428class RenderNode extends Disposable {
429  private childrenList: Array<RenderNode>;
430  private nodePtr: NodePtr;
431  private parentRenderNode: WeakRef<RenderNode> | null;
432  private backgroundColorValue: number;
433  private clipToFrameValue: boolean;
434  private frameValue: Frame;
435  private opacityValue: number;
436  private pivotValue: Vector2;
437  private rotationValue: Vector3;
438  private scaleValue: Vector2;
439  private shadowColorValue: number;
440  private shadowOffsetValue: Vector2;
441  private labelValue: string;
442  private shadowAlphaValue: number;
443  private shadowElevationValue: number;
444  private shadowRadiusValue: number;
445  private transformValue: Transform;
446  private translationValue: Vector2;
447  private baseNode_: BaseNode;
448  private borderStyleValue: EdgeStyles;
449  private borderWidthValue: EdgeWidths;
450  private borderColorValue: EdgeColors;
451  private borderRadiusValue: BorderRadiuses;
452  private shapeMaskValue: ShapeMask;
453  private shapeClipValue: ShapeClip;
454  private _nativeRef: NativeStrongRef;
455  private _frameNode: WeakRef<FrameNode>;
456  private lengthMetricsUnitValue: LengthMetricsUnit;
457  private markNodeGroupValue: boolean;
458  private apiTargetVersion: number;
459
460  constructor(type: string) {
461    super();
462    this.nodePtr = null;
463    this.childrenList = [];
464    this.parentRenderNode = null;
465    this.backgroundColorValue = 0;
466    this.apiTargetVersion = getUINativeModule().common.getApiTargetVersion();
467    this.clipToFrameValue = true;
468    if (this.apiTargetVersion && this.apiTargetVersion < 12) {
469        this.clipToFrameValue = false;
470    }
471    this.frameValue = { x: 0, y: 0, width: 0, height: 0 };
472    this.opacityValue = 1.0;
473    this.pivotValue = { x: 0.5, y: 0.5 };
474    this.rotationValue = { x: 0, y: 0, z: 0 };
475    this.scaleValue = { x: 1.0, y: 1.0 };
476    this.shadowColorValue = 0;
477    this.shadowOffsetValue = { x: 0, y: 0 };
478    this.labelValue = '';
479    this.shadowAlphaValue = 0;
480    this.shadowElevationValue = 0;
481    this.shadowRadiusValue = 0;
482    this.transformValue = [1, 0, 0, 0,
483      0, 1, 0, 0,
484      0, 0, 1, 0,
485      0, 0, 0, 1];
486    this.translationValue = { x: 0, y: 0 };
487    this.lengthMetricsUnitValue = LengthMetricsUnit.DEFAULT;
488    this.markNodeGroupValue = false;
489    if (type === 'BuilderRootFrameNode' || type === 'CustomFrameNode') {
490      return;
491    }
492    this._nativeRef = getUINativeModule().renderNode.createRenderNode(this);
493    this.nodePtr = this._nativeRef?.getNativeHandle();
494    if (this.apiTargetVersion && this.apiTargetVersion < 12) {
495      this.clipToFrame = false;
496  } else {
497      this.clipToFrame = true;
498  }
499  }
500
501  set backgroundColor(color: number) {
502    this.backgroundColorValue = this.checkUndefinedOrNullWithDefaultValue<number>(color, 0);
503    getUINativeModule().renderNode.setBackgroundColor(this.nodePtr, this.backgroundColorValue);
504  }
505  set clipToFrame(useClip: boolean) {
506    this.clipToFrameValue = this.checkUndefinedOrNullWithDefaultValue<boolean>(useClip, true);
507    getUINativeModule().renderNode.setClipToFrame(this.nodePtr, this.clipToFrameValue);
508  }
509  set frame(frame: Frame) {
510    if (frame === undefined || frame === null) {
511      this.frameValue = { x: 0, y: 0, width: 0, height: 0 };
512    } else {
513      this.size = { width: frame.width, height: frame.height };
514      this.position = { x: frame.x, y: frame.y };
515    }
516  }
517  set opacity(value: number) {
518    this.opacityValue = this.checkUndefinedOrNullWithDefaultValue<number>(value, 1.0);
519    getUINativeModule().common.setOpacity(this.nodePtr, this.opacityValue);
520  }
521  set pivot(pivot: Vector2) {
522    if (pivot === undefined || pivot === null) {
523      this.pivotValue = { x: 0.5, y: 0.5 };
524    } else {
525      this.pivotValue.x = this.checkUndefinedOrNullWithDefaultValue<number>(pivot.x, 0.5);
526      this.pivotValue.y = this.checkUndefinedOrNullWithDefaultValue<number>(pivot.y, 0.5);
527    }
528    getUINativeModule().renderNode.setPivot(this.nodePtr, this.pivotValue.x, this.pivotValue.y);
529  }
530  set position(position: Vector2) {
531    if (position === undefined || position === null) {
532      this.frameValue.x = 0;
533      this.frameValue.y = 0;
534    } else {
535      this.frameValue.x = this.checkUndefinedOrNullWithDefaultValue<number>(position.x, 0);
536      this.frameValue.y = this.checkUndefinedOrNullWithDefaultValue<number>(position.y, 0);
537    }
538    getUINativeModule().renderNode.setPosition(this.nodePtr, this.frameValue.x, this.frameValue.y, this.lengthMetricsUnitValue);
539  }
540  set rotation(rotation: Vector3) {
541    if (rotation === undefined || rotation === null) {
542      this.rotationValue = { x: 0, y: 0, z: 0 };
543    } else {
544      this.rotationValue.x = this.checkUndefinedOrNullWithDefaultValue<number>(rotation.x, 0);
545      this.rotationValue.y = this.checkUndefinedOrNullWithDefaultValue<number>(rotation.y, 0);
546      this.rotationValue.z = this.checkUndefinedOrNullWithDefaultValue<number>(rotation.z, 0);
547    }
548    getUINativeModule().renderNode.setRotation(this.nodePtr, this.rotationValue.x, this.rotationValue.y, this.rotationValue.z, this.lengthMetricsUnitValue);
549  }
550  set scale(scale: Vector2) {
551    if (scale === undefined || scale === null) {
552      this.scaleValue = { x: 1.0, y: 1.0 };
553    } else {
554      this.scaleValue.x = this.checkUndefinedOrNullWithDefaultValue<number>(scale.x, 1.0);
555      this.scaleValue.y = this.checkUndefinedOrNullWithDefaultValue<number>(scale.y, 1.0);
556    }
557    getUINativeModule().renderNode.setScale(this.nodePtr, this.scaleValue.x, this.scaleValue.y);
558  }
559  set shadowColor(color: number) {
560    this.shadowColorValue = this.checkUndefinedOrNullWithDefaultValue<number>(color, 0);
561    getUINativeModule().renderNode.setShadowColor(this.nodePtr, this.shadowColorValue);
562  }
563  set shadowOffset(offset: Vector2) {
564    if (offset === undefined || offset === null) {
565      this.shadowOffsetValue = { x: 0, y: 0 };
566    } else {
567      this.shadowOffsetValue.x = this.checkUndefinedOrNullWithDefaultValue<number>(offset.x, 0);
568      this.shadowOffsetValue.y = this.checkUndefinedOrNullWithDefaultValue<number>(offset.y, 0);
569    }
570    getUINativeModule().renderNode.setShadowOffset(this.nodePtr, this.shadowOffsetValue.x, this.shadowOffsetValue.y, this.lengthMetricsUnitValue);
571  }
572  set label(label: string) {
573    this.labelValue = this.checkUndefinedOrNullWithDefaultValue<string>(label, '');
574    getUINativeModule().renderNode.setLabel(this.nodePtr, this.labelValue);
575  }
576  set shadowAlpha(alpha: number) {
577    this.shadowAlphaValue = this.checkUndefinedOrNullWithDefaultValue<number>(alpha, 0);
578    getUINativeModule().renderNode.setShadowAlpha(this.nodePtr, this.shadowAlphaValue);
579  }
580  set shadowElevation(elevation: number) {
581    this.shadowElevationValue = this.checkUndefinedOrNullWithDefaultValue<number>(elevation, 0);
582    getUINativeModule().renderNode.setShadowElevation(this.nodePtr, this.shadowElevationValue);
583  }
584  set shadowRadius(radius: number) {
585    this.shadowRadiusValue = this.checkUndefinedOrNullWithDefaultValue<number>(radius, 0);
586    getUINativeModule().renderNode.setShadowRadius(this.nodePtr, this.shadowRadiusValue);
587  }
588  set size(size: Size) {
589    if (size === undefined || size === null) {
590      this.frameValue.width = 0;
591      this.frameValue.height = 0;
592    } else {
593      this.frameValue.width = this.checkUndefinedOrNullWithDefaultValue<number>(size.width, 0);
594      this.frameValue.height = this.checkUndefinedOrNullWithDefaultValue<number>(size.height, 0);
595    }
596      getUINativeModule().renderNode.setSize(this.nodePtr, this.frameValue.width, this.frameValue.height, this.lengthMetricsUnitValue);
597  }
598  set transform(transform: Transform) {
599    if (transform === undefined || transform === null) {
600      this.transformValue = [1, 0, 0, 0,
601        0, 1, 0, 0,
602        0, 0, 1, 0,
603        0, 0, 0, 1];
604    } else {
605      let i: number = 0;
606      while (i < transform.length && i < 16) {
607        if (i % 5 === 0) {
608          this.transformValue[i] = this.checkUndefinedOrNullWithDefaultValue<number>(transform[i], 1);
609        } else {
610          this.transformValue[i] = this.checkUndefinedOrNullWithDefaultValue<number>(transform[i], 0);
611        }
612        i = i + 1;
613      }
614    }
615    getUINativeModule().common.setTransform(this.nodePtr, this.transformValue);
616  }
617  set translation(translation: Vector2) {
618    if (translation === undefined || translation === null) {
619      this.translationValue = { x: 0, y: 0 };
620    } else {
621      this.translationValue.x = this.checkUndefinedOrNullWithDefaultValue<number>(translation.x, 0);
622      this.translationValue.y = this.checkUndefinedOrNullWithDefaultValue<number>(translation.y, 0);
623    }
624    getUINativeModule().renderNode.setTranslate(this.nodePtr, this.translationValue.x, this.translationValue.y, 0);
625  }
626  set lengthMetricsUnit(unit: LengthMetricsUnit) {
627    if (unit === undefined || unit == null) {
628      this.lengthMetricsUnitValue = LengthMetricsUnit.DEFAULT;
629    } else {
630      this.lengthMetricsUnitValue = unit;
631    }
632  }
633  set markNodeGroup(isNodeGroup) {
634    if (isNodeGroup === undefined || isNodeGroup === null) {
635        this.markNodeGroupValue = false;
636    } else {
637        this.markNodeGroupValue = isNodeGroup;
638    }
639    getUINativeModule().renderNode.setMarkNodeGroup(this.nodePtr, this.markNodeGroupValue);
640  }
641  get backgroundColor(): number {
642    return this.backgroundColorValue;
643  }
644  get clipToFrame(): boolean {
645    return this.clipToFrameValue;
646  }
647  get opacity(): number {
648    return this.opacityValue;
649  }
650  get frame(): Frame {
651    return this.frameValue;
652  }
653  get pivot(): Vector2 {
654    return this.pivotValue;
655  }
656  get position(): Vector2 {
657    return { x: this.frameValue.x, y: this.frameValue.y };
658  }
659  get rotation(): Vector3 {
660    return this.rotationValue;
661  }
662  get scale(): Vector2 {
663    return this.scaleValue;
664  }
665  get shadowColor(): number {
666    return this.shadowColorValue;
667  }
668  get shadowOffset(): Vector2 {
669    return this.shadowOffsetValue;
670  }
671  get label(): string {
672    return this.labelValue;
673  }
674  get shadowAlpha(): number {
675    return this.shadowAlphaValue;
676  }
677  get shadowElevation(): number {
678    return this.shadowElevationValue;
679  }
680  get shadowRadius(): number {
681    return this.shadowRadiusValue;
682  }
683  get size(): Size {
684    return { width: this.frameValue.width, height: this.frameValue.height };
685  }
686  get transform(): Transform {
687    return this.transformValue;
688  }
689  get translation(): Vector2 {
690    return this.translationValue;
691  }
692  get lengthMetricsUnit() {
693    return this.lengthMetricsUnitValue;
694  }
695  get markNodeGroup() {
696    return this.markNodeGroupValue;
697  }
698  checkUndefinedOrNullWithDefaultValue<T>(arg: T, defaultValue: T): T {
699    if (arg === undefined || arg === null) {
700      return defaultValue;
701    } else {
702      return arg;
703    }
704  }
705  appendChild(node: RenderNode) {
706    if (node === undefined || node === null) {
707      return;
708    }
709    if (this.childrenList.findIndex(element => element === node) !== -1) {
710      return;
711    }
712    this.childrenList.push(node);
713    node.parentRenderNode = new WeakRef(this);
714    getUINativeModule().renderNode.appendChild(this.nodePtr, node.nodePtr);
715    getUINativeModule().renderNode.addBuilderNode(this.nodePtr, node.nodePtr);
716  }
717  insertChildAfter(child: RenderNode, sibling: RenderNode | null) {
718    if (child === undefined || child === null) {
719      return;
720    }
721    let indexOfNode: number = this.childrenList.findIndex(element => element === child);
722    if (indexOfNode !== -1) {
723      return;
724    }
725    child.parentRenderNode = new WeakRef(this);
726    let indexOfSibling = this.childrenList.findIndex(element => element === sibling);
727    if (indexOfSibling === -1) {
728      sibling === null;
729    }
730    if (sibling === undefined || sibling === null) {
731      this.childrenList.splice(0, 0, child);
732      getUINativeModule().renderNode.insertChildAfter(this.nodePtr, child.nodePtr, null);
733    } else {
734      this.childrenList.splice(indexOfSibling + 1, 0, child);
735      getUINativeModule().renderNode.insertChildAfter(this.nodePtr, child.nodePtr, sibling.nodePtr);
736    }
737    getUINativeModule().renderNode.addBuilderNode(this.nodePtr, child.nodePtr);
738  }
739  removeChild(node: RenderNode) {
740    if (node === undefined || node === null) {
741      return;
742    }
743    const index = this.childrenList.findIndex(element => element === node);
744    if (index === -1) {
745      return;
746    }
747    const child = this.childrenList[index];
748    child.parentRenderNode = null;
749    this.childrenList.splice(index, 1);
750    getUINativeModule().renderNode.removeBuilderNode(this.nodePtr, node.nodePtr);
751    getUINativeModule().renderNode.removeChild(this.nodePtr, node.nodePtr);
752  }
753  clearChildren() {
754    getUINativeModule().renderNode.clearBuilderNode(this.nodePtr);
755    this.childrenList = new Array<RenderNode>();
756    getUINativeModule().renderNode.clearChildren(this.nodePtr);
757  }
758  getChild(index: number): RenderNode | null {
759    if (this.childrenList.length > index && index >= 0) {
760      return this.childrenList[index];
761    }
762    return null;
763  }
764  getFirstChild(): RenderNode | null {
765    if (this.childrenList.length > 0) {
766      return this.childrenList[0];
767    }
768    return null;
769  }
770  getNextSibling(): RenderNode | null {
771    if (this.parentRenderNode === undefined || this.parentRenderNode === null) {
772      return null;
773    }
774    let parent = this.parentRenderNode.deref();
775    if (parent === undefined || parent === null) {
776      return null;
777    }
778    let siblingList = parent.childrenList;
779    const index = siblingList.findIndex(element => element === this);
780    if (index === -1) {
781      return null;
782    }
783    return parent.getChild(index + 1);
784  }
785  getPreviousSibling(): RenderNode | null {
786    if (this.parentRenderNode === undefined || this.parentRenderNode === null) {
787      return null;
788    }
789    let parent = this.parentRenderNode.deref();
790    if (parent === undefined || parent === null) {
791      return null;
792    }
793    let siblingList = parent.childrenList;
794    const index = siblingList.findIndex(element => element === this);
795    if (index === -1) {
796      return null;
797    }
798    return parent.getChild(index - 1);
799  }
800  setFrameNode(frameNode: WeakRef<FrameNode>) {
801    this._frameNode = frameNode;
802  }
803
804  setNodePtr(nativeRef: NativeStrongRef) {
805    this._nativeRef = nativeRef;
806    this.nodePtr = this._nativeRef?.getNativeHandle();
807  }
808
809  setBaseNode(baseNode: BaseNode | null) {
810    this.baseNode_ = baseNode;
811  }
812  resetNodePtr(): void {
813    this.nodePtr = null;
814    this._nativeRef = null;
815  }
816  getNodeType(): string {
817    return getUINativeModule().renderNode.getNodeType(this.nodePtr);
818  }
819  dispose() {
820    super.dispose();
821    if (this.nodePtr) {
822      getUINativeModule().renderNode.fireArkUIObjectLifecycleCallback(new WeakRef(this),
823          'RenderNode', this.getNodeType() || 'RenderNode', this.nodePtr);
824    }
825    this._nativeRef?.dispose();
826    this.baseNode_?.disposeNode();
827    this._frameNode?.deref()?.resetNodePtr();
828    this._nativeRef = null;
829    this.nodePtr = null;
830  }
831  isDisposed(): boolean {
832    return super.isDisposed() && (this._nativeRef === undefined || this._nativeRef === null);
833  }
834  getNodePtr(): NodePtr {
835    return this.nodePtr;
836  }
837
838  invalidate() {
839    getUINativeModule().renderNode.invalidate(this.nodePtr);
840  }
841  set borderStyle(style: EdgeStyles) {
842    if (style === undefined || style === null) {
843      this.borderStyleValue = { left: BorderStyle.NONE, top: BorderStyle.NONE, right: BorderStyle.NONE, bottom: BorderStyle.NONE };
844    } else {
845      this.borderStyleValue = style;
846    }
847    getUINativeModule().renderNode.setBorderStyle(
848      this.nodePtr, this.borderStyleValue.left, this.borderStyleValue.top, this.borderStyleValue.right, this.borderStyleValue.bottom);
849  }
850  get borderStyle(): EdgeStyles {
851    return this.borderStyleValue;
852  }
853  set borderWidth(width: EdgeWidths) {
854    if (width === undefined || width === null) {
855      this.borderWidthValue = { left: 0, top: 0, right: 0, bottom: 0 };
856    } else {
857      this.borderWidthValue = width;
858    }
859    getUINativeModule().renderNode.setBorderWidth(
860      this.nodePtr, this.borderWidthValue.left, this.borderWidthValue.top,
861      this.borderWidthValue.right, this.borderWidthValue.bottom, this.lengthMetricsUnitValue);
862  }
863  get borderWidth(): EdgeWidths {
864    return this.borderWidthValue;
865  }
866  set borderColor(color: EdgeColors) {
867    if (color === undefined || color === null) {
868      this.borderColorValue = { left: 0XFF000000, top: 0XFF000000, right: 0XFF000000, bottom: 0XFF000000 };
869    } else {
870      this.borderColorValue = color;
871    }
872    getUINativeModule().renderNode.setBorderColor(
873      this.nodePtr, this.borderColorValue.left, this.borderColorValue.top, this.borderColorValue.right, this.borderColorValue.bottom);
874  }
875  get borderColor(): EdgeColors {
876    return this.borderColorValue;
877  }
878  set borderRadius(radius: BorderRadiuses) {
879    if (radius === undefined || radius === null) {
880      this.borderRadiusValue = { topLeft: 0, topRight: 0, bottomLeft: 0, bottomRight: 0 };
881    } else {
882      this.borderRadiusValue = radius;
883    }
884    getUINativeModule().renderNode.setBorderRadius(
885      this.nodePtr, this.borderRadiusValue.topLeft, this.borderRadiusValue.topRight,
886      this.borderRadiusValue.bottomLeft, this.borderRadiusValue.bottomRight, this.lengthMetricsUnitValue);
887  }
888  get borderRadius(): BorderRadiuses {
889    return this.borderRadiusValue;
890  }
891  set shapeMask(shapeMask: ShapeMask) {
892    if (shapeMask === undefined || shapeMask === null) {
893      this.shapeMaskValue = new ShapeMask();
894    } else {
895      this.shapeMaskValue = shapeMask;
896    }
897    if (this.shapeMaskValue.rect !== null) {
898      const rectMask = this.shapeMaskValue.rect;
899      getUINativeModule().renderNode.setRectMask(
900        this.nodePtr, rectMask.left, rectMask.top, rectMask.right, rectMask.bottom,
901        this.shapeMaskValue.fillColor, this.shapeMaskValue.strokeColor, this.shapeMaskValue.strokeWidth);
902    } else if (this.shapeMaskValue.circle !== null) {
903      const circle = this.shapeMaskValue.circle;
904      getUINativeModule().renderNode.setCircleMask(
905        this.nodePtr, circle.centerX, circle.centerY, circle.radius,
906        this.shapeMaskValue.fillColor, this.shapeMaskValue.strokeColor, this.shapeMaskValue.strokeWidth);
907    } else if (this.shapeMaskValue.roundRect !== null) {
908      const roundRect = this.shapeMask.roundRect;
909      const corners = roundRect.corners;
910      const rect = roundRect.rect;
911      getUINativeModule().renderNode.setRoundRectMask(
912        this.nodePtr,
913        corners.topLeft.x,
914        corners.topLeft.y,
915        corners.topRight.x,
916        corners.topRight.y,
917        corners.bottomLeft.x,
918        corners.bottomLeft.y,
919        corners.bottomRight.x,
920        corners.bottomRight.y,
921        rect.left,
922        rect.top,
923        rect.right,
924        rect.bottom,
925        this.shapeMaskValue.fillColor,
926        this.shapeMaskValue.strokeColor,
927        this.shapeMaskValue.strokeWidth);
928    } else if (this.shapeMaskValue.oval !== null) {
929      const oval = this.shapeMaskValue.oval;
930      getUINativeModule().renderNode.setOvalMask(
931        this.nodePtr, oval.left, oval.top, oval.right, oval.bottom,
932        this.shapeMaskValue.fillColor, this.shapeMaskValue.strokeColor, this.shapeMaskValue.strokeWidth);
933    } else if (this.shapeMaskValue.path !== null) {
934      const path = this.shapeMaskValue.path;
935      getUINativeModule().renderNode.setPath(
936        this.nodePtr, path.commands, this.shapeMaskValue.fillColor, this.shapeMaskValue.strokeColor, this.shapeMaskValue.strokeWidth);
937    }
938  }
939  get shapeMask(): ShapeMask {
940    return this.shapeMaskValue;
941  }
942  set shapeClip(shapeClip: ShapeClip) {
943    if (shapeClip === undefined || shapeClip === null) {
944      this.shapeClipValue = new ShapeClip();
945    } else {
946      this.shapeClipValue = shapeClip;
947    }
948    if (this.shapeClipValue.rect !== null) {
949      const rectClip = this.shapeClipValue.rect;
950      getUINativeModule().renderNode.setRectClip(
951        this.nodePtr, rectClip.left, rectClip.top, rectClip.right, rectClip.bottom);
952    } else if (this.shapeClipValue.circle !== null) {
953      const circle = this.shapeClipValue.circle;
954      getUINativeModule().renderNode.setCircleClip(
955        this.nodePtr, circle.centerX, circle.centerY, circle.radius);
956    } else if (this.shapeClipValue.roundRect !== null) {
957      const roundRect = this.shapeClipValue.roundRect;
958      const corners = roundRect.corners;
959      const rect = roundRect.rect;
960      getUINativeModule().renderNode.setRoundRectClip(
961        this.nodePtr,
962        corners.topLeft.x,
963        corners.topLeft.y,
964        corners.topRight.x,
965        corners.topRight.y,
966        corners.bottomLeft.x,
967        corners.bottomLeft.y,
968        corners.bottomRight.x,
969        corners.bottomRight.y,
970        rect.left,
971        rect.top,
972        rect.right,
973        rect.bottom);
974    } else if (this.shapeClipValue.oval !== null) {
975      const oval = this.shapeClipValue.oval;
976      getUINativeModule().renderNode.setOvalClip(
977        this.nodePtr, oval.left, oval.top, oval.right, oval.bottom,
978      );
979    } else if (this.shapeClipValue.path !== null) {
980      const path = this.shapeClipValue.path;
981      getUINativeModule().renderNode.setPathClip(
982        this.nodePtr, path.commands);
983    }
984  }
985  get shapeClip(): ShapeClip {
986    this.shapeClipValue = this.shapeClipValue ? this.shapeClipValue : new ShapeClip();
987    return this.shapeClipValue;
988  }
989}
990
991function edgeColors(all: number): EdgeColors {
992  return { left: all, top: all, right: all, bottom: all };
993}
994
995function edgeWidths(all: number): EdgeWidths {
996  return { left: all, top: all, right: all, bottom: all };
997}
998
999function borderStyles(all: BorderStyle): EdgeStyles {
1000  return { left: all, top: all, right: all, bottom: all };
1001}
1002
1003function borderRadiuses(all: number): BorderRadiuses {
1004  return { topLeft: all, topRight: all, bottomLeft: all, bottomRight: all };
1005}
1006