Browse Source

item增加全局透明度;spath添加;绘制文本

haojianlong 4 năm trước cách đây
mục cha
commit
4b4e94bc8f

+ 1 - 1
saga-web-draw/package.json

@@ -1,6 +1,6 @@
 {
 {
     "name": "@saga-web/draw",
     "name": "@saga-web/draw",
-    "version": "2.1.108",
+    "version": "2.1.109",
     "description": "上格云绘制引擎。",
     "description": "上格云绘制引擎。",
     "main": "lib/index.js",
     "main": "lib/index.js",
     "types": "lib/index.d.js",
     "types": "lib/index.d.js",

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 280 - 386
saga-web-draw/src/SPainter.ts


+ 208 - 0
saga-web-draw/src/SPath.ts

@@ -0,0 +1,208 @@
+/*
+ * *********************************************************************************************************************
+ *
+ *          !!
+ *        .F88X
+ *        X8888Y
+ *      .}888888N;
+ *        i888888N;        .:!              .I$WI:
+ *          R888888I      .'N88~            i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
+ *          .R888888I    .;N8888~          .X8'  "8I.!,/8"  !%NY8`"8I8~~8>,88I
+ *            +888888N;  .8888888Y                                  "&&8Y.}8,
+ *            ./888888N;  .R888888Y        .'}~    .>}'.`+>  i}!    "i'  +/'  .'i~  !11,.:">,  .~]!  .i}i
+ *              ~888888%:  .I888888l      .]88~`1/iY88Ii+1'.R$8$8]"888888888>  Y8$  W8E  X8E  W8888'188Il}Y88$*
+ *              18888888    E8888881    .]W%8$`R8X'&8%++N8i,8N%N8+l8%`  .}8N:.R$RE%N88N%N$K$R  188,FE$8%~Y88I
+ *            .E888888I  .i8888888'      .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
+ *            8888888I  .,N888888~        ~88i"8W,!N8*.I88.}888%F,i$88"F88"  888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
+ *          i888888N'      I888Y          ]88;/EX*IFKFK88X  K8R  .l8W  88Y  ~88}'88E&%8W.X8N``]88!.$8K  .:W8I
+ *        .i888888N;        I8Y          .&8$  .X88!  i881.:%888>I88  ;88]  +88+.';;;;:.Y88X  18N.,88l  .+88/
+ *      .:R888888I
+ *      .&888888I                                          Copyright (c) 2009-2020.  博锐尚格科技股份有限公司
+ *        ~8888'
+ *        .!88~                                                                     All rights reserved.
+ *
+ * *********************************************************************************************************************
+ */
+
+import { SPathCommand } from "./SPathCommand";
+import { SPoint } from "./types/SPoint";
+
+/**
+ * Path 对象
+ *
+ * @author 庞利祥 <sybotan@126.com>
+ */
+export class SPath {
+    /** 命令集合 */
+    cmdList: SPathCommand[] = [];
+
+    /**
+     * 添加 path 命令
+     *
+     * @param cmd         命令
+     * @param args        命令参数
+     */
+    private addCommand(cmd: string, ...args: number[]): void {
+        this.cmdList.push({ command: cmd, args: args });
+    }
+
+    /**
+     * 添加一条新路径到对当前路径。
+     *
+     * @param path  路径对象
+     */
+    addPath(path: SPath): void {
+        this.cmdList = this.cmdList.concat(path.cmdList);
+    }
+
+    /**
+     * 使笔点返回到当前子路径的起始点。它尝试从当前点到起始点绘制一条直线。 如果图形已经是封闭的或者只有一个点,那么此函数不会做任何操作。
+     */
+    closePath(): void {
+        this.addCommand("Z");
+    }
+
+    /**
+     * 移动当前点到指定位置
+     *
+     * @param x       X 坐标
+     * @param y       Y 坐标
+     */
+    moveTo(x: number, y: number): void {
+        this.addCommand("M", x, y);
+    }
+
+    /**
+     * 从当前点向指定点画线
+     *
+     * @param x       X 坐标
+     * @param y       Y 坐标
+     */
+    lineTo(x: number, y: number): void {
+        this.addCommand("L", x, y);
+    }
+
+    /**
+     * 添加一条圆弧路径。
+     *
+     * @param x               圆孤圆心的 X 坐标
+     * @param y               圆弧圆心的 Y 坐标
+     * @param radius          圆弧半径
+     * @param startAngle      开始角度
+     * @param endAngle        结束角度
+     * @param anticlockwise   是否逆时针绘制( 1 是, 0 不是)
+     */
+    arc(
+        x: number,
+        y: number,
+        radius: number,
+        startAngle: number,
+        endAngle: number,
+        anticlockwise: number
+    ): void {
+        this.addCommand(
+            "Arc",
+            x,
+            y,
+            radius,
+            startAngle,
+            endAngle,
+            anticlockwise
+        );
+    }
+
+    /**
+     * 根据控制点和半径添加一条圆弧路径,使用直线连接前一个点。
+     *
+     * @param x1        点 1 的 x 坐标
+     * @param y1        点 1 的 y 坐标
+     * @param x2        点 2 的 x 坐标
+     * @param y2        点 1 的 y 坐标
+     * @param radius    半径
+     */
+    arcTo(
+        x1: number,
+        y1: number,
+        x2: number,
+        y2: number,
+        radius: number
+    ): void {
+        this.addCommand("ArcTo", x1, y1, x2, y2, radius);
+    }
+
+    /**
+     * 添加二次贝塞尔曲线
+     *
+     * @param cp1x    控制点 X 坐标
+     * @param cp1y    控制点 Y 坐标
+     * @param x       结束点 X 坐标
+     * @param y       结束点 Y 坐标
+     */
+    quadraticCurveTo(cp1x: number, cp1y: number, x: number, y: number): void {
+        this.addCommand("Q", cp1x, cp1y, x, y);
+    }
+
+    /**
+     * 添加三次贝塞尔曲线
+     *
+     * @param cp1x    起始点控制点 X 坐标
+     * @param cp1y    起始点控制点 Y 坐标
+     * @param cp2x    结束点控制点 X 坐标
+     * @param cp2y    结束点控制点 Y 坐标
+     * @param x       结束点 X 坐标
+     * @param y       结束点 Y 坐标
+     */
+    bezierCurveTo(
+        cp1x: number,
+        cp1y: number,
+        cp2x: number,
+        cp2y: number,
+        x: number,
+        y: number
+    ): void {
+        this.addCommand("C", cp1x, cp1y, cp2x, cp2y, x, y);
+    }
+
+    /**
+     * 添加椭圆
+     *
+     * @param cx          圆点 X 坐标
+     * @param cy          圆点 Y 坐标
+     * @param rx          水平半径
+     * @param ry          垂直半径
+     */
+    ellipse(cx: number, cy: number, rx: number, ry: number): void {
+        this.addCommand("Ellipse", cx, cy, rx, ry);
+    }
+
+    /**
+     * 添加矩形
+     *
+     * @param x           X 坐标
+     * @param y           Y 坐标
+     * @param w           宽度
+     * @param h           高度
+     */
+    rect(x: number, y: number, w: number, h: number): void {
+        this.addCommand("M", x, y);
+        this.addCommand("L", x + w, y);
+        this.addCommand("L", x + w, y + h);
+        this.addCommand("L", x, y + h);
+        this.addCommand("Z");
+    }
+
+    /**
+     * 添加多边形
+     *
+     * @param pList   点集数组
+     */
+    polygon(pList: SPoint[]): void {
+        if (pList.length > 2) {
+            this.addCommand("M", pList[0].x, pList[0].y);
+            for (let i = 1; i < pList.length; i++) {
+                this.addCommand("L", pList[i].x, pList[i].y);
+            }
+            this.addCommand("Z");
+        }
+    }
+}

+ 0 - 258
saga-web-draw/src/SPath2D.ts

@@ -1,258 +0,0 @@
-import { SPoint } from "./index";
-import {SStringBuilder} from "@saga-web/base/lib";
-
-/**
- * Path对象
- *
- * @author  庞利祥(sybotan@126.com)
- */
-export class SPath2D {
-    /** 内部path对象 */
-    _path = new Path2D();
-    private svgBuilder = new SStringBuilder();
-
-    /**
-     * svg数据值
-     */
-    svgPath(): string {
-        return this.svgBuilder.toString(" ");
-    } // Function svgPath()
-
-    /**
-     * 添加路径
-     *
-     * @param   path    添加的路径
-     */
-    addPath(path: SPath2D): void {
-        this._path.addPath(path._path);
-        this.svgBuilder.append(path.svgBuilder.toString(" "))
-    } // Function addPath()
-
-    /**
-     * 移动到指定位置
-     *
-     * @param   x       x坐标
-     * @param   y       y坐标
-     */
-    moveTo(x: number, y: number): void {
-        this._path.moveTo(x, y);
-        this.svgBuilder.append(`M ${x} ${y}`);
-    } // Function moveTo()
-
-    /**
-     * 从当前位置到指定位置画直线
-     *
-     * @param   x       x坐标
-     * @param   y       y坐标
-     */
-    lineTo(x: number, y: number): void {
-        this._path.lineTo(x, y);
-        this.svgBuilder.append(`L ${x} ${y}`);
-    } // Function moveTo()
-
-    /**
-     * 矩形
-     *
-     * @param   x           左上角x坐标
-     * @param   y           左上角y坐标
-     * @param   width       宽度
-     * @param   height      高度
-     */
-    rect(x: number, y: number, width: number, height: number): void {
-        let r = x + width;
-        let b = y + height;
-        this._path.moveTo(x, y);
-        this._path.lineTo(r, y);
-        this._path.lineTo(r, b);
-        this._path.lineTo(x, b);
-        this._path.closePath();
-        this.svgBuilder.append(`M ${x} ${y} L${r} ${y} L${r} ${b} L${x} ${b} Z`);
-        // // 逆时针
-        // this._path.moveTo(x, y);
-        // this._path.lineTo(r, y);
-        // this._path.lineTo(r, b);
-        // this._path.lineTo(x, b);
-        // this._path.closePath();
-        // this.svgBuilder.append(`M ${x} ${y} L${r} ${y} L${} ${} L${} ${} L${} ${}`);
-
-    } // Function rect()
-
-    /**
-     * 绘制折线
-     *
-     * @param   points      折线折点
-     */
-    polyline(points: SPoint[]): void {
-        if (points.length < 2) {
-            return;
-        }
-        points.map((it: SPoint, index: number): void => {
-            if (index == 0) {
-                this._path.moveTo(it.x, it.y);
-                this.svgBuilder.append(`M ${it.x} ${it.y}`);
-            } else {
-                this._path.lineTo(it.x, it.y);
-                this.svgBuilder.append(`L ${it.x} ${it.y}`);
-            }
-        });
-    } // Function drawPolyline()
-
-    /**
-     * 绘制多边形
-     *
-     * @param   points      多边形顶点
-     */
-    polygon(points: SPoint[]): void {
-        if (points.length < 3) {
-            return;
-        }
-        points.map((it: SPoint, index: number): void => {
-            if (index == 0) {
-                this._path.moveTo(it.x, it.y);
-                this.svgBuilder.append(`M ${it.x} ${it.y}`);
-            } else {
-                this._path.lineTo(it.x, it.y);
-                this.svgBuilder.append(`L ${it.x} ${it.y}`);
-            }
-        });
-        this._path.closePath();
-        this.svgBuilder.append(`Z`);
-    } // Functin polygon()
-
-    /**
-     * 椭圆弧
-     *
-     * @param   x               椭圆所在矩形X坐标
-     * @param   y               椭圆所在矩形Y坐标
-     * @param   width           椭圆所在矩形宽度
-     * @param   height          椭圆所在矩形高度
-     * @param   startAngle      开始角度(单位弧度)
-     * @param   endAngle        结束角度(单位弧度)
-     */
-    static arc(
-        x: number,
-        y: number,
-        width: number,
-        height: number,
-        startAngle: number,
-        endAngle: number
-    ): string {
-        let a = width / 2;
-        let b = height / 2;
-        let p1 = SPath2D.arcPoint(a, b, startAngle);
-        let p2 = SPath2D.arcPoint(a, b, endAngle);
-        let large = SPath2D.largeArcFlag(startAngle, endAngle);
-        p1.x = x + a + p1.x;
-        p1.y = y + b - p1.y;
-        p2.x = x + a + p2.x;
-        p2.y = y + b - p2.y;
-        return `M ${p1.x} ${p1.y} A ${a} ${b} 0 ${large} 0 ${p2.x} ${p2.y}`;
-    } // Function arc()
-
-    /**
-     * 绘制椭圆弦弧
-     *
-     * @param   x               椭圆所在矩形X坐标
-     * @param   y               椭圆所在矩形Y坐标
-     * @param   width           椭圆所在矩形宽度
-     * @param   height          椭圆所在矩形高度
-     * @param   startAngle      开始角度(单位弧度)
-     * @param   endAngle        结束角度(单位弧度)
-     */
-    static chord(
-        x: number,
-        y: number,
-        width: number,
-        height: number,
-        startAngle: number,
-        endAngle: number
-    ): string {
-        let a = width / 2;
-        let b = height / 2;
-        let p1 = SPath2D.arcPoint(a, b, startAngle);
-        let p2 = SPath2D.arcPoint(a, b, endAngle);
-        let large = SPath2D.largeArcFlag(startAngle, endAngle);
-        p1.x = x + a + p1.x;
-        p1.y = y + b - p1.y;
-        p2.x = x + a + p2.x;
-        p2.y = y + b - p2.y;
-        return `M ${p1.x} ${p1.y} A ${a} ${b} 0 ${large} 0 ${p2.x} ${p2.y} Z`;
-    } // Function chord()
-
-    /**
-     * 绘制椭圆饼
-     *
-     * @param   x               椭圆所在矩形X坐标
-     * @param   y               椭圆所在矩形Y坐标
-     * @param   width           椭圆所在矩形宽度
-     * @param   height          椭圆所在矩形高度
-     * @param   startAngle      开始角度(单位弧度)
-     * @param   endAngle        结束角度(单位弧度)
-     */
-    static pie(
-        x: number,
-        y: number,
-        width: number,
-        height: number,
-        startAngle: number,
-        endAngle: number
-    ): string {
-        let a = width / 2;
-        let b = height / 2;
-        let p1 = SPath2D.arcPoint(a, b, startAngle);
-        let p2 = SPath2D.arcPoint(a, b, endAngle);
-        let large = SPath2D.largeArcFlag(startAngle, endAngle);
-        p1.x = x + a + p1.x;
-        p1.y = y + b - p1.y;
-        p2.x = x + a + p2.x;
-        p2.y = y + b - p2.y;
-        return `M ${x + a} ${y + b} L ${p1.x} ${
-            p1.y
-        } A ${a} ${b} 0 ${large} 0 ${p2.x} ${p2.y} Z`;
-    } // Function pie()
-
-    /**
-     * 计算大弧标志
-     *
-     * @param   startAngle      启动角度(单位弧度)
-     * @param   endAngle        结束角度(单位弧度)
-     */
-    static largeArcFlag(startAngle: number, endAngle: number): number {
-        return ((Math.abs(endAngle - startAngle) * 180) / Math.PI) % 360 >
-            179.99999
-            ? 1
-            : 0;
-    } // Function largeArcFlag()
-
-    // https://blog.csdn.net/xiamentingtao/article/details/85804823
-    static arcPoint(a: number, b: number, angle: number): SPoint {
-        let p = new SPoint();
-        if (angle >= 0) {
-            angle = angle - Math.floor(angle / Math.PI / 2) * 2 * Math.PI;
-        } else {
-            angle = angle + Math.ceil(-angle / Math.PI / 2) * 2 * Math.PI;
-        }
-        if (Math.abs(Math.PI / 2 - angle) <= 0.000001) {
-            p.x = 0;
-            p.y = b;
-        } else if (Math.abs((Math.PI * 3) / 2 - angle) <= 0.000001) {
-            p.x = 0;
-            p.y = -b;
-        } else if (Math.PI / 2 < angle && angle < (Math.PI * 3) / 2) {
-            p.x =
-                -(a * b) /
-                Math.sqrt(b * b + a * a * Math.tan(angle) * Math.tan(angle));
-            p.y =
-                -(a * b * Math.tan(angle)) /
-                Math.sqrt(b * b + a * a * Math.tan(angle) * Math.tan(angle));
-        } else {
-            p.x =
-                (a * b) /
-                Math.sqrt(b * b + a * a * Math.tan(angle) * Math.tan(angle));
-            p.y =
-                (a * b * Math.tan(angle)) /
-                Math.sqrt(b * b + a * a * Math.tan(angle) * Math.tan(angle));
-        }
-        return p;
-    } // Function arcPoint()
-} // Class SPath2D

+ 37 - 0
saga-web-draw/src/SPathCommand.ts

@@ -0,0 +1,37 @@
+/*
+ * *********************************************************************************************************************
+ *
+ *          !!
+ *        .F88X
+ *        X8888Y
+ *      .}888888N;
+ *        i888888N;        .:!              .I$WI:
+ *          R888888I      .'N88~            i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
+ *          .R888888I    .;N8888~          .X8'  "8I.!,/8"  !%NY8`"8I8~~8>,88I
+ *            +888888N;  .8888888Y                                  "&&8Y.}8,
+ *            ./888888N;  .R888888Y        .'}~    .>}'.`+>  i}!    "i'  +/'  .'i~  !11,.:">,  .~]!  .i}i
+ *              ~888888%:  .I888888l      .]88~`1/iY88Ii+1'.R$8$8]"888888888>  Y8$  W8E  X8E  W8888'188Il}Y88$*
+ *              18888888    E8888881    .]W%8$`R8X'&8%++N8i,8N%N8+l8%`  .}8N:.R$RE%N88N%N$K$R  188,FE$8%~Y88I
+ *            .E888888I  .i8888888'      .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
+ *            8888888I  .,N888888~        ~88i"8W,!N8*.I88.}888%F,i$88"F88"  888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
+ *          i888888N'      I888Y          ]88;/EX*IFKFK88X  K8R  .l8W  88Y  ~88}'88E&%8W.X8N``]88!.$8K  .:W8I
+ *        .i888888N;        I8Y          .&8$  .X88!  i881.:%888>I88  ;88]  +88+.';;;;:.Y88X  18N.,88l  .+88/
+ *      .:R888888I
+ *      .&888888I                                          Copyright (c) 2009-2020.  博锐尚格科技股份有限公司
+ *        ~8888'
+ *        .!88~                                                                     All rights reserved.
+ *
+ * *********************************************************************************************************************
+ */
+
+/**
+ *  路径命令接口
+ *
+ *  @author 庞利祥 <sybotan@126.com>
+ */
+export interface SPathCommand {
+    /** 命令 */
+    command: string;
+    /** 参数 */
+    args: number[];
+}

+ 318 - 276
saga-web-draw/src/engines/SCanvasPaintEngine.ts

@@ -1,3 +1,29 @@
+/*
+ * *********************************************************************************************************************
+ *
+ *          !!
+ *        .F88X
+ *        X8888Y
+ *      .}888888N;
+ *        i888888N;        .:!              .I$WI:
+ *          R888888I      .'N88~            i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
+ *          .R888888I    .;N8888~          .X8'  "8I.!,/8"  !%NY8`"8I8~~8>,88I
+ *            +888888N;  .8888888Y                                  "&&8Y.}8,
+ *            ./888888N;  .R888888Y        .'}~    .>}'.`+>  i}!    "i'  +/'  .'i~  !11,.:">,  .~]!  .i}i
+ *              ~888888%:  .I888888l      .]88~`1/iY88Ii+1'.R$8$8]"888888888>  Y8$  W8E  X8E  W8888'188Il}Y88$*
+ *              18888888    E8888881    .]W%8$`R8X'&8%++N8i,8N%N8+l8%`  .}8N:.R$RE%N88N%N$K$R  188,FE$8%~Y88I
+ *            .E888888I  .i8888888'      .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
+ *            8888888I  .,N888888~        ~88i"8W,!N8*.I88.}888%F,i$88"F88"  888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
+ *          i888888N'      I888Y          ]88;/EX*IFKFK88X  K8R  .l8W  88Y  ~88}'88E&%8W.X8N``]88!.$8K  .:W8I
+ *        .i888888N;        I8Y          .&8$  .X88!  i881.:%888>I88  ;88]  +88+.';;;;:.Y88X  18N.,88l  .+88/
+ *      .:R888888I
+ *      .&888888I                                          Copyright (c) 2009-2020.  博锐尚格科技股份有限公司
+ *        ~8888'
+ *        .!88~                                                                     All rights reserved.
+ *
+ * *********************************************************************************************************************
+ */
+
 import { SPaintEngine } from "./SPaintEngine";
 import { SPaintEngine } from "./SPaintEngine";
 import {
 import {
     SBrushType,
     SBrushType,
@@ -14,17 +40,17 @@ import {
     STextBaseLine,
     STextBaseLine,
     STextDirection
     STextDirection
 } from "..";
 } from "..";
-import { SPath2D } from "../SPath2D";
+import { SPath } from "../SPath";
 
 
 /**
 /**
- * Canvas绘制引擎基类
+ * Canvas 绘制引擎基类
  *
  *
- * @author  庞利祥(sybotan@126.com)
+ * @author 庞利祥 <sybotan@126.com>
  */
  */
 export class SCanvasPaintEngine extends SPaintEngine {
 export class SCanvasPaintEngine extends SPaintEngine {
-    /** 画布对象    */
+    /** 画布对象 */
     private readonly _canvas: CanvasRenderingContext2D;
     private readonly _canvas: CanvasRenderingContext2D;
-    /** 融合类型    */
+    /** 融合类型 */
     static gcoList = [
     static gcoList = [
         "copy",
         "copy",
         "destination-atop",
         "destination-atop",
@@ -43,214 +69,103 @@ export class SCanvasPaintEngine extends SPaintEngine {
     /**
     /**
      * 绘制引擎类型
      * 绘制引擎类型
      *
      *
-     * @return  返回Canvas绘制引擎类型
+     * @return 返回 Canvas 绘制引擎类型
      */
      */
     get type(): SPaintEngineType {
     get type(): SPaintEngineType {
         return SPaintEngineType.Canvas;
         return SPaintEngineType.Canvas;
-    } // Get type
+    }
 
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // 构造函数
     // 构造函数
     /**
     /**
      * 构造函数
      * 构造函数
      *
      *
-     * @param   canvas      canvas对象
+     * @param canvas    canvas对象
      */
      */
     constructor(canvas: CanvasRenderingContext2D) {
     constructor(canvas: CanvasRenderingContext2D) {
         super();
         super();
         this._canvas = canvas;
         this._canvas = canvas;
         this._canvas.imageSmoothingEnabled = true;
         this._canvas.imageSmoothingEnabled = true;
-        // this._canvas.imageSmoothingQuality;
-    } // Constructor()
+    }
 
 
     // =================================================================================================================
     // =================================================================================================================
     // 绘制图形
     // 绘制图形
-    /**
-     * 设置裁剪路径
-     *
-     * @param   path        裁剪路径
-     */
-    setClip(path: Path2D): void {
-        this.setMatrix();
-        // this._canvas.stroke(path);
-        this._canvas.fill(path);
-        this._canvas.clip();
-    } // Function setClip()
 
 
     /**
     /**
      * 清空矩形区域
      * 清空矩形区域
      *
      *
-     * @param   rect        矩形
+     * @param rect  矩形
      */
      */
     clearRect(rect: SRect): void {
     clearRect(rect: SRect): void {
         this.setMatrix();
         this.setMatrix();
         this._canvas.clearRect(rect.x, rect.y, rect.width, rect.height);
         this._canvas.clearRect(rect.x, rect.y, rect.width, rect.height);
-    } // Function clearRect()
+    }
 
 
     /**
     /**
-     * 绘制空心矩形
+     * 绘制矩形
      *
      *
-     * @param   rect        矩形
+     * @param rect  矩形
      */
      */
     drawRect(rect: SRect): void {
     drawRect(rect: SRect): void {
-        this.setMatrix();
-        this.setPen();
-        this.setBrush();
-        this.setComposite();
-        this.setShadow();
-        this._canvas.fillRect(rect.x, rect.y, rect.width, rect.height);
-        this._canvas.strokeRect(rect.x, rect.y, rect.width, rect.height);
-    } // Function drawRect()
+        this.init((): void => {
+            this._canvas.beginPath();
+            this._canvas.rect(rect.x, rect.y, rect.width, rect.height);
+            this._canvas.stroke();
+            this._canvas.fill();
+        });
+    }
 
 
     /**
     /**
      * 绘制圆形
      * 绘制圆形
      *
      *
-     * @param   cx          圆心X坐标
-     * @param   cy          圆心X坐标
-     * @param   r           圆半径
+     * @param cx    圆心 x 坐标
+     * @param cy    圆心 y 坐标
+     * @param r     圆半径
      */
      */
     drawCircle(cx: number, cy: number, r: number): void {
     drawCircle(cx: number, cy: number, r: number): void {
-        this.setMatrix();
-        this.setPen();
-        this.setBrush();
-        this.setComposite();
-        this.setShadow();
-        this._canvas.beginPath();
-        this._canvas.arc(cx, cy, r, 0, 2 * Math.PI, true);
-        this._canvas.fill();
-        this._canvas.stroke();
-    } // Function drawCircle()
+        this.init((): void => {
+            this._canvas.beginPath();
+            this._canvas.arc(cx, cy, r, 0, 2 * Math.PI, true);
+            this._canvas.fill();
+            this._canvas.stroke();
+        });
+    }
 
 
     /**
     /**
      * 绘制椭圆
      * 绘制椭圆
      *
      *
-     * @param   cx          圆点X坐标
-     * @param   cy          圆点Y坐标
-     * @param   rx          水平半径
-     * @param   ry          垂直半径
+     * @param cx    圆点 X 坐标
+     * @param cy    圆点 Y 坐标
+     * @param rx    水平半径
+     * @param ry    垂直半径
      */
      */
     drawEllipse(cx: number, cy: number, rx: number, ry: number): void {
     drawEllipse(cx: number, cy: number, rx: number, ry: number): void {
-        this.setMatrix();
-        this.setPen();
-        this.setBrush();
-        this.setComposite();
-        this.setShadow();
-        this._canvas.beginPath();
-        this._canvas.ellipse(cx, cy, rx, ry, 0.5, 0, 2 * Math.PI, true);
-    } // Function drawEllipse()
-
-    /**
-     * 绘制椭圆弧
-     *
-     * @param   x               椭圆所在矩形X坐标
-     * @param   y               椭圆所在矩形Y坐标
-     * @param   width           椭圆所在矩形宽度
-     * @param   height          椭圆所在矩形高度
-     * @param   startAngle      开始角度(单位弧度)
-     * @param   endAngle        结束角度(单位弧度)
-     */
-    drawArc(
-        x: number,
-        y: number,
-        width: number,
-        height: number,
-        startAngle: number,
-        endAngle: number
-    ): void {
-        this.setMatrix();
-        this.setPen();
-        this.setBrush();
-        this.setComposite();
-        this.setShadow();
-        let p = SPath2D.arc(x, y, width, height, startAngle, endAngle);
-        let path = new Path2D(
-            SPath2D.arc(x, y, width, height, startAngle, endAngle)
-        );
-        this._canvas.stroke(path);
-    } // Function drawArc()
-
-    /**
-     * 绘制椭圆弦弧
-     *
-     * @param   x               椭圆所在矩形X坐标
-     * @param   y               椭圆所在矩形Y坐标
-     * @param   width           椭圆所在矩形宽度
-     * @param   height          椭圆所在矩形高度
-     * @param   startAngle      开始角度(单位弧度)
-     * @param   endAngle        结束角度(单位弧度)
-     */
-    drawChord(
-        x: number,
-        y: number,
-        width: number,
-        height: number,
-        startAngle: number,
-        endAngle: number
-    ): void {
-        this.setMatrix();
-        this.setPen();
-        this.setBrush();
-        this.setComposite();
-        this.setShadow();
-        let path = new Path2D(
-            SPath2D.chord(x, y, width, height, startAngle, endAngle)
-        );
-
-        this._canvas.fill(path);
-        this._canvas.stroke(path);
-    } // Function drawChord()
-
-    /**
-     * 绘制椭圆饼
-     *
-     * @param   x               椭圆所在矩形X坐标
-     * @param   y               椭圆所在矩形Y坐标
-     * @param   width           椭圆所在矩形宽度
-     * @param   height          椭圆所在矩形高度
-     * @param   startAngle      开始角度(单位弧度)
-     * @param   endAngle        结束角度(单位弧度)
-     */
-    drawPie(
-        x: number,
-        y: number,
-        width: number,
-        height: number,
-        startAngle: number,
-        endAngle: number
-    ): void {
-        this.setMatrix();
-        this.setPen();
-        this.setBrush();
-        this.setComposite();
-        this.setShadow();
-        let path = new Path2D(
-            SPath2D.pie(x, y, width, height, startAngle, endAngle)
-        );
-        this._canvas.fill(path);
-        this._canvas.stroke(path);
-    } // Function drawPie()
+        this.init((): void => {
+            this._canvas.beginPath();
+            this._canvas.ellipse(cx, cy, rx, ry, 0, 0, 2 * Math.PI, true);
+            this._canvas.fill();
+            this._canvas.stroke();
+        });
+    }
 
 
     /**
     /**
      * 绘制线段
      * 绘制线段
      *
      *
-     * @param   line        线段
+     * @param line  线段
      */
      */
     drawLine(line: SLine): void {
     drawLine(line: SLine): void {
-        this.setMatrix();
-        this.setPen();
-        this.setBrush();
-        this.setComposite();
-        this.setShadow();
-        this._canvas.beginPath();
-        this._canvas.moveTo(line.x1, line.y1);
-        this._canvas.lineTo(line.x2, line.y2);
-        this._canvas.stroke();
-    } // Function drawLine()
+        this.init((): void => {
+            this._canvas.beginPath();
+            this._canvas.moveTo(line.x1, line.y1);
+            this._canvas.lineTo(line.x2, line.y2);
+            this._canvas.stroke();
+        });
+    }
 
 
     /**
     /**
      * 绘制折线
      * 绘制折线
      *
      *
-     * @param   points      折线折点
+     * @param points    折线折点
      */
      */
     drawPolyline(points: SPoint[]): void {
     drawPolyline(points: SPoint[]): void {
         // 折线至少要有2个节点
         // 折线至少要有2个节点
@@ -258,25 +173,20 @@ export class SCanvasPaintEngine extends SPaintEngine {
             return;
             return;
         }
         }
 
 
-        this.setMatrix();
-        this.setPen();
-        this.setBrush();
-        this.setComposite();
-        this.setShadow();
-
-        this._canvas.beginPath();
-        this._canvas.moveTo(points[0].x, points[0].y);
-        for (let p of points) {
-            this._canvas.lineTo(p.x, p.y);
-        }
-
-        this._canvas.stroke();
-    } // Function drawPolyline()
+        this.init((): void => {
+            this._canvas.beginPath();
+            this._canvas.moveTo(points[0].x, points[0].y);
+            for (let p of points) {
+                this._canvas.lineTo(p.x, p.y);
+            }
+            this._canvas.stroke();
+        });
+    }
 
 
     /**
     /**
      * 绘制多边形
      * 绘制多边形
      *
      *
-     * @param   points      多边形顶点
+     * @param points    多边形顶点
      */
      */
     drawPolygon(points: SPoint[]): void {
     drawPolygon(points: SPoint[]): void {
         // 多边形至少要有3个节点
         // 多边形至少要有3个节点
@@ -284,68 +194,57 @@ export class SCanvasPaintEngine extends SPaintEngine {
             return;
             return;
         }
         }
 
 
-        this.setMatrix();
-        this.setPen();
-        this.setBrush();
-        this.setComposite();
-        this.setShadow();
-
-        this._canvas.beginPath();
-        this._canvas.moveTo(points[0].x, points[0].y);
-        for (let p of points) {
-            this._canvas.lineTo(p.x, p.y);
-        }
-        this._canvas.closePath();
+        this.init((): void => {
+            this._canvas.beginPath();
+            this._canvas.moveTo(points[0].x, points[0].y);
+            for (let p of points) {
+                this._canvas.lineTo(p.x, p.y);
+            }
+            this._canvas.closePath();
 
 
-        this._canvas.fill();
-        this._canvas.stroke();
-    } // Function drawPolygon()
+            this._canvas.fill();
+            this._canvas.stroke();
+        });
+    }
 
 
     /**
     /**
      * 绘制路径
      * 绘制路径
      *
      *
-     * @param   path        路径
+     * @param path  路径
      */
      */
-    drawPath(path: SPath2D): void {
-        this.setMatrix();
-        this.setPen();
-        this.setBrush();
-        this.setComposite();
-        this.setShadow();
-
-        this._canvas.fill(path._path);
-        this._canvas.stroke(path._path);
-    } // Function drawPath()
+    drawPath(path: SPath): void {
+        this.init((): void => {
+            this.drawWay(path);
+        });
+    }
 
 
     /**
     /**
      * 绘制文本
      * 绘制文本
      *
      *
-     * @param   text        文本内容
-     * @param   x           X坐标
-     * @param   y           Y坐标
-     * @param   maxWidth    最大宽度
+     * @param text      文本内容
+     * @param x         X 坐标
+     * @param y         Y 坐标
+     * @param maxWidth  最大宽度
      */
      */
     drawText(text: string, x: number, y: number, maxWidth?: number): void {
     drawText(text: string, x: number, y: number, maxWidth?: number): void {
-        this.setMatrix();
-        this.setPen();
-        this.setBrush();
-        this.setFont();
-        this.setComposite();
-        this.setShadow();
-
-        if (maxWidth == undefined) {
-            this._canvas.fillText(text, x, y);
-        } else {
-            this._canvas.fillText(text, x, y, maxWidth);
-        }
-    } // Function drawText()
+        this.init((): void => {
+            this.setFont();
+            if (maxWidth == undefined) {
+                this._canvas.strokeText(text, x, y);
+                this._canvas.fillText(text, x, y);
+            } else {
+                this._canvas.strokeText(text, x, y);
+                this._canvas.fillText(text, x, y, maxWidth);
+            }
+        });
+    }
 
 
     /**
     /**
      * 绘制图片
      * 绘制图片
      *
      *
      * @param img       图片
      * @param img       图片
-     * @param x         X坐标
-     * @param y         Y坐标
+     * @param x         X 坐标
+     * @param y         Y 坐标
      * @param width     宽度
      * @param width     宽度
      * @param height    高度
      * @param height    高度
      */
      */
@@ -356,66 +255,131 @@ export class SCanvasPaintEngine extends SPaintEngine {
         width?: number,
         width?: number,
         height?: number
         height?: number
     ): void {
     ): void {
-        this.setMatrix();
-        try {
-            if (width == undefined) {
-                this._canvas.drawImage(img, x, y);
-            } else {
-                this._canvas.drawImage(img, x, y, width, height as number);
+        this.init((): void => {
+            try {
+                if (width == undefined) {
+                    this._canvas.drawImage(img, x, y);
+                } else {
+                    this._canvas.drawImage(img, x, y, width, height as number);
+                }
+            } catch (e) {
+                console.log(e);
             }
             }
-        } catch (e) {
-            console.log(e);
-        }
-    } // Function drawImage()
+        });
+    }
 
 
     /**
     /**
      * 预测量文本宽度
      * 预测量文本宽度
      *
      *
-     * @param   text    预测的文本
-     * @return  文本长度像素
-     * */
+     * @param text  预测的文本
+     * @return 文本长度像素
+     */
     textWidth(text: string): number {
     textWidth(text: string): number {
         return this._canvas.measureText(text).width;
         return this._canvas.measureText(text).width;
-    } // Function textWidth()
-
-    // /**
-    //  * 绘制带导角空心矩形
-    //  *
-    //  * @param   x           X坐标
-    //  * @param   y           Y坐标
-    //  * @param   w           宽度
-    //  * @param   h           高度
-    //  * @param   r           导角半径
-    //  */
-    // drawRoundedRect(x: number, y: number, w: number, h: number, r: number): void {
-    //     this.canvas.beginPath();
-    //     this.canvas.moveTo(x, y + r);
-    //     this.canvas.lineTo(x, y + h - r);
-    //     this.canvas.quadraticCurveTo(x, y + h, x + r, y + h);
-    //     this.canvas.lineTo(x + w - r,y + h);
-    //     this.canvas.quadraticCurveTo(x + w, y + h, x + w, y + h - r);
-    //     this.canvas.lineTo(x + w, y + r);
-    //     this.canvas.quadraticCurveTo(x + w, y, x + w - r, y);
-    //     this.canvas.lineTo(x + r, y);
-    //     this.canvas.quadraticCurveTo(x, y, x,y + r);
-    //     this.canvas.fill();
-    //     this.canvas.stroke();
-    // } // Function drawRoundedRect()
+    }
+
+    /**
+     * 绘制二次贝塞尔曲线
+     *
+     * @param cp1x    控制点 X 坐标
+     * @param cp1y    控制点 Y 坐标
+     * @param x       结束点 X 坐标
+     * @param y       结束点 Y 坐标
+     */
+    quadraticCurveTo(cp1x: number, cp1y: number, x: number, y: number): void {
+        this._canvas.quadraticCurveTo(cp1x, cp1y, x, y);
+    }
+
+    /**
+     * 绘制三次贝塞尔曲线
+     *
+     * @param cp1x    起始点控制点 X 坐标
+     * @param cp1y    起始点控制点 Y 坐标
+     * @param cp2x    结束点控制点 X 坐标
+     * @param cp2y    结束点控制点 Y 坐标
+     * @param x       结束点X坐标
+     * @param y       结束点Y坐标
+     */
+    bezierCurveTo(
+        cp1x: number,
+        cp1y: number,
+        cp2x: number,
+        cp2y: number,
+        x: number,
+        y: number
+    ): void {
+        this._canvas.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
+    }
+
+    /**
+     * 绘制带导角空心矩形
+     *
+     * @param rect    矩形
+     * @param r       导角半径
+     */
+    drawRoundRect(rect: SRect, r: number): void {
+        this.init((): void => {
+            this._canvas.beginPath();
+            this._canvas.moveTo(rect.x, rect.y + r);
+            this._canvas.lineTo(rect.x, rect.bottom - r);
+            this._canvas.quadraticCurveTo(
+                rect.x,
+                rect.bottom,
+                rect.x + r,
+                rect.bottom
+            );
+            this._canvas.lineTo(rect.right - r, rect.bottom);
+            this._canvas.quadraticCurveTo(
+                rect.right,
+                rect.bottom,
+                rect.right,
+                rect.bottom - r
+            );
+            this._canvas.lineTo(rect.right, rect.y + r);
+            this._canvas.quadraticCurveTo(
+                rect.right,
+                rect.y,
+                rect.right - r,
+                rect.y
+            );
+            this._canvas.lineTo(rect.x + r, rect.y);
+            this._canvas.quadraticCurveTo(rect.x, rect.y, rect.x, rect.y + r);
+            this._canvas.fill();
+            this._canvas.stroke();
+        });
+    }
 
 
     /**
     /**
      * 设置字体
      * 设置字体
      *
      *
-     * @param   font    字体
+     * @param font  字体
      */
      */
     changeFont(font: SFont): void {
     changeFont(font: SFont): void {
         this._canvas.font = `${font.size}px ${font.name}`;
         this._canvas.font = `${font.size}px ${font.name}`;
         this.setTextAlign(font.textAlign);
         this.setTextAlign(font.textAlign);
         this.setBaseLine(font.textBaseLine);
         this.setBaseLine(font.textBaseLine);
         this.setTextDirection(font.textDirection);
         this.setTextDirection(font.textDirection);
-    } // Function changeFont()
+    }
 
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // 私有函数
     // 私有函数
+
+    /**
+     * 设置整体绘制状态
+     *
+     * @param fn    绘制图形的具体函数
+     */
+    private init(fn: Function): void {
+        this.setMatrix();
+        this.setPen();
+        this.setBrush();
+        this.setComposite();
+        this.setShadow();
+        this.setClip();
+        this.setGlobalAlpha();
+        fn();
+    }
+
     /**
     /**
      * 设置画笔
      * 设置画笔
      */
      */
@@ -438,12 +402,12 @@ export class SCanvasPaintEngine extends SPaintEngine {
         }
         }
 
 
         this.setLineCapStyle(this.state.pen.lineCapStyle);
         this.setLineCapStyle(this.state.pen.lineCapStyle);
-    } // Function setPen()
+    }
 
 
     /**
     /**
      * 线段端点风格
      * 线段端点风格
      *
      *
-     * @param   style       风格
+     * @param style     风格
      */
      */
     private setLineCapStyle(style: SLineCapStyle): void {
     private setLineCapStyle(style: SLineCapStyle): void {
         if (style == undefined) return;
         if (style == undefined) return;
@@ -454,7 +418,7 @@ export class SCanvasPaintEngine extends SPaintEngine {
         } else {
         } else {
             this._canvas.lineCap = "butt";
             this._canvas.lineCap = "butt";
         }
         }
-    } // Set lineCapStyle
+    }
 
 
     /**
     /**
      * 设置画刷
      * 设置画刷
@@ -499,7 +463,7 @@ export class SCanvasPaintEngine extends SPaintEngine {
                 this._canvas.fillStyle = drawGradient;
                 this._canvas.fillStyle = drawGradient;
             }
             }
         }
         }
-    } // Function setBrush()
+    }
 
 
     /**
     /**
      * 设置融合
      * 设置融合
@@ -507,7 +471,7 @@ export class SCanvasPaintEngine extends SPaintEngine {
     private setComposite(): void {
     private setComposite(): void {
         this._canvas.globalCompositeOperation =
         this._canvas.globalCompositeOperation =
             SCanvasPaintEngine.gcoList[this.state._composite];
             SCanvasPaintEngine.gcoList[this.state._composite];
-    } // Function setComposite()
+    }
 
 
     /**
     /**
      * 设置阴影
      * 设置阴影
@@ -528,7 +492,7 @@ export class SCanvasPaintEngine extends SPaintEngine {
             this._canvas.shadowOffsetX = 0;
             this._canvas.shadowOffsetX = 0;
             this._canvas.shadowOffsetY = 0;
             this._canvas.shadowOffsetY = 0;
         }
         }
-    } // Function setShadow()
+    }
 
 
     /**
     /**
      * 设置字体
      * 设置字体
@@ -538,12 +502,12 @@ export class SCanvasPaintEngine extends SPaintEngine {
         this.setTextAlign(this.state.font.textAlign);
         this.setTextAlign(this.state.font.textAlign);
         this.setBaseLine(this.state.font.textBaseLine);
         this.setBaseLine(this.state.font.textBaseLine);
         this.setTextDirection(this.state.font.textDirection);
         this.setTextDirection(this.state.font.textDirection);
-    } // Function setFont()
+    }
 
 
     /**
     /**
      * 文本对齐选项
      * 文本对齐选项
      *
      *
-     * @param   value       对齐方式
+     * @param value     对齐方式
      */
      */
     private setTextAlign(value: STextAlign): void {
     private setTextAlign(value: STextAlign): void {
         if (value == undefined) {
         if (value == undefined) {
@@ -560,12 +524,12 @@ export class SCanvasPaintEngine extends SPaintEngine {
         } else {
         } else {
             this._canvas.textAlign = "right";
             this._canvas.textAlign = "right";
         }
         }
-    } // Function setTextAlign()
+    }
 
 
     /**
     /**
      * 设置文本基线对齐选项
      * 设置文本基线对齐选项
      *
      *
-     * @param   value       对齐方式
+     * @param value     对齐方式
      */
      */
     private setBaseLine(value: STextBaseLine): void {
     private setBaseLine(value: STextBaseLine): void {
         if (value == undefined) {
         if (value == undefined) {
@@ -584,12 +548,12 @@ export class SCanvasPaintEngine extends SPaintEngine {
         } else {
         } else {
             this._canvas.textBaseline = "bottom";
             this._canvas.textBaseline = "bottom";
         }
         }
-    } // Set textBaseLine()
+    }
 
 
     /**
     /**
      * 设置文本方向选项
      * 设置文本方向选项
      *
      *
-     * @param   value       文本方向
+     * @param value     文本方向
      */
      */
     private setTextDirection(value: STextDirection): void {
     private setTextDirection(value: STextDirection): void {
         if (value == undefined) {
         if (value == undefined) {
@@ -602,7 +566,7 @@ export class SCanvasPaintEngine extends SPaintEngine {
         } else {
         } else {
             this._canvas.direction = "rtl";
             this._canvas.direction = "rtl";
         }
         }
-    } // Set textDirection
+    }
 
 
     /**
     /**
      * 设置变型矩阵
      * 设置变型矩阵
@@ -616,5 +580,83 @@ export class SCanvasPaintEngine extends SPaintEngine {
             this.state.matrix.e,
             this.state.matrix.e,
             this.state.matrix.f
             this.state.matrix.f
         );
         );
-    } // Function setMatrix()
-} // class SPaintEngine
+    }
+
+    /**
+     * 设置裁剪路径
+     */
+    setClip(): void {
+        if (this.state.clip) {
+            this.drawWay(this.state.clip);
+            this._canvas.clip();
+        }
+    }
+
+    /**
+     * 绘制路径
+     */
+    private drawWay(path: SPath): void {
+        this._canvas.beginPath();
+        path.cmdList.forEach((cmd): void => {
+            if (cmd.command == "L") {
+                this._canvas.lineTo(cmd.args[0], cmd.args[1]);
+            } else if (cmd.command == "M") {
+                this._canvas.moveTo(cmd.args[0], cmd.args[1]);
+            } else if (cmd.command == "Z") {
+                this._canvas.closePath();
+            } else if (cmd.command == "Q") {
+                this._canvas.quadraticCurveTo(
+                    cmd.args[0],
+                    cmd.args[1],
+                    cmd.args[2],
+                    cmd.args[3]
+                );
+            } else if (cmd.command == "T") {
+                // @ts-ignore
+                this._canvas.bezierCurveTo(
+                    cmd.args[0],
+                    cmd.args[1],
+                    cmd.args[2],
+                    cmd.args[3],
+                    cmd.args[4]
+                );
+            } else if (cmd.command == "Ellipse") {
+                this._canvas.ellipse(
+                    cmd.args[0],
+                    cmd.args[1],
+                    cmd.args[2],
+                    cmd.args[3],
+                    0,
+                    0,
+                    Math.PI * 2
+                );
+            } else if (cmd.command == "Arc") {
+                this._canvas.arc(
+                    cmd.args[0],
+                    cmd.args[1],
+                    cmd.args[2],
+                    cmd.args[3],
+                    cmd.args[4],
+                    cmd.args[5] == 1
+                );
+            } else if (cmd.command == "ArcTo") {
+                this._canvas.arcTo(
+                    cmd.args[0],
+                    cmd.args[1],
+                    cmd.args[2],
+                    cmd.args[3],
+                    cmd.args[4]
+                );
+            }
+        });
+        this._canvas.fill();
+        this._canvas.stroke();
+    }
+
+    /**
+     * 设置绘制透明度
+     */
+    private setGlobalAlpha(): void {
+        this._canvas.globalAlpha = this.state.globalAlpha;
+    }
+}

+ 92 - 121
saga-web-draw/src/engines/SPaintEngine.ts

@@ -1,21 +1,47 @@
-import { SFont, SLine, SPaintEngineType, SPath2D, SPoint, SRect } from "..";
+/*
+ * *********************************************************************************************************************
+ *
+ *          !!
+ *        .F88X
+ *        X8888Y
+ *      .}888888N;
+ *        i888888N;        .:!              .I$WI:
+ *          R888888I      .'N88~            i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
+ *          .R888888I    .;N8888~          .X8'  "8I.!,/8"  !%NY8`"8I8~~8>,88I
+ *            +888888N;  .8888888Y                                  "&&8Y.}8,
+ *            ./888888N;  .R888888Y        .'}~    .>}'.`+>  i}!    "i'  +/'  .'i~  !11,.:">,  .~]!  .i}i
+ *              ~888888%:  .I888888l      .]88~`1/iY88Ii+1'.R$8$8]"888888888>  Y8$  W8E  X8E  W8888'188Il}Y88$*
+ *              18888888    E8888881    .]W%8$`R8X'&8%++N8i,8N%N8+l8%`  .}8N:.R$RE%N88N%N$K$R  188,FE$8%~Y88I
+ *            .E888888I  .i8888888'      .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
+ *            8888888I  .,N888888~        ~88i"8W,!N8*.I88.}888%F,i$88"F88"  888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
+ *          i888888N'      I888Y          ]88;/EX*IFKFK88X  K8R  .l8W  88Y  ~88}'88E&%8W.X8N``]88!.$8K  .:W8I
+ *        .i888888N;        I8Y          .&8$  .X88!  i881.:%888>I88  ;88]  +88+.';;;;:.Y88X  18N.,88l  .+88/
+ *      .:R888888I
+ *      .&888888I                                          Copyright (c) 2009-2020.  博锐尚格科技股份有限公司
+ *        ~8888'
+ *        .!88~                                                                     All rights reserved.
+ *
+ * *********************************************************************************************************************
+ */
+
+import { SFont, SLine, SPaintEngineType, SPath, SPoint, SRect } from "..";
 import { SPaintState } from "./SPaintState";
 import { SPaintState } from "./SPaintState";
-import { SMatrix } from "@saga-web/base/lib";
+import { SMatrix } from "@saga-web/base";
 
 
 /**
 /**
  * 绘制引擎基类
  * 绘制引擎基类
  *
  *
- * @author  庞利祥(sybotan@126.com)
+ * @author 庞利祥 <sybotan@126.com>
  */
  */
 export abstract class SPaintEngine {
 export abstract class SPaintEngine {
     /** 当关状态 */
     /** 当关状态 */
     private _state = new SPaintState();
     private _state = new SPaintState();
     get state(): SPaintState {
     get state(): SPaintState {
         return this._state;
         return this._state;
-    } // Function state()
+    }
     set state(value: SPaintState) {
     set state(value: SPaintState) {
         this._state = value;
         this._state = value;
-    } // Function state()
+    }
 
 
     /** 状态栈 */
     /** 状态栈 */
     private stateStack = new Array<SPaintState>();
     private stateStack = new Array<SPaintState>();
@@ -24,62 +50,62 @@ export abstract class SPaintEngine {
     abstract get type(): SPaintEngineType;
     abstract get type(): SPaintEngineType;
 
 
     /**
     /**
-     * 保存painter状态
+     * 保存 painter 状态
      */
      */
     save(): void {
     save(): void {
         let state = new SPaintState(this.state);
         let state = new SPaintState(this.state);
         this.stateStack.push(state);
         this.stateStack.push(state);
-    } // Function save()
+    }
 
 
     /**
     /**
-     * 恢复painter状态
+     * 恢复 painter 状态
      */
      */
     restore(): void {
     restore(): void {
         if (this.stateStack.length > 0) {
         if (this.stateStack.length > 0) {
             this.state = this.stateStack.pop() as SPaintState;
             this.state = this.stateStack.pop() as SPaintState;
         }
         }
-    } // Function restore()
+    }
 
 
     // =================================================================================================================
     // =================================================================================================================
     // 变换相关
     // 变换相关
     /**
     /**
      * 平移变换
      * 平移变换
      *
      *
-     * @param   x       X轴方向平移
-     * @param   y       Y辆方向平移
+     * @param x     X 轴方向平移
+     * @param y     Y 辆方向平移
      */
      */
     translate(x: number, y: number): void {
     translate(x: number, y: number): void {
         this.state.matrix.translate(x, y);
         this.state.matrix.translate(x, y);
-    } // Function translate()
+    }
 
 
     /**
     /**
      * 缩放
      * 缩放
      *
      *
-     * @param   x       X轴方向缩放
-     * @param   y       Y辆方向缩放
+     * @param x     X 轴方向缩放
+     * @param y     Y 轴方向缩放
      */
      */
     scale(x: number, y: number): void {
     scale(x: number, y: number): void {
         this.state.matrix.scale(x, y);
         this.state.matrix.scale(x, y);
-    } // Function scale()
+    }
 
 
     /**
     /**
      * 旋转
      * 旋转
      *
      *
-     * @param   angle   旋转角度(单位弧度)
+     * @param angle     旋转角度(单位弧度)
      */
      */
     rotate(angle: number): void {
     rotate(angle: number): void {
         this.state.matrix.rotate(0, 0, angle);
         this.state.matrix.rotate(0, 0, angle);
-    } // Function rotate()
+    }
 
 
     /**
     /**
      * 将当前的变形矩阵乘上一个基于自身参数的矩阵
      * 将当前的变形矩阵乘上一个基于自身参数的矩阵
      *
      *
-     * @param   m11     水平方向的缩放
-     * @param   m12     水平方向的倾斜偏移
-     * @param   m21     竖直方向的倾斜偏移
-     * @param   m22     竖直方向的缩放
-     * @param   dx      水平方向的移动
-     * @param   dy      竖直方向的移动
+     * @param m11   水平方向的缩放
+     * @param m12   水平方向的倾斜偏移
+     * @param m21   竖直方向的倾斜偏移
+     * @param m22   竖直方向的缩放
+     * @param dx    水平方向的移动
+     * @param dy    竖直方向的移动
      */
      */
     transform(
     transform(
         m11: number,
         m11: number,
@@ -88,17 +114,17 @@ export abstract class SPaintEngine {
         m22: number,
         m22: number,
         dx: number,
         dx: number,
         dy: number
         dy: number
-    ): void {} // Function transform()
+    ): void {}
 
 
     /**
     /**
      * 将当前的变形矩阵重置为单位矩阵,再将当前的变形矩阵乘上一个基于自身参数的矩阵
      * 将当前的变形矩阵重置为单位矩阵,再将当前的变形矩阵乘上一个基于自身参数的矩阵
      *
      *
-     * @param   m11     水平方向的缩放
-     * @param   m12     水平方向的倾斜偏移
-     * @param   m21     竖直方向的倾斜偏移
-     * @param   m22     竖直方向的缩放
-     * @param   dx      水平方向的移动
-     * @param   dy      竖直方向的移动
+     * @param m11   水平方向的缩放
+     * @param m12   水平方向的倾斜偏移
+     * @param m21   竖直方向的倾斜偏移
+     * @param m22   竖直方向的缩放
+     * @param dx    水平方向的移动
+     * @param dy    竖直方向的移动
      */
      */
     setTransform(
     setTransform(
         m11: number,
         m11: number,
@@ -107,149 +133,86 @@ export abstract class SPaintEngine {
         m22: number,
         m22: number,
         dx: number,
         dx: number,
         dy: number
         dy: number
-    ): void {} // Function transform()
+    ): void {}
 
 
     /**
     /**
-     * 重置当前变形为单位矩阵。等价于调用setTransform(1, 0, 0, 1, 0, 0)
+     * 重置当前变形为单位矩阵。等价于调用 setTransform(1, 0, 0, 1, 0, 0)
      */
      */
     resetTransform(): void {
     resetTransform(): void {
         this.state.matrix = new SMatrix();
         this.state.matrix = new SMatrix();
-    } // Function resetTransform()
+    }
 
 
     // =================================================================================================================
     // =================================================================================================================
     // 绘制图形
     // 绘制图形
-    /**
-     * 设置裁剪路径
-     *
-     * @param   path        裁剪路径
-     */
-    abstract setClip(path: Path2D): void;
 
 
     /**
     /**
      * 清空矩形区域
      * 清空矩形区域
      *
      *
-     * @param   rect        矩形
+     * @param rect  矩形
      */
      */
     abstract clearRect(rect: SRect): void;
     abstract clearRect(rect: SRect): void;
 
 
     /**
     /**
      * 绘制空心矩形
      * 绘制空心矩形
      *
      *
-     * @param   rect        矩形
+     * @param rect  矩形
      */
      */
     abstract drawRect(rect: SRect): void;
     abstract drawRect(rect: SRect): void;
 
 
     /**
     /**
      * 绘制圆形
      * 绘制圆形
      *
      *
-     * @param   cx          圆心X坐标
-     * @param   cy          圆心X坐标
-     * @param   r           圆半径
+     * @param cx    圆心 X 坐标
+     * @param cy    圆心 Y 坐标
+     * @param r     圆半径
      */
      */
     abstract drawCircle(cx: number, cy: number, r: number): void;
     abstract drawCircle(cx: number, cy: number, r: number): void;
 
 
     /**
     /**
      * 绘制椭圆
      * 绘制椭圆
      *
      *
-     * @param   cx          圆点X坐标
-     * @param   cy          圆点Y坐标
-     * @param   rx          水平半径
-     * @param   ry          垂直半径
+     * @param cx    圆点 X 坐标
+     * @param cy    圆点 Y 坐标
+     * @param rx    水平半径
+     * @param ry    垂直半径
      */
      */
     abstract drawEllipse(cx: number, cy: number, rx: number, ry: number): void;
     abstract drawEllipse(cx: number, cy: number, rx: number, ry: number): void;
 
 
     /**
     /**
-     * 绘制椭圆弧
-     *
-     * @param   x               椭圆所在矩形X坐标
-     * @param   y               椭圆所在矩形Y坐标
-     * @param   width           椭圆所在矩形宽度
-     * @param   height          椭圆所在矩形高度
-     * @param   startRadian     开始角度(单位弧度)
-     * @param   endRadian       结束角度(单位弧度)
-     */
-    abstract drawArc(
-        x: number,
-        y: number,
-        width: number,
-        height: number,
-        startRadian: number,
-        endRadian: number
-    ): void;
-
-    /**
-     * 绘制椭圆弦弧
-     *
-     * @param   x               椭圆所在矩形X坐标
-     * @param   y               椭圆所在矩形Y坐标
-     * @param   width           椭圆所在矩形宽度
-     * @param   height          椭圆所在矩形高度
-     * @param   startRadian     开始角度(单位弧度)
-     * @param   endRadian       结束角度(单位弧度)
-     */
-    abstract drawChord(
-        x: number,
-        y: number,
-        width: number,
-        height: number,
-        startRadian: number,
-        endRadian: number
-    ): void;
-
-    /**
-     * 绘制椭圆饼
-     *
-     * @param   x               椭圆所在矩形X坐标
-     * @param   y               椭圆所在矩形Y坐标
-     * @param   width           椭圆所在矩形宽度
-     * @param   height          椭圆所在矩形高度
-     * @param   startAngle      开始角度(单位弧度)
-     * @param   endAngle        结束角度(单位弧度)
-     */
-    abstract drawPie(
-        x: number,
-        y: number,
-        width: number,
-        height: number,
-        startAngle: number,
-        endAngle: number
-    ): void;
-
-    /**
      * 绘制线段
      * 绘制线段
      *
      *
-     * @param   line        线段
+     * @param line  线段
      */
      */
     abstract drawLine(line: SLine): void;
     abstract drawLine(line: SLine): void;
 
 
     /**
     /**
      * 绘制折线
      * 绘制折线
      *
      *
-     * @param   points      折线折点
+     * @param points    折线折点
      */
      */
     abstract drawPolyline(points: SPoint[]): void;
     abstract drawPolyline(points: SPoint[]): void;
 
 
     /**
     /**
      * 绘制多边形
      * 绘制多边形
      *
      *
-     * @param   points      多边形顶点
+     * @param points    多边形顶点
      */
      */
     abstract drawPolygon(points: SPoint[]): void;
     abstract drawPolygon(points: SPoint[]): void;
 
 
     /**
     /**
      * 绘制路径
      * 绘制路径
      *
      *
-     * @param   path        路径
+     * @param path  路径
      */
      */
-    abstract drawPath(path: SPath2D): void;
+    abstract drawPath(path: SPath): void;
 
 
     /**
     /**
      * 绘制文本
      * 绘制文本
      *
      *
-     * @param   text        文本内容
-     * @param   x           X坐标
-     * @param   y           Y坐标
-     * @param   maxWidth    最大宽度
+     * @param text          文本内容
+     * @param x             X 坐标
+     * @param y             Y 坐标
+     * @param maxWidth      最大宽度
      */
      */
     abstract drawText(
     abstract drawText(
         text: string,
         text: string,
@@ -262,8 +225,8 @@ export abstract class SPaintEngine {
      * 绘制图片
      * 绘制图片
      *
      *
      * @param img       图片
      * @param img       图片
-     * @param x         X坐标
-     * @param y         Y坐标
+     * @param x         X 坐标
+     * @param y         Y 坐标
      * @param width     宽度
      * @param width     宽度
      * @param height    高度
      * @param height    高度
      */
      */
@@ -278,14 +241,22 @@ export abstract class SPaintEngine {
     /**
     /**
      * 预测量文本宽度
      * 预测量文本宽度
      *
      *
-     * @param   text    预测的文本
-     * */
+     * @param text  预测的文本
+     */
     abstract textWidth(text: string): number;
     abstract textWidth(text: string): number;
 
 
     /**
     /**
      * 修改字体
      * 修改字体
      *
      *
-     * @param   font    字体
-     * */
+     * @param font  字体
+     */
     abstract changeFont(font: SFont): void;
     abstract changeFont(font: SFont): void;
-} // class SPaintEngine
+
+    /**
+     * 绘制带导角空心矩形
+     *
+     * @param rect    矩形
+     * @param r       导角半径
+     */
+    abstract drawRoundRect(rect: SRect, r: number): void;
+}

+ 64 - 13
saga-web-draw/src/engines/SPaintState.ts

@@ -1,12 +1,38 @@
-import { SBrush, SFont, SPen } from "..";
-import { SCompositeType } from "../enums/SCompositeType";
+/*
+ * *********************************************************************************************************************
+ *
+ *          !!
+ *        .F88X
+ *        X8888Y
+ *      .}888888N;
+ *        i888888N;        .:!              .I$WI:
+ *          R888888I      .'N88~            i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
+ *          .R888888I    .;N8888~          .X8'  "8I.!,/8"  !%NY8`"8I8~~8>,88I
+ *            +888888N;  .8888888Y                                  "&&8Y.}8,
+ *            ./888888N;  .R888888Y        .'}~    .>}'.`+>  i}!    "i'  +/'  .'i~  !11,.:">,  .~]!  .i}i
+ *              ~888888%:  .I888888l      .]88~`1/iY88Ii+1'.R$8$8]"888888888>  Y8$  W8E  X8E  W8888'188Il}Y88$*
+ *              18888888    E8888881    .]W%8$`R8X'&8%++N8i,8N%N8+l8%`  .}8N:.R$RE%N88N%N$K$R  188,FE$8%~Y88I
+ *            .E888888I  .i8888888'      .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
+ *            8888888I  .,N888888~        ~88i"8W,!N8*.I88.}888%F,i$88"F88"  888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
+ *          i888888N'      I888Y          ]88;/EX*IFKFK88X  K8R  .l8W  88Y  ~88}'88E&%8W.X8N``]88!.$8K  .:W8I
+ *        .i888888N;        I8Y          .&8$  .X88!  i881.:%888>I88  ;88]  +88+.';;;;:.Y88X  18N.,88l  .+88/
+ *      .:R888888I
+ *      .&888888I                                          Copyright (c) 2009-2020.  博锐尚格科技股份有限公司
+ *        ~8888'
+ *        .!88~                                                                     All rights reserved.
+ *
+ * *********************************************************************************************************************
+ */
+
+import { SBrush, SFont, SPath, SPen } from "..";
+import { SCompositeType } from "..";
 import { SShadow } from "../SShadow";
 import { SShadow } from "../SShadow";
 import { SMatrix } from "@saga-web/base";
 import { SMatrix } from "@saga-web/base";
 
 
 /**
 /**
  * 绘制状态
  * 绘制状态
  *
  *
- * @author  庞利祥(sybotan@126.com)
+ * @author 庞利祥 <sybotan@126.com>
  */
  */
 export class SPaintState {
 export class SPaintState {
     /** 变换矩阵 */
     /** 变换矩阵 */
@@ -16,33 +42,33 @@ export class SPaintState {
     private _pen = new SPen();
     private _pen = new SPen();
     get pen(): SPen {
     get pen(): SPen {
         return this._pen;
         return this._pen;
-    } // Get pen
+    }
     set pen(value: SPen) {
     set pen(value: SPen) {
         this._pen = value;
         this._pen = value;
-    } // Set pen
+    }
 
 
     /** 画刷 */
     /** 画刷 */
     private _brush = new SBrush();
     private _brush = new SBrush();
     get brush(): SBrush {
     get brush(): SBrush {
         return this._brush;
         return this._brush;
-    } // Get brush
+    }
     set brush(value: SBrush) {
     set brush(value: SBrush) {
         this._brush = value;
         this._brush = value;
-    } // Set brush
+    }
 
 
     /** 字体 */
     /** 字体 */
     private _font = new SFont();
     private _font = new SFont();
     get font(): SFont {
     get font(): SFont {
         return this._font;
         return this._font;
-    } // Get font
+    }
     set font(value: SFont) {
     set font(value: SFont) {
         this._font = value;
         this._font = value;
-    } // Set font
+    }
 
 
     /** 融合 */
     /** 融合 */
     _composite = SCompositeType.SourceOver;
     _composite = SCompositeType.SourceOver;
 
 
-    /** 阴影效果    */
+    /** 阴影效果 */
     private _shadow: SShadow = new SShadow();
     private _shadow: SShadow = new SShadow();
     get shadow(): SShadow {
     get shadow(): SShadow {
         return this._shadow;
         return this._shadow;
@@ -51,10 +77,33 @@ export class SPaintState {
         this._shadow = v;
         this._shadow = v;
     }
     }
 
 
+    /** 裁剪 */
+    private _clip: SPath | undefined;
+    get clip(): SPath | undefined {
+        return this._clip;
+    }
+    set clip(v: SPath | undefined) {
+        if (v) {
+            this._clip = new SPath();
+            this._clip.addPath(v);
+        } else {
+            this._clip = v;
+        }
+    }
+
+    /** 透明度 */
+    private _globalAlpha: number = 1;
+    get globalAlpha(): number {
+        return this._globalAlpha;
+    }
+    set globalAlpha(v: number) {
+        this._globalAlpha = v;
+    }
+
     /**
     /**
      * 构造函数
      * 构造函数
      *
      *
-     * @param   state   绘制状态
+     * @param state     绘制状态
      */
      */
     constructor(state?: SPaintState) {
     constructor(state?: SPaintState) {
         if (state != undefined) {
         if (state != undefined) {
@@ -63,6 +112,8 @@ export class SPaintState {
             this.font = new SFont(state.font);
             this.font = new SFont(state.font);
             this._composite = state._composite;
             this._composite = state._composite;
             this.shadow = new SShadow(state.shadow);
             this.shadow = new SShadow(state.shadow);
+            this.clip = state.clip;
+            this.globalAlpha = state.globalAlpha;
             let m = new SMatrix();
             let m = new SMatrix();
             m.m11 = state.matrix.m11;
             m.m11 = state.matrix.m11;
             m.m12 = state.matrix.m12;
             m.m12 = state.matrix.m12;
@@ -82,5 +133,5 @@ export class SPaintState {
             m.m44 = state.matrix.m44;
             m.m44 = state.matrix.m44;
             this.matrix = m;
             this.matrix = m;
         }
         }
-    } // Constructor
-} // class SPaintState
+    }
+}

+ 95 - 163
saga-web-draw/src/engines/SSvgPaintEngine.ts

@@ -1,29 +1,52 @@
-import { SStringBuilder } from "@saga-web/base/lib";
-import { SPath2D } from "../SPath2D";
+/*
+ * *********************************************************************************************************************
+ *
+ *          !!
+ *        .F88X
+ *        X8888Y
+ *      .}888888N;
+ *        i888888N;        .:!              .I$WI:
+ *          R888888I      .'N88~            i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
+ *          .R888888I    .;N8888~          .X8'  "8I.!,/8"  !%NY8`"8I8~~8>,88I
+ *            +888888N;  .8888888Y                                  "&&8Y.}8,
+ *            ./888888N;  .R888888Y        .'}~    .>}'.`+>  i}!    "i'  +/'  .'i~  !11,.:">,  .~]!  .i}i
+ *              ~888888%:  .I888888l      .]88~`1/iY88Ii+1'.R$8$8]"888888888>  Y8$  W8E  X8E  W8888'188Il}Y88$*
+ *              18888888    E8888881    .]W%8$`R8X'&8%++N8i,8N%N8+l8%`  .}8N:.R$RE%N88N%N$K$R  188,FE$8%~Y88I
+ *            .E888888I  .i8888888'      .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
+ *            8888888I  .,N888888~        ~88i"8W,!N8*.I88.}888%F,i$88"F88"  888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
+ *          i888888N'      I888Y          ]88;/EX*IFKFK88X  K8R  .l8W  88Y  ~88}'88E&%8W.X8N``]88!.$8K  .:W8I
+ *        .i888888N;        I8Y          .&8$  .X88!  i881.:%888>I88  ;88]  +88+.';;;;:.Y88X  18N.,88l  .+88/
+ *      .:R888888I
+ *      .&888888I                                          Copyright (c) 2009-2020.  博锐尚格科技股份有限公司
+ *        ~8888'
+ *        .!88~                                                                     All rights reserved.
+ *
+ * *********************************************************************************************************************
+ */
+
+import { SStringBuilder } from "@saga-web/base";
 import {
 import {
-    SBrushType,
     SFont,
     SFont,
-    SGradientStop,
     SLine,
     SLine,
-    SLinearGradient,
     SPaintEngine,
     SPaintEngine,
     SPaintEngineType,
     SPaintEngineType,
     SPoint,
     SPoint,
-    SRadialGradient,
     SRect
     SRect
 } from "..";
 } from "..";
+import { SPath } from "../SPath";
 
 
 /**
 /**
- * Canvas绘制引擎基类
+ * Canvas 绘制引擎基类
  *
  *
- * @author  庞利祥(sybotan@126.com)
+ * @author 庞利祥 <sybotan@126.com>
  */
  */
 export class SSvgPaintEngine extends SPaintEngine {
 export class SSvgPaintEngine extends SPaintEngine {
+    /** 字符串 builder */
     private _builder = new SStringBuilder();
     private _builder = new SStringBuilder();
 
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // 属性定义
     // 属性定义
-    /** svg版本号(1.1) */
+    /** svg 版本号(1.1) */
     version = "1.1";
     version = "1.1";
     /** 宽度 */
     /** 宽度 */
     width: number = 0;
     width: number = 0;
@@ -33,19 +56,19 @@ export class SSvgPaintEngine extends SPaintEngine {
     /**
     /**
      * 绘制引擎类型
      * 绘制引擎类型
      *
      *
-     * @return  返回SVG绘制引擎类型
+     * @return 返回 SVG 绘制引擎类型
      */
      */
     get type(): SPaintEngineType {
     get type(): SPaintEngineType {
         return SPaintEngineType.SVG;
         return SPaintEngineType.SVG;
-    } // Get type
+    }
 
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // 构造函数
     // 构造函数
     /**
     /**
      * 构造函数
      * 构造函数
      *
      *
-     * @param   w       宽度
-     * @param   h       高度
+     * @param w     宽度
+     * @param h     高度
      */
      */
     constructor(w: number, h: number) {
     constructor(w: number, h: number) {
         super();
         super();
@@ -63,54 +86,46 @@ export class SSvgPaintEngine extends SPaintEngine {
         this._builder.append(
         this._builder.append(
             `version="${this.version}" width="${w}" height="${h}">`
             `version="${this.version}" width="${w}" height="${h}">`
         );
         );
-    } // Constructor
+    }
 
 
     /**
     /**
-     * 转svg图像
+     * 转 svg 图像
      *
      *
-     * @return  svg图像
+     * @return svg图像
      */
      */
     toSvg(): string {
     toSvg(): string {
         return this._builder.toString("\n") + "</svg>\n";
         return this._builder.toString("\n") + "</svg>\n";
-    } // Function toSvg()
+    }
 
 
     // =================================================================================================================
     // =================================================================================================================
     // 绘制图形
     // 绘制图形
-    /**
-     * 设置裁剪路径
-     *
-     * @param   path        裁剪路径
-     */
-    setClip(path: Path2D): void {
-        // TODO:  PLX添加实现代码
-    } // Function setClip()
+
     /**
     /**
      * 清空矩形区域
      * 清空矩形区域
      *
      *
-     * @param   rect        矩形
+     * @param rect  矩形
      */
      */
-    clearRect(rect: SRect): void {} // Function clearRect()
+    clearRect(rect: SRect): void {}
 
 
     /**
     /**
      * 绘制空心矩形
      * 绘制空心矩形
      *
      *
-     * @param   rect       矩形
+     * @param rect  矩形
      */
      */
     drawRect(rect: SRect): void {
     drawRect(rect: SRect): void {
         this._builder.append(
         this._builder.append(
-            // eslint-disable-next-line max-len
             `<rect x="${rect.x}" y="${rect.y}" width="${rect.width}" height="${
             `<rect x="${rect.x}" y="${rect.y}" width="${rect.width}" height="${
                 rect.height
                 rect.height
             }" ${this.getStyle(true, true, false)} ${this.getSvgMatrix()}/>`
             }" ${this.getStyle(true, true, false)} ${this.getSvgMatrix()}/>`
         );
         );
-    } // Functin drawRects()
+    }
 
 
     /**
     /**
      * 绘制圆形
      * 绘制圆形
      *
      *
-     * @param   cx          圆心X坐标
-     * @param   cy          圆心X坐标
-     * @param   r           圆半径
+     * @param cx    圆心 X 坐标
+     * @param cy    圆心 Y 坐标
+     * @param r     圆半径
      */
      */
     drawCircle(cx: number, cy: number, r: number): void {
     drawCircle(cx: number, cy: number, r: number): void {
         this._builder.append(
         this._builder.append(
@@ -120,15 +135,15 @@ export class SSvgPaintEngine extends SPaintEngine {
                 false
                 false
             )} ${this.getSvgMatrix()}/>`
             )} ${this.getSvgMatrix()}/>`
         );
         );
-    } // Function drawCircle()
+    }
 
 
     /**
     /**
      * 绘制椭圆
      * 绘制椭圆
      *
      *
-     * @param   cx          圆点X坐标
-     * @param   cy          圆点Y坐标
-     * @param   rx          水平半径
-     * @param   ry          垂直半径
+     * @param cx    圆点 X 坐标
+     * @param cy    圆点 Y 坐标
+     * @param rx    水平半径
+     * @param ry    垂直半径
      */
      */
     drawEllipse(cx: number, cy: number, rx: number, ry: number): void {
     drawEllipse(cx: number, cy: number, rx: number, ry: number): void {
         this._builder.append(
         this._builder.append(
@@ -138,99 +153,12 @@ export class SSvgPaintEngine extends SPaintEngine {
                 false
                 false
             )} ${this.getSvgMatrix()}/>`
             )} ${this.getSvgMatrix()}/>`
         );
         );
-    } // Function drawEllipse()
-
-    /**
-     * 绘制椭圆弧
-     *
-     * @param   x               椭圆所在矩形X坐标
-     * @param   y               椭圆所在矩形Y坐标
-     * @param   width           椭圆所在矩形宽度
-     * @param   height          椭圆所在矩形高度
-     * @param   startAngle      开始角度(单位弧度)
-     * @param   endAngle        结束角度(单位弧度)
-     */
-    drawArc(
-        x: number,
-        y: number,
-        width: number,
-        height: number,
-        startAngle: number,
-        endAngle: number
-    ): void {
-        let path = SPath2D.arc(x, y, width, height, startAngle, endAngle);
-
-        this._builder.append(
-            `<path d="${path}" ${this.getStyle(
-                false,
-                true,
-                false
-            )} ${this.getSvgMatrix()}/>`
-        );
-    } // Function drawArc()
-
-    /**
-     * 绘制椭圆弦弧
-     *
-     * @param   x               椭圆所在矩形X坐标
-     * @param   y               椭圆所在矩形Y坐标
-     * @param   width           椭圆所在矩形宽度
-     * @param   height          椭圆所在矩形高度
-     * @param   startAngle      开始角度(单位弧度)
-     * @param   endAngle        结束角度(单位弧度)
-     */
-    drawChord(
-        x: number,
-        y: number,
-        width: number,
-        height: number,
-        startAngle: number,
-        endAngle: number
-    ): void {
-        let path = SPath2D.chord(x, y, width, height, startAngle, endAngle);
-
-        this._builder.append(
-            `<path d="${path}" ${this.getStyle(
-                true,
-                true,
-                false
-            )} ${this.getSvgMatrix()}/>`
-        );
-    } // Function drawChord()
-
-    /**
-     * 绘制椭圆饼
-     *
-     * @param   x               椭圆所在矩形X坐标
-     * @param   y               椭圆所在矩形Y坐标
-     * @param   width           椭圆所在矩形宽度
-     * @param   height          椭圆所在矩形高度
-     * @param   startAngle      开始角度(单位弧度)
-     * @param   endAngle        结束角度(单位弧度)
-     */
-    drawPie(
-        x: number,
-        y: number,
-        width: number,
-        height: number,
-        startAngle: number,
-        endAngle: number
-    ): void {
-        let path = SPath2D.pie(x, y, width, height, startAngle, endAngle);
-
-        this._builder.append(
-            `<path d="${path}" ${this.getStyle(
-                true,
-                true,
-                false
-            )} ${this.getSvgMatrix()}/>`
-        );
-    } // Function drawPie()
+    }
 
 
     /**
     /**
      * 绘制线段
      * 绘制线段
      *
      *
-     * @param   line        线段
+     * @param line  线段
      */
      */
     drawLine(line: SLine): void {
     drawLine(line: SLine): void {
         this._builder.append(
         this._builder.append(
@@ -238,12 +166,12 @@ export class SSvgPaintEngine extends SPaintEngine {
                 line.y2
                 line.y2
             }" ${this.getStyle(false, true, false)} ${this.getSvgMatrix()}/>`
             }" ${this.getStyle(false, true, false)} ${this.getSvgMatrix()}/>`
         );
         );
-    } // Function drawLine()
+    }
 
 
     /**
     /**
      * 绘制折线
      * 绘制折线
      *
      *
-     * @param   points      折线折点
+     * @param points    折线折点
      */
      */
     drawPolyline(points: SPoint[]): void {
     drawPolyline(points: SPoint[]): void {
         this._builder.append(
         this._builder.append(
@@ -251,12 +179,12 @@ export class SSvgPaintEngine extends SPaintEngine {
                 points
                 points
             )}" ${this.getStyle(false, true, false)} ${this.getSvgMatrix()}/>`
             )}" ${this.getStyle(false, true, false)} ${this.getSvgMatrix()}/>`
         );
         );
-    } // Function drawPolyline()
+    }
 
 
     /**
     /**
      * 绘制多边形
      * 绘制多边形
      *
      *
-     * @param   points      多边形顶点
+     * @param points    多边形顶点
      */
      */
     drawPolygon(points: SPoint[]): void {
     drawPolygon(points: SPoint[]): void {
         this._builder.append(
         this._builder.append(
@@ -264,30 +192,29 @@ export class SSvgPaintEngine extends SPaintEngine {
                 points
                 points
             )}" ${this.getStyle(true, true, false)} ${this.getSvgMatrix()}/>`
             )}" ${this.getStyle(true, true, false)} ${this.getSvgMatrix()}/>`
         );
         );
-    } // Function drawPolyline()
+    }
 
 
     /**
     /**
      * 绘制路径
      * 绘制路径
      *
      *
-     * @param   path        路径
+     * @param path  路径
      */
      */
-    drawPath(path: SPath2D): void {
-        this._builder.append(
-            `<path d="${path.svgPath()}" ${this.getStyle(
-                true,
-                true,
-                false
-            )} ${this.getSvgMatrix()}/>`
-        );
-    } // Function drawPath()
+    drawPath(path: SPath): void {
+        //     `<path d="${path.svgPath()}" ${this.getStyle(
+        //         true,
+        //         true,
+        //         false
+        //     )} ${this.getSvgMatrix()}/>`
+        // );
+    }
 
 
     /**
     /**
      * 绘制文本
      * 绘制文本
      *
      *
-     * @param   text        文本内容
-     * @param   x           X坐标
-     * @param   y           Y坐标
-     * @param   maxWidth    最大宽度
+     * @param text        文本内容
+     * @param x           X 坐标
+     * @param y           Y 坐标
+     * @param maxWidth    最大宽度
      */
      */
     drawText(text: string, x: number, y: number, maxWidth?: number): void {
     drawText(text: string, x: number, y: number, maxWidth?: number): void {
         this._builder.append(
         this._builder.append(
@@ -297,14 +224,14 @@ export class SSvgPaintEngine extends SPaintEngine {
                 true
                 true
             )} ${this.getSvgMatrix()}>${text}</text>>`
             )} ${this.getSvgMatrix()}>${text}</text>>`
         );
         );
-    } // Function drawText()
+    }
 
 
     /**
     /**
      * 绘制图片
      * 绘制图片
      *
      *
      * @param img       图片
      * @param img       图片
-     * @param x         X坐标
-     * @param y         Y坐标
+     * @param x         X 坐标
+     * @param y         Y 坐标
      * @param width     宽度
      * @param width     宽度
      * @param height    高度
      * @param height    高度
      */
      */
@@ -316,40 +243,40 @@ export class SSvgPaintEngine extends SPaintEngine {
         height?: number
         height?: number
     ): void {
     ): void {
         // TODO: 未完成
         // TODO: 未完成
-    } // Function drawImage()
+    }
 
 
     /**
     /**
      * 预测量文本宽度
      * 预测量文本宽度
      *
      *
-     * @param   text    预测的文本
-     * @return  文本长度像素
-     * */
+     * @param text  预测的文本
+     * @return 文本长度像素
+     */
     textWidth(text: string): number {
     textWidth(text: string): number {
         return 0;
         return 0;
-    } // Function textWidth()
+    }
 
 
     /**
     /**
      * 设置字体
      * 设置字体
      *
      *
-     * @param   font    字体
+     * @param font  字体
      */
      */
-    changeFont(font: SFont): void {} // Function changeFont()
+    changeFont(font: SFont): void {}
 
 
     /**
     /**
      * 获得svg需要的变形信息
      * 获得svg需要的变形信息
      *
      *
-     * @return  变换信息
+     * @return 变换信息
      */
      */
     private getSvgMatrix(): string {
     private getSvgMatrix(): string {
         // eslint-disable-next-line max-len
         // eslint-disable-next-line max-len
         return `transform="matrix(${this.state.matrix.a}, ${this.state.matrix.b}, ${this.state.matrix.c}, ${this.state.matrix.d}, ${this.state.matrix.e}, ${this.state.matrix.f})"`;
         return `transform="matrix(${this.state.matrix.a}, ${this.state.matrix.b}, ${this.state.matrix.c}, ${this.state.matrix.d}, ${this.state.matrix.e}, ${this.state.matrix.f})"`;
-    } // Function getMatrix()
+    }
 
 
     /**
     /**
      * 将点列表转换为字符串表达形式
      * 将点列表转换为字符串表达形式
      *
      *
-     * @param   points      被转换的点
-     * @return  点列表字符串
+     * @param points    被转换的点
+     * @return 点列表字符串
      */
      */
     private static pointsToStr(points: SPoint[]): string {
     private static pointsToStr(points: SPoint[]): string {
         let strBuilder = new SStringBuilder();
         let strBuilder = new SStringBuilder();
@@ -357,7 +284,7 @@ export class SSvgPaintEngine extends SPaintEngine {
             strBuilder.append(`${p.x},${p.y}`);
             strBuilder.append(`${p.x},${p.y}`);
         }
         }
         return strBuilder.toString(" ");
         return strBuilder.toString(" ");
-    } // Function pointsToStr()
+    }
 
 
     /** 获得风格 */
     /** 获得风格 */
     private getStyle(
     private getStyle(
@@ -401,5 +328,10 @@ export class SSvgPaintEngine extends SPaintEngine {
         }
         }
         builder.append('"');
         builder.append('"');
         return builder.toString("");
         return builder.toString("");
-    } // Get penStyle
-} // Class SSvgPaintEngine
+    }
+
+    /**
+     * 绘制圆角矩形
+     */
+    drawRoundRect(): void {}
+}

+ 5 - 3
saga-web-draw/src/index.ts

@@ -40,10 +40,11 @@ import { SGradient } from "./SGradient";
 import { SGradientStop } from "./SGradientStop";
 import { SGradientStop } from "./SGradientStop";
 import { SLinearGradient } from "./SLinearGradient";
 import { SLinearGradient } from "./SLinearGradient";
 import { SPainter } from "./SPainter";
 import { SPainter } from "./SPainter";
-import { SPath2D } from "./SPath2D";
+import { SPath } from "./SPath";
 import { SPen } from "./SPen";
 import { SPen } from "./SPen";
 import { SRadialGradient } from "./SRadialGradient";
 import { SRadialGradient } from "./SRadialGradient";
 import { SArrowStyleType } from "./enums/SArrowStyleType";
 import { SArrowStyleType } from "./enums/SArrowStyleType";
+import { SCompositeType } from "./enums/SCompositeType";
 export {
 export {
     SBrush,
     SBrush,
     SCanvasView,
     SCanvasView,
@@ -53,8 +54,9 @@ export {
     SGradientStop,
     SGradientStop,
     SLinearGradient,
     SLinearGradient,
     SPainter,
     SPainter,
-    SPath2D,
+    SPath,
     SPen,
     SPen,
     SRadialGradient,
     SRadialGradient,
-    SArrowStyleType
+    SArrowStyleType,
+    SCompositeType
 };
 };

+ 2 - 2
saga-web-graph/package.json

@@ -1,6 +1,6 @@
 {
 {
     "name": "@saga-web/graph",
     "name": "@saga-web/graph",
-    "version": "2.1.127",
+    "version": "2.1.128",
     "description": "上格云二维图形引擎。",
     "description": "上格云二维图形引擎。",
     "main": "lib/index.js",
     "main": "lib/index.js",
     "types": "lib/index.d.js",
     "types": "lib/index.d.js",
@@ -40,7 +40,7 @@
         "typescript": "^3.9.7"
         "typescript": "^3.9.7"
     },
     },
     "dependencies": {
     "dependencies": {
-        "@saga-web/draw": "2.1.108",
+        "@saga-web/draw": "2.1.109",
         "@types/uuid": "^8.0.0"
         "@types/uuid": "^8.0.0"
     }
     }
 }
 }

+ 11 - 0
saga-web-graph/src/SGraphItem.ts

@@ -125,6 +125,16 @@ export class SGraphItem extends SObject {
         this.update();
         this.update();
     } // Set visible
     } // Set visible
 
 
+    /** 透明度 */
+    private _globalAlpha = 1;
+    get globalAlpha(): number {
+        return this._globalAlpha;
+    } // Get number
+    set globalAlpha(v: number) {
+        this._globalAlpha = v;
+        this.update();
+    } // Set number
+
     /** 是否可以移动 */
     /** 是否可以移动 */
     moveable: boolean = false;
     moveable: boolean = false;
     /** 是否正在移动 */
     /** 是否正在移动 */
@@ -200,6 +210,7 @@ export class SGraphItem extends SObject {
                 painter.translate(item.x, item.y);
                 painter.translate(item.x, item.y);
                 painter.scale(item.scale, item.scale);
                 painter.scale(item.scale, item.scale);
                 painter.rotate(item.rotate);
                 painter.rotate(item.rotate);
+                painter.globalAlpha = item.globalAlpha;
 
 
                 // 如果不进行变形处理,则取消painter的变型操作
                 // 如果不进行变形处理,则取消painter的变型操作
                 if (!item.isTransform) {
                 if (!item.isTransform) {