/* * (c) Copyright Ascensio System SIA 2010-2024 * * This program is a free software product. You can redistribute it and/or * modify it under the terms of the GNU Affero General Public License (AGPL) * version 3 as published by the Free Software Foundation. In accordance with * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect * that Ascensio System SIA expressly excludes the warranty of non-infringement * of any third-party rights. * * This program is distributed WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html * * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish * street, Riga, Latvia, EU, LV-1050. * * The interactive user interfaces in modified source and object code versions * of the Program must display Appropriate Legal Notices, as required under * Section 5 of the GNU AGPL version 3. * * Pursuant to Section 7(b) of the License you must retain the original Product * logo when distributing the program. Pursuant to Section 7(e) we decline to * grant you any rights under trademark law for use of our trademarks. * * All the Product's GUI elements, including illustrations and icon sets, as * well as technical writing content are licensed under the terms of the * Creative Commons Attribution-ShareAlike 4.0 International. See the License * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode * */ "use strict"; (function(window, undefined){ // Import var getFullImageSrc2 = AscCommon.getFullImageSrc2; var CShapeColor = AscFormat.CShapeColor; var c_oAscFill = Asc.c_oAscFill; function DrawLineEnd(xEnd, yEnd, xPrev, yPrev, type, w, len, drawer, trans) { switch (type) { case AscFormat.LineEndType.None: break; case AscFormat.LineEndType.Arrow: { if (Asc.editor.isPdfEditor() == true) { drawer.CheckDash(); } var _ex = xPrev - xEnd; var _ey = yPrev - yEnd; var _elen = Math.sqrt(_ex*_ex + _ey*_ey); _ex /= _elen; _ey /= _elen; var _vx = _ey; var _vy = -_ex; var tmpx = xEnd + len * _ex; var tmpy = yEnd + len * _ey; var x1 = tmpx + _vx * w/2; var y1 = tmpy + _vy * w/2; var x3 = tmpx - _vx * w/2; var y3 = tmpy - _vy * w/2; drawer._s(); drawer._m(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(xEnd, yEnd), trans.TransformPointY(xEnd, yEnd)); drawer._l(trans.TransformPointX(x3, y3), trans.TransformPointY(x3, y3)); drawer.ds(); drawer._e(); break; } case AscFormat.LineEndType.ReverseArrow: { if (Asc.editor.isPdfEditor() == true) { drawer.CheckDash(); } var _ex = xPrev - xEnd; var _ey = yPrev - yEnd; var _elen = Math.sqrt(_ex*_ex + _ey*_ey); _ex /= _elen; _ey /= _elen; var _vx = _ey; var _vy = -_ex; var tmpx = xEnd - len * _ex; var tmpy = yEnd - len * _ey; var x1 = tmpx + _vx * w/2; var y1 = tmpy + _vy * w/2; var x3 = tmpx - _vx * w/2; var y3 = tmpy - _vy * w/2; drawer._s(); drawer._m(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(xEnd, yEnd), trans.TransformPointY(xEnd, yEnd)); drawer._l(trans.TransformPointX(x3, y3), trans.TransformPointY(x3, y3)); drawer.ds(); drawer._e(); break; } case AscFormat.LineEndType.Diamond: { var _ex = xPrev - xEnd; var _ey = yPrev - yEnd; var _elen = Math.sqrt(_ex*_ex + _ey*_ey); _ex /= _elen; _ey /= _elen; var _vx = _ey; var _vy = -_ex; var tmpx = xEnd + len/2 * _ex; var tmpy = yEnd + len/2 * _ey; var x1 = xEnd + _vx * w/2; var y1 = yEnd + _vy * w/2; var x3 = xEnd - _vx * w/2; var y3 = yEnd - _vy * w/2; var tmpx2 = xEnd - len/2 * _ex; var tmpy2 = yEnd - len/2 * _ey; drawer._s(); drawer._m(trans.TransformPointX(tmpx, tmpy), trans.TransformPointY(tmpx, tmpy)); drawer._l(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(tmpx2, tmpy2), trans.TransformPointY(tmpx2, tmpy2)); drawer._l(trans.TransformPointX(x3, y3), trans.TransformPointY(x3, y3)); drawer._z(); if (Asc.editor.isPdfEditor()) { let oRGBColor; if (drawer.Shape.GetRGBColor) { oRGBColor = drawer.Shape.GetRGBColor(drawer.Shape.GetFillColor()); } else if (drawer.Shape.group) { oRGBColor = drawer.Shape.group.GetRGBColor(drawer.Shape.group.GetFillColor()); } if (oRGBColor) { drawer.Graphics.m_oPen.Color.R = oRGBColor.r; drawer.Graphics.m_oPen.Color.G = oRGBColor.g; drawer.Graphics.m_oPen.Color.B = oRGBColor.b; } } drawer.drawStrokeFillStyle(); drawer._e(); drawer._s(); drawer._m(trans.TransformPointX(tmpx, tmpy), trans.TransformPointY(tmpx, tmpy)); drawer._l(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(tmpx2, tmpy2), trans.TransformPointY(tmpx2, tmpy2)); drawer._l(trans.TransformPointX(x3, y3), trans.TransformPointY(x3, y3)); drawer._z(); drawer.ds(); drawer._e(); break; } case AscFormat.LineEndType.Square: { var angle = Math.atan2(yEnd - yPrev, xEnd - xPrev); function rotatePoints(aPoints) { // Поворачиваем каждую вершину вокруг центра for (var i = 0; i < aPoints.length; i++) { var x = aPoints[i].x - xEnd; var y = aPoints[i].y - yEnd; // Применяем матрицу поворота var rotatedX = x * Math.cos(angle) - y * Math.sin(angle); var rotatedY = x * Math.sin(angle) + y * Math.cos(angle); // Возвращаем вершины на место aPoints[i].x = rotatedX + xEnd; aPoints[i].y = rotatedY + yEnd; } } var x1 = xEnd - w/2; var y1 = yEnd + w/2; var x2 = xEnd - w/2; var y2 = yEnd - w/2; var x3 = xEnd + w/2; var y3 = yEnd - w/2; var x4 = xEnd + w/2; var y4 = yEnd + w/2; let aSmall = [ { x: x1, y: y1 }, { x: x2, y: y2 }, { x: x3, y: y3 }, { x: x4, y: y4 } ] rotatePoints(aSmall); drawer._s(); drawer._m(trans.TransformPointX(aSmall[0].x, aSmall[0].y), trans.TransformPointY(aSmall[0].x, aSmall[0].y)); for (var i = 1; i < aSmall.length; i++) { drawer._l(trans.TransformPointX(aSmall[i].x, aSmall[i].y), trans.TransformPointY(aSmall[i].x, aSmall[i].y)); } drawer._z(); if (Asc.editor.isPdfEditor()) { let oRGBColor; if (drawer.Shape.GetRGBColor) { oRGBColor = drawer.Shape.GetRGBColor(drawer.Shape.GetFillColor()); } else if (drawer.Shape.group) { oRGBColor = drawer.Shape.group.GetRGBColor(drawer.Shape.group.GetFillColor()); } if (oRGBColor) { drawer.Graphics.m_oPen.Color.R = oRGBColor.r; drawer.Graphics.m_oPen.Color.G = oRGBColor.g; drawer.Graphics.m_oPen.Color.B = oRGBColor.b; } } drawer.drawStrokeFillStyle(); drawer._e(); x1 = xEnd - w * 2/4; y1 = yEnd + w * 2/4; x2 = xEnd - w * 2/4; y2 = yEnd - w * 2/4; x3 = xEnd + w * 2/4; y3 = yEnd - w * 2/4; x4 = xEnd + w * 2/4; y4 = yEnd + w * 2/4; let aBig = [ { x: x1, y: y1 }, { x: x2, y: y2 }, { x: x3, y: y3 }, { x: x4, y: y4 } ] rotatePoints(aBig); drawer._s(); drawer._m(trans.TransformPointX(aBig[0].x, aBig[0].y), trans.TransformPointY(aBig[0].x, aBig[0].y)); for (var i = 1; i < aBig.length; i++) { drawer._l(trans.TransformPointX(aBig[i].x, aBig[i].y), trans.TransformPointY(aBig[i].x, aBig[i].y)); } drawer._z(); drawer.ds(); drawer._e(); break; } case AscFormat.LineEndType.Oval: { var _ex = xPrev - xEnd; var _ey = yPrev - yEnd; var _elen = Math.sqrt(_ex*_ex + _ey*_ey); _ex /= _elen; _ey /= _elen; var _vx = _ey; var _vy = -_ex; var tmpx = xEnd + len/2 * _ex; var tmpy = yEnd + len/2 * _ey; var tmpx2 = xEnd - len/2 * _ex; var tmpy2 = yEnd - len/2 * _ey; var cx1 = tmpx + _vx * 3*w/4; var cy1 = tmpy + _vy * 3*w/4; var cx2 = tmpx2 + _vx * 3*w/4; var cy2 = tmpy2 + _vy * 3*w/4; var cx3 = tmpx - _vx * 3*w/4; var cy3 = tmpy - _vy * 3*w/4; var cx4 = tmpx2 - _vx * 3*w/4; var cy4 = tmpy2 - _vy * 3*w/4; drawer._s(); drawer._m(trans.TransformPointX(tmpx, tmpy), trans.TransformPointY(tmpx, tmpy)); drawer._c(trans.TransformPointX(cx1, cy1), trans.TransformPointY(cx1, cy1), trans.TransformPointX(cx2, cy2), trans.TransformPointY(cx2, cy2), trans.TransformPointX(tmpx2, tmpy2), trans.TransformPointY(tmpx2, tmpy2)); drawer._c(trans.TransformPointX(cx4, cy4), trans.TransformPointY(cx4, cy4), trans.TransformPointX(cx3, cy3), trans.TransformPointY(cx3, cy3), trans.TransformPointX(tmpx, tmpy), trans.TransformPointY(tmpx, tmpy)); if (Asc.editor.isPdfEditor()) { let oRGBColor; if (drawer.Shape.GetRGBColor) { oRGBColor = drawer.Shape.GetRGBColor(drawer.Shape.GetFillColor()); } else if (drawer.Shape.group) { oRGBColor = drawer.Shape.group.GetRGBColor(drawer.Shape.group.GetFillColor()); } if (oRGBColor) { drawer.Graphics.m_oPen.Color.R = oRGBColor.r; drawer.Graphics.m_oPen.Color.G = oRGBColor.g; drawer.Graphics.m_oPen.Color.B = oRGBColor.b; } } drawer.drawStrokeFillStyle(); drawer._e(); drawer._s(); drawer._m(trans.TransformPointX(tmpx, tmpy), trans.TransformPointY(tmpx, tmpy)); drawer._c(trans.TransformPointX(cx1, cy1), trans.TransformPointY(cx1, cy1), trans.TransformPointX(cx2, cy2), trans.TransformPointY(cx2, cy2), trans.TransformPointX(tmpx2, tmpy2), trans.TransformPointY(tmpx2, tmpy2)); drawer._c(trans.TransformPointX(cx4, cy4), trans.TransformPointY(cx4, cy4), trans.TransformPointX(cx3, cy3), trans.TransformPointY(cx3, cy3), trans.TransformPointX(tmpx, tmpy), trans.TransformPointY(tmpx, tmpy)); drawer.ds(); drawer._e(); break; } case AscFormat.LineEndType.Stealth: { var _ex = xPrev - xEnd; var _ey = yPrev - yEnd; var _elen = Math.sqrt(_ex*_ex + _ey*_ey); _ex /= _elen; _ey /= _elen; var _vx = _ey; var _vy = -_ex; var tmpx = xEnd + len * _ex; var tmpy = yEnd + len * _ey; var x1 = tmpx + _vx * w/2; var y1 = tmpy + _vy * w/2; var x3 = tmpx - _vx * w/2; var y3 = tmpy - _vy * w/2; var x4 = xEnd + (len - w/2) * _ex; var y4 = yEnd + (len - w/2) * _ey; drawer._s(); drawer._m(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(xEnd, yEnd), trans.TransformPointY(xEnd, yEnd)); drawer._l(trans.TransformPointX(x3, y3), trans.TransformPointY(x3, y3)); drawer._l(trans.TransformPointX(x4, y4), trans.TransformPointY(x4, y4)); drawer._z(); drawer.drawStrokeFillStyle(); drawer._e(); drawer._s(); drawer._m(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(xEnd, yEnd), trans.TransformPointY(xEnd, yEnd)); drawer._l(trans.TransformPointX(x3, y3), trans.TransformPointY(x3, y3)); drawer._l(trans.TransformPointX(x4, y4), trans.TransformPointY(x4, y4)); drawer._z(); drawer.ds(); drawer._e(); break; } case AscFormat.LineEndType.ReverseTriangle: { var _ex = xPrev - xEnd; var _ey = yPrev - yEnd; var _elen = Math.sqrt(_ex*_ex + _ey*_ey); _ex /= _elen; _ey /= _elen; var _vx = _ey; var _vy = -_ex; var tmpx = xEnd - len * _ex; var tmpy = yEnd - len * _ey; var x1 = tmpx + _vx * w/2; var y1 = tmpy + _vy * w/2; var x3 = tmpx - _vx * w/2; var y3 = tmpy - _vy * w/2; drawer._s(); drawer._m(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(xEnd, yEnd), trans.TransformPointY(xEnd, yEnd)); drawer._l(trans.TransformPointX(x3, y3), trans.TransformPointY(x3, y3)); drawer._z(); if (Asc.editor.isPdfEditor()) { let oRGBColor; if (drawer.Shape.GetRGBColor) { oRGBColor = drawer.Shape.GetRGBColor(drawer.Shape.GetFillColor()); } else if (drawer.Shape.group) { oRGBColor = drawer.Shape.group.GetRGBColor(drawer.Shape.group.GetFillColor()); } if (oRGBColor) { drawer.Graphics.m_oPen.Color.R = oRGBColor.r; drawer.Graphics.m_oPen.Color.G = oRGBColor.g; drawer.Graphics.m_oPen.Color.B = oRGBColor.b; } } drawer.drawStrokeFillStyle(); drawer._e(); drawer._s(); drawer._m(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(xEnd, yEnd), trans.TransformPointY(xEnd, yEnd)); drawer._l(trans.TransformPointX(x3, y3), trans.TransformPointY(x3, y3)); drawer._z(); drawer.ds(); drawer._e(); break; } case AscFormat.LineEndType.Triangle: { var _ex = xPrev - xEnd; var _ey = yPrev - yEnd; var _elen = Math.sqrt(_ex*_ex + _ey*_ey); _ex /= _elen; _ey /= _elen; var _vx = _ey; var _vy = -_ex; var tmpx = xEnd + len * _ex; var tmpy = yEnd + len * _ey; var x1 = tmpx + _vx * w/2; var y1 = tmpy + _vy * w/2; var x3 = tmpx - _vx * w/2; var y3 = tmpy - _vy * w/2; drawer._s(); drawer._m(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(xEnd, yEnd), trans.TransformPointY(xEnd, yEnd)); drawer._l(trans.TransformPointX(x3, y3), trans.TransformPointY(x3, y3)); drawer._z(); if (Asc.editor.isPdfEditor()) { let oRGBColor; if (drawer.Shape.GetRGBColor) { oRGBColor = drawer.Shape.GetRGBColor(drawer.Shape.GetFillColor()); } else if (drawer.Shape.group) { oRGBColor = drawer.Shape.group.GetRGBColor(drawer.Shape.group.GetFillColor()); } if (oRGBColor) { drawer.Graphics.m_oPen.Color.R = oRGBColor.r; drawer.Graphics.m_oPen.Color.G = oRGBColor.g; drawer.Graphics.m_oPen.Color.B = oRGBColor.b; } } drawer.drawStrokeFillStyle(); drawer._e(); drawer._s(); drawer._m(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(xEnd, yEnd), trans.TransformPointY(xEnd, yEnd)); drawer._l(trans.TransformPointX(x3, y3), trans.TransformPointY(x3, y3)); drawer._z(); drawer.ds(); drawer._e(); break; } case AscFormat.LineEndType.Butt: { var _ex = xPrev - xEnd; var _ey = yPrev - yEnd; var _elen = Math.sqrt(_ex*_ex + _ey*_ey); _ex /= _elen; _ey /= _elen; var _vx = _ey; var _vy = -_ex; var tmpx = xEnd + len * _ex; var tmpy = yEnd + len * _ey; var angle = Math.atan2(yEnd - yPrev, xEnd - xPrev); // Вычисляем координаты конца перпендикулярной линии var perpendicularLength = w; var x1 = xEnd + perpendicularLength * Math.cos(angle - Math.PI / 2); var y1 = yEnd + perpendicularLength * Math.sin(angle - Math.PI / 2); var x2 = xEnd - perpendicularLength * Math.cos(angle - Math.PI / 2); var y2 = yEnd - perpendicularLength * Math.sin(angle - Math.PI / 2); drawer._s(); drawer._m(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(x2, y2), trans.TransformPointY(x2, y2)); drawer.ds(); break; } case AscFormat.LineEndType.Slash: { var _ex = xPrev - xEnd; var _ey = yPrev - yEnd; var _elen = Math.sqrt(_ex*_ex + _ey*_ey); _ex /= _elen; _ey /= _elen; var _vx = _ey; var _vy = -_ex; var tmpx = xEnd + len * _ex; var tmpy = yEnd + len * _ey; var angle = Math.atan2(yEnd - yPrev, xEnd - xPrev) + (30 * Math.PI / 180); // Вычисляем координаты конца перпендикулярной линии var perpendicularLength = w; var x1 = xEnd + perpendicularLength * Math.cos(angle - Math.PI / 2); var y1 = yEnd + perpendicularLength * Math.sin(angle - Math.PI / 2); var x2 = xEnd - perpendicularLength * Math.cos(angle - Math.PI / 2); var y2 = yEnd - perpendicularLength * Math.sin(angle - Math.PI / 2); drawer._s(); drawer._m(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(x2, y2), trans.TransformPointY(x2, y2)); drawer.ds(); break; } // visio types are handled below } if (type === AscFormat.LineEndType.vsdxOpenASMEArrow || type === AscFormat.LineEndType.vsdxFilledASMEArrow || type === AscFormat.LineEndType.vsdxClosedASMEArrow) { len *= 1.5; let isFilled = type === AscFormat.LineEndType.vsdxFilledASMEArrow; let isOpen = type === AscFormat.LineEndType.vsdxOpenASMEArrow; drawArrow(drawer, xPrev, yPrev, xEnd, yEnd, 0, isFilled, isOpen, w, len); } else if (type === AscFormat.LineEndType.vsdxOpenSharpArrow || type === AscFormat.LineEndType.vsdxFilledSharpArrow || type === AscFormat.LineEndType.vsdxClosedSharpArrow) { let isFilled = type === AscFormat.LineEndType.vsdxFilledSharpArrow; let isOpen = type === AscFormat.LineEndType.vsdxOpenSharpArrow; drawArrow(drawer, xPrev, yPrev, xEnd, yEnd, 0, isFilled, isOpen, w, len); } else if (type === AscFormat.LineEndType.vsdxOpen90Arrow || type === AscFormat.LineEndType.vsdxFilled90Arrow || type === AscFormat.LineEndType.vsdxClosed90Arrow) { len /= 2; let isFilled = type === AscFormat.LineEndType.vsdxFilled90Arrow; let isOpen = type === AscFormat.LineEndType.vsdxOpen90Arrow; drawArrow(drawer, xPrev, yPrev, xEnd, yEnd, 0, isFilled, isOpen, w, len); } else if (type === AscFormat.LineEndType.vsdxIndentedFilledArrow || type === AscFormat.LineEndType.vsdxIndentedClosedArrow || type === AscFormat.LineEndType.vsdxOutdentedFilledArrow || type === AscFormat.LineEndType.vsdxOutdentedClosedArrow) { let isArrowFilled = type === AscFormat.LineEndType.vsdxIndentedFilledArrow || type === AscFormat.LineEndType.vsdxOutdentedFilledArrow; let isIndented = type === AscFormat.LineEndType.vsdxIndentedFilledArrow || type === AscFormat.LineEndType.vsdxIndentedClosedArrow; var _ex = xPrev - xEnd; var _ey = yPrev - yEnd; var _elen = Math.sqrt(_ex*_ex + _ey*_ey); _ex /= _elen; // cos a _ey /= _elen; // sin a // a now is 90 - a + invert cos var _vx = _ey; var _vy = -_ex; // (xEnd, yEnd) - right arrow point var tmpx = xEnd + len * _ex; var tmpy = yEnd + len * _ey; // (x1, y1) - top arrow point var x1 = tmpx + _vx * w/2; var y1 = tmpy + _vy * w/2; // (x3, y3) - bottom arrow point var x3 = tmpx - _vx * w/2; var y3 = tmpy - _vy * w/2; let controlPointShift = isIndented? 0.75 * len : 1.25 * len; var x4 = xEnd + controlPointShift * _ex; var y4 = yEnd + controlPointShift * _ey; drawer._s(); drawer._m(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(xEnd, yEnd), trans.TransformPointY(xEnd, yEnd)); drawer._l(trans.TransformPointX(x3, y3), trans.TransformPointY(x3, y3)); let cpxLocal = trans.TransformPointX(x4, y4); let cpyLocal = trans.TransformPointY(x4, y4); let endXLocal = trans.TransformPointX(x1, y1); let endYLocal = trans.TransformPointY(x1, y1); drawer._c2(cpxLocal, cpyLocal, endXLocal, endYLocal); drawer._z(); stokeOrFillPath(drawer, isArrowFilled); drawer._e(); } else if (type === AscFormat.LineEndType.vsdxOpenFletch || type === AscFormat.LineEndType.vsdxFilledFletch || type === AscFormat.LineEndType.vsdxClosedFletch) { let isArrowFilled = false; let isArrowClosed = false; if (type === AscFormat.LineEndType.vsdxFilledFletch) { isArrowClosed = true; isArrowFilled = true; } else if (type === AscFormat.LineEndType.vsdxClosedFletch) { isArrowFilled = false; isArrowClosed = true; } var _ex = xPrev - xEnd; var _ey = yPrev - yEnd; var _elen = Math.sqrt(_ex*_ex + _ey*_ey); _ex /= _elen; // cos a _ey /= _elen; // sin a // a now is 90 - a + invert cos var _vx = _ey; var _vy = -_ex; // (xEnd, yEnd) - right arrow point // left arrow point? var tmpx = xEnd + len * _ex; var tmpy = yEnd + len * _ey; // (x1, y1) - top arrow point var x1 = tmpx + _vx * w/2; var y1 = tmpy + _vy * w/2; // (x3, y3) - bottom arrow point var x3 = tmpx - _vx * w/2; var y3 = tmpy - _vy * w/2; let controlPointShift = 0.5 * len; var x4 = xEnd + controlPointShift * _ex; var y4 = yEnd + controlPointShift * _ey; drawer._s(); drawer._m(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); let cpxLocal = trans.TransformPointX(x4, y4); let cpyLocal = trans.TransformPointY(x4, y4); let endXLocal = trans.TransformPointX(xEnd, yEnd); let endYLocal = trans.TransformPointY(xEnd, yEnd); drawer._c2(cpxLocal, cpyLocal, endXLocal, endYLocal); // drawer._m(trans.TransformPointX(x3, y3), trans.TransformPointY(x3, y3)); drawer._c2(cpxLocal, cpyLocal, trans.TransformPointX(x3, y3), trans.TransformPointY(x3, y3)); if (isArrowClosed) { // drawer._m(trans.TransformPointX(x3, y3), trans.TransformPointY(x3, y3)); drawer._c2(cpxLocal, cpyLocal, trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); } // drawer._z(); stokeOrFillPath(drawer, isArrowFilled); drawer._e(); } else if (type === AscFormat.LineEndType.vsdxDimensionLine) { const drawLineAngle = Math.atan2(yEnd - yPrev, xEnd - xPrev) + (45 * Math.PI / 180); // Вычисляем координаты конца перпендикулярной линии const perpendicularLength = w * Math.sin(Math.PI / 4); // don't know why it's not just =w here const x1 = xEnd + perpendicularLength * Math.cos(drawLineAngle); // top right point for visio const y1 = yEnd + perpendicularLength * Math.sin(drawLineAngle); // top right point for visio const x2 = xEnd - perpendicularLength * Math.cos(drawLineAngle); const y2 = yEnd - perpendicularLength * Math.sin(drawLineAngle); drawer._s(); drawer._m(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(x2, y2), trans.TransformPointY(x2, y2)); drawer.ds(); } else if (type === AscFormat.LineEndType.vsdxFilledDot || type === AscFormat.LineEndType.vsdxClosedDot) { let isFilled = type === AscFormat.LineEndType.vsdxFilledDot; drawCircle(drawer, xPrev, yPrev, xEnd, yEnd, 0, w, len, isFilled); } else if (type === AscFormat.LineEndType.vsdxFilledSquare || type === AscFormat.LineEndType.vsdxClosedSquare) { let isArrowFilled = type === AscFormat.LineEndType.vsdxFilledSquare; let _ex = xPrev - xEnd; let _ey = yPrev - yEnd; let _elen = Math.sqrt(_ex*_ex + _ey*_ey); _ex /= _elen; // cos a _ey /= _elen; // sin a let isRotated = false; _ex = isRotated? _ex : 1; // cos a _ey = isRotated? _ey : 0; // sin a // a now is 90 - a + invert cos let _vx = _ey; let _vy = -_ex; // (xEnd, yEnd) - right arrow point let paramsScale = 0.4; // left arrow point? let tmpx = xEnd + len * paramsScale * _ex; let tmpy = yEnd + len * paramsScale * _ey; // (x1, y1) - left top arrow point let x1 = tmpx + _vx * w * paramsScale; let y1 = tmpy + _vy * w * paramsScale; // (x2, y2) - left bottom arrow point let x2 = tmpx - _vx * w * paramsScale; let y2 = tmpy - _vy * w * paramsScale; // right arrow point? let tmpxRight = xEnd - len * paramsScale * _ex; let tmpyRight = yEnd - len * paramsScale * _ey; // (x3, y3) - left top arrow point let x3 = tmpxRight + _vx * w * paramsScale; let y3 = tmpyRight + _vy * w * paramsScale; // (x4, y4) - left bottom arrow point let x4 = tmpxRight - _vx * w * paramsScale; let y4 = tmpyRight - _vy * w * paramsScale; drawer._s(); drawer._m(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(x3, y3), trans.TransformPointY(x3, y3)); drawer._l(trans.TransformPointX(x4, y4), trans.TransformPointY(x4, y4)); drawer._l(trans.TransformPointX(x2, y2), trans.TransformPointY(x2, y2)); drawer._z(); stokeOrFillPath(drawer, isArrowFilled); drawer._e(); } else if (type === AscFormat.LineEndType.vsdxDiamond) { drawRhomb(drawer, xPrev, yPrev, xEnd, yEnd, 0); } else if (type === AscFormat.LineEndType.vsdxBackslash) { let _ex = xPrev - xEnd; let _ey = yPrev - yEnd; const arrowPartLen = Math.sqrt(_ex * _ex + _ey * _ey); const arrowCos = _ex / arrowPartLen; const arrowSin = _ey / arrowPartLen; const xShift = len * arrowCos; const yShift = len * arrowSin; const drawLineAngle = Math.atan2(yEnd - yPrev, xEnd - xPrev) - (45 * Math.PI / 180); // Вычисляем координаты конца перпендикулярной линии const perpendicularLength = w * Math.sin(Math.PI / 4); // don't know why it's not just =w here const x1 = xEnd + perpendicularLength * Math.cos(drawLineAngle) + xShift; // top right point for visio const y1 = yEnd + perpendicularLength * Math.sin(drawLineAngle) + yShift; // top right point for visio const x2 = xEnd - perpendicularLength * Math.cos(drawLineAngle) + xShift; const y2 = yEnd - perpendicularLength * Math.sin(drawLineAngle) + yShift; drawer._s(); drawer._m(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(x2, y2), trans.TransformPointY(x2, y2)); drawer.ds(); drawer._e(); } else if (type === AscFormat.LineEndType.vsdxOpenOneDash) { let shift = 0.75 * len; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); } else if (type === AscFormat.LineEndType.vsdxOpenTwoDash) { let shift = 0.75 * len; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift * 1.5); } else if (type === AscFormat.LineEndType.vsdxOpenThreeDash) { let shift = 0.75 * len; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift * 1.5); drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift * 2); } else if (type === AscFormat.LineEndType.vsdxFork) { drawFork(drawer, xPrev, yPrev, xEnd, yEnd); } else if (type === AscFormat.LineEndType.vsdxDashFork) { drawFork(drawer, xPrev, yPrev, xEnd, yEnd); let shift = 1.5 * len * 0.75; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); } else if (type === AscFormat.LineEndType.vsdxClosedFork) { let isFilled = false; drawFork(drawer, xPrev, yPrev, xEnd, yEnd); let shift = 0.75 * len * 1.5; drawCircle(drawer, xPrev, yPrev, xEnd, yEnd, shift, w, len, isFilled); } else if (type === AscFormat.LineEndType.vsdxClosedPlus) { let shift = 0.75 * len * 1.5; drawCircle(drawer, xPrev, yPrev, xEnd, yEnd, shift, w, len, false); shift = 0.75 * len * 0.5; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); } else if (type === AscFormat.LineEndType.vsdxClosedOneDash) { let shift = 0.75 * len * 1.5; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); shift = 0.75 * len * 0.5; drawCircle(drawer, xPrev, yPrev, xEnd, yEnd, shift, w, len, false); } else if (type === AscFormat.LineEndType.vsdxClosedTwoDash) { let shift = 0.75 * len * 2; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); shift = 0.75 * len * 1.5; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); shift = 0.75 * len * 0.5; drawCircle(drawer, xPrev, yPrev, xEnd, yEnd, shift, w, len, false); } else if (type === AscFormat.LineEndType.vsdxClosedThreeDash) { let shift = 0.75 * len * 2.5; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); shift = 0.75 * len * 2; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); shift = 0.75 * len * 1.5; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); shift = 0.75 * len * 0.5; drawCircle(drawer, xPrev, yPrev, xEnd, yEnd, shift, w, len, false); } else if (type === AscFormat.LineEndType.vsdxClosedDiamond) { let shift = 0.75 * len * 1.25; drawRhomb(drawer, xPrev, yPrev, xEnd, yEnd, shift); shift = 0.75 * len * 0.5; drawCircle(drawer, xPrev, yPrev, xEnd, yEnd, shift, w, len, false); } else if (type === AscFormat.LineEndType.vsdxFilledOneDash) { let shift = 0.75 * len * 1.5; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); shift = 0.75 * len * 0.5; drawCircle(drawer, xPrev, yPrev, xEnd, yEnd, shift, w, len, true); } else if (type === AscFormat.LineEndType.vsdxFilledTwoDash) { let shift = 0.75 * len * 2; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); shift = 0.75 * len * 1.5; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); shift = 0.75 * len * 0.5; drawCircle(drawer, xPrev, yPrev, xEnd, yEnd, shift, w, len, true); } else if (type === AscFormat.LineEndType.vsdxFilledThreeDash) { let shift = 0.75 * len * 2.5; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); shift = 0.75 * len * 2; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); shift = 0.75 * len * 1.5; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); shift = 0.75 * len * 0.5; drawCircle(drawer, xPrev, yPrev, xEnd, yEnd, shift, w, len, true); } else if (type === AscFormat.LineEndType.vsdxFilledDiamond) { let shift = 0.75 * len * 1.25; drawRhomb(drawer, xPrev, yPrev, xEnd, yEnd, shift); shift = 0.75 * len * 0.5; drawCircle(drawer, xPrev, yPrev, xEnd, yEnd, shift, w, len, true); } else if (type === AscFormat.LineEndType.vsdxFilledDoubleArrow) { drawArrow(drawer, xPrev, yPrev, xEnd, yEnd, 0, true, false, w, len); drawArrow(drawer, xPrev, yPrev, xEnd, yEnd, len, true, false, w, len); } else if (type === AscFormat.LineEndType.vsdxClosedDoubleArrow) { drawArrow(drawer, xPrev, yPrev, xEnd, yEnd, 0, false, false, w, len); drawArrow(drawer, xPrev, yPrev, xEnd, yEnd, len, false, false, w, len); } else if (type === AscFormat.LineEndType.vsdxClosedNoDash) { let shift = 0.75 * len * 0.5; drawCircle(drawer, xPrev, yPrev, xEnd, yEnd, shift, w, len, false); } else if (type === AscFormat.LineEndType.vsdxFilledNoDash) { let shift = 0.75 * len * 0.5; drawCircle(drawer, xPrev, yPrev, xEnd, yEnd, shift, w, len, true); } else if (type === AscFormat.LineEndType.vsdxOpenDoubleArrow) { drawArrow(drawer, xPrev, yPrev, xEnd, yEnd, 0, false, true, w, len); drawArrow(drawer, xPrev, yPrev, xEnd, yEnd, len, false, true, w, len); } else if (type === AscFormat.LineEndType.vsdxOpenArrowSingleDash) { drawArrow(drawer, xPrev, yPrev, xEnd, yEnd, 0, false, true, w, len); let shift = 0.75 * len * 2; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); } else if (type === AscFormat.LineEndType.vsdxOpenDoubleArrowSingleDash) { drawArrow(drawer, xPrev, yPrev, xEnd, yEnd, 0, false, true, w, len); drawArrow(drawer, xPrev, yPrev, xEnd, yEnd, len, false, true, w, len); let shift = 0.75 * len * 2 + len; drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift); } /** * @param {CShapeDrawer} drawer * @param {boolean} isFilled - if not filled it is stroke bcs if both repeat all commands */ function stokeOrFillPath(drawer, isFilled) { if (isFilled) { if (Asc.editor.isPdfEditor()) { let oRGBColor; if (drawer.Shape.GetRGBColor) { oRGBColor = drawer.Shape.GetRGBColor(drawer.Shape.GetFillColor()); } else if (drawer.Shape.group) { oRGBColor = drawer.Shape.group.GetRGBColor(drawer.Shape.group.GetFillColor()); } if (oRGBColor) { drawer.Graphics.m_oPen.Color.R = oRGBColor.r; drawer.Graphics.m_oPen.Color.G = oRGBColor.g; drawer.Graphics.m_oPen.Color.B = oRGBColor.b; } } drawer.drawStrokeFillStyle(); } let isStroke = !isFilled; if (isStroke) { drawer.ds(); } } /** * Draws fork BEFORE line end * @param drawer * @param xPrev * @param yPrev * @param xEnd * @param yEnd */ function drawFork(drawer, xPrev, yPrev, xEnd, yEnd) { var arrowAngle = Math.atan2(yEnd - yPrev, xEnd - xPrev); var perpendicularAngle = arrowAngle - (90 * Math.PI / 180); // Вычисляем координаты конца перпендикулярной линии var perpendicularLength = w / 2; let horLength = w * 0.75; var x1 = xEnd + perpendicularLength * Math.cos(perpendicularAngle); // top right point var y1 = yEnd + perpendicularLength * Math.sin(perpendicularAngle); // top right point var x2 = xEnd - perpendicularLength * Math.cos(perpendicularAngle); // bottom right point var y2 = yEnd - perpendicularLength * Math.sin(perpendicularAngle); // bottom right point let x3 = xEnd - horLength * Math.cos(arrowAngle); // left point let y3 = yEnd - horLength * Math.sin(arrowAngle); // left point drawer._s(); drawer._m(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(x3, y3), trans.TransformPointY(x3, y3)); drawer._l(trans.TransformPointX(x2, y2), trans.TransformPointY(x2, y2)); drawer.ds(); drawer._e(); } /** * Draws vertical line ON line end * @param drawer * @param xPrev * @param yPrev * @param xEnd * @param yEnd * @param shift */ function drawVerticalLine(drawer, xPrev, yPrev, xEnd, yEnd, shift) { let arrowAngle = Math.atan2(yEnd - yPrev, xEnd - xPrev); var drawLineAngle = arrowAngle - (90 * Math.PI / 180); // Вычисляем координаты конца перпендикулярной линии var perpendicularLength = w / 2; var x1 = xEnd + perpendicularLength * Math.cos(drawLineAngle) - shift * Math.cos(arrowAngle); // top right point for visio var y1 = yEnd + perpendicularLength * Math.sin(drawLineAngle) - shift * Math.sin(arrowAngle); // top right point for visio var x2 = xEnd - perpendicularLength * Math.cos(drawLineAngle) - shift * Math.cos(arrowAngle); var y2 = yEnd - perpendicularLength * Math.sin(drawLineAngle) - shift * Math.sin(arrowAngle); drawer._s(); drawer._m(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(x2, y2), trans.TransformPointY(x2, y2)); drawer.ds(); drawer._e(); } /** * Draws center ON line end * @param drawer * @param xPrev * @param yPrev * @param xEnd * @param yEnd * @param shift - horizontal shift distance * @param w * @param len * @param isArrowFilled */ function drawCircle(drawer, xPrev, yPrev, xEnd, yEnd, shift, w, len, isArrowFilled) { len *= 0.75; w *= 0.75; var _ex = xPrev - xEnd; var _ey = yPrev - yEnd; var _elen = Math.sqrt(_ex*_ex + _ey*_ey); _ex /= _elen; // cos a _ey /= _elen; // sin a var _vx = _ey; var _vy = -_ex; var tmpx = xEnd + (len / 2 + shift) * _ex; // left circle point var tmpy = yEnd + (len / 2 + shift) * _ey; // left circle point var tmpx2 = xEnd - (len / 2 - shift) * _ex; // right circle point var tmpy2 = yEnd - (len / 2 - shift) * _ey; // right circle point // left top control point var cx1 = tmpx + _vx * 3*w/4; var cy1 = tmpy + _vy * 3*w/4; // right top control point var cx2 = tmpx2 + _vx * 3*w/4; var cy2 = tmpy2 + _vy * 3*w/4; // left bottom control point var cx3 = tmpx - _vx * 3*w/4; var cy3 = tmpy - _vy * 3*w/4; // right bottom control point var cx4 = tmpx2 - _vx * 3*w/4; var cy4 = tmpy2 - _vy * 3*w/4; drawer._s(); drawer._m(trans.TransformPointX(tmpx, tmpy), trans.TransformPointY(tmpx, tmpy)); drawer._c(trans.TransformPointX(cx1, cy1), trans.TransformPointY(cx1, cy1), trans.TransformPointX(cx2, cy2), trans.TransformPointY(cx2, cy2), trans.TransformPointX(tmpx2, tmpy2), trans.TransformPointY(tmpx2, tmpy2)); drawer._c(trans.TransformPointX(cx4, cy4), trans.TransformPointY(cx4, cy4), trans.TransformPointX(cx3, cy3), trans.TransformPointY(cx3, cy3), trans.TransformPointX(tmpx, tmpy), trans.TransformPointY(tmpx, tmpy)); stokeOrFillPath(drawer, isArrowFilled); drawer._e(); } /** * Draws BEFORE line end * @param drawer * @param xPrev * @param yPrev * @param xEnd * @param yEnd * @param shift */ function drawRhomb(drawer, xPrev, yPrev, xEnd, yEnd, shift) { let isArrowFilled = false; let _ex = xPrev - xEnd; let _ey = yPrev - yEnd; const _elen = Math.sqrt(_ex * _ex + _ey * _ey); _ex /= _elen; // cos a _ey /= _elen; // sin a let isRotated = true; _ex = isRotated? _ex : 1; // cos a _ey = isRotated? _ey : 0; // sin a // a now is 90 - a + invert cos const _vx = _ey; const _vy = -_ex; // (xEnd, yEnd) - right arrow point xEnd = xEnd + shift * _ex; yEnd = yEnd + shift * _ey; let heightScale = 0.5; let widthScale = 1; // middle arrow point const tmpx = xEnd + len * widthScale * _ex; const tmpy = yEnd + len * widthScale * _ey; // (x1, y1) - middle top arrow point const x1 = tmpx + _vx * w * heightScale; const y1 = tmpy + _vy * w * heightScale; // (x2, y2) - middle bottom arrow point const x2 = tmpx - _vx * w * heightScale; const y2 = tmpy - _vy * w * heightScale; // most left point const x3 = tmpx + len * widthScale * _ex; const y3 = tmpy + len * widthScale * _ey; drawer._s(); drawer._m(trans.TransformPointX(xEnd, yEnd), trans.TransformPointY(xEnd, yEnd)); drawer._l(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(x3, y3), trans.TransformPointY(x3, y3)); drawer._l(trans.TransformPointX(x2, y2), trans.TransformPointY(x2, y2)); drawer._z(); stokeOrFillPath(drawer, isArrowFilled); drawer._e(); } /** * Draws arrow BEFORE line end * @param drawer * @param xPrev * @param yPrev * @param xEnd * @param yEnd * @param shift * @param isFilled * @param isOpen * @param w * @param len */ function drawArrow(drawer, xPrev, yPrev, xEnd, yEnd, shift, isFilled, isOpen, w, len) { if (Asc.editor.isPdfEditor() == true) { drawer.CheckDash(); } var _ex = xPrev - xEnd; var _ey = yPrev - yEnd; var _elen = Math.sqrt(_ex*_ex + _ey*_ey); _ex /= _elen; _ey /= _elen; var _vx = _ey; var _vy = -_ex; xEnd += shift * _ex; yEnd += shift * _ey; // (xEnd, yEnd) - right arrow point var tmpx = xEnd + len * _ex; var tmpy = yEnd + len * _ey; // (x1, y1) - top arrow point var x1 = tmpx + _vx * w/2; var y1 = tmpy + _vy * w/2; // (x3, y3) - bottom arrow point var x3 = tmpx - _vx * w/2; var y3 = tmpy - _vy * w/2; drawer._s(); drawer._m(trans.TransformPointX(x1, y1), trans.TransformPointY(x1, y1)); drawer._l(trans.TransformPointX(xEnd, yEnd), trans.TransformPointY(xEnd, yEnd)); drawer._l(trans.TransformPointX(x3, y3), trans.TransformPointY(x3, y3)); if (!isOpen) { drawer._z(); } stokeOrFillPath(drawer, isFilled); drawer._e(); } } function CShapeDrawer() { this.Shape = null; this.Graphics = null; this.UniFill = null; this.Ln = null; this.Transform = null; this.bIsTexture = false; this.bIsNoFillAttack = false; this.bIsNoStrokeAttack = false; this.bDrawSmartAttack = false; this.FillUniColor = null; this.StrokeUniColor = null; this.StrokeWidth = 0; this.min_x = 0xFFFF; this.min_y = 0xFFFF; this.max_x = -0xFFFF; this.max_y = -0xFFFF; this.OldLineJoin = null; this.IsArrowsDrawing = false; this.IsCurrentPathCanArrows = true; this.bIsCheckBounds = false; this.IsRectShape = false; } CShapeDrawer.prototype = { Clear : function() { //this.Shape = null; //this.Graphics = null; this.UniFill = null; this.Ln = null; this.Transform = null; this.bIsTexture = false; this.bIsNoFillAttack = false; this.bIsNoStrokeAttack = false; this.FillUniColor = null; this.StrokeUniColor = null; this.StrokeWidth = 0; this.min_x = 0xFFFF; this.min_y = 0xFFFF; this.max_x = -0xFFFF; this.max_y = -0xFFFF; this.OldLineJoin = null; this.IsArrowsDrawing = false; this.IsCurrentPathCanArrows = true; this.bIsCheckBounds = false; this.IsRectShape = false; }, isPdf : function() { return this.Graphics.isPdf() || this.Graphics.isNativeDrawer(); }, CheckPoint : function(_x,_y) { // TODO: !!! var x = _x; var y = _y; if (false && this.Graphics.MaxEpsLine !== undefined) { x = this.Graphics.Graphics.m_oFullTransform.TransformPointX(_x,_y); y = this.Graphics.Graphics.m_oFullTransform.TransformPointY(_x,_y); } if (x < this.min_x) this.min_x = x; if (y < this.min_y) this.min_y = y; if (x > this.max_x) this.max_x = x; if (y > this.max_y) this.max_y = y; }, CheckDash : function() { if (Asc.editor.isPdfEditor()) { let aDash; if (this.Shape.GetDash) aDash = this.Shape.GetDash(); else if (this.Shape.group && this.Shape.group.GetDash) aDash = this.Shape.group.GetDash(); else if (this.Shape.IsDrawing && this.Shape.IsDrawing()) { if (AscCommon.DashPatternPresets[this.Ln.prstDash]) { aDash = AscCommon.DashPatternPresets[this.Ln.prstDash].slice(); for (var indexD = 0; indexD < aDash.length; indexD++) aDash[indexD] *= 2 * this.StrokeWidth; } } if (aDash) { this.Graphics.p_dash(aDash.map(function(measure) { return measure / 2; })); } } else if (this.Ln.prstDash != null && AscCommon.DashPatternPresets[this.Ln.prstDash]) { var _arr = AscCommon.DashPatternPresets[this.Ln.prstDash].slice(); for (var indexD = 0; indexD < _arr.length; indexD++) _arr[indexD] *= this.StrokeWidth; this.Graphics.p_dash(_arr); } else if (this.isPdf()) { this.Graphics.p_dash(null); } }, fromShape2 : function(shape, graphics, geom) { this.fromShape(shape, graphics); if (!geom && !graphics.bDrawRectWithLines) { this.IsRectShape = true; } else { if (geom.preset == "rect" && !graphics.bDrawRectWithLines) this.IsRectShape = true; } }, fromShape : function(shape, graphics) { this.IsRectShape = false; this.Shape = shape; this.Graphics = graphics; this.UniFill = shape.brush; this.Ln = shape.pen; this.Transform = shape.TransformMatrix; this.min_x = 0xFFFF; this.min_y = 0xFFFF; this.max_x = -0xFFFF; this.max_y = -0xFFFF; var bIsCheckBounds = false; if (this.UniFill == null || this.UniFill.fill == null) this.bIsNoFillAttack = true; else { var _fill = this.UniFill.fill; switch (_fill.type) { case c_oAscFill.FILL_TYPE_BLIP: { this.bIsTexture = true; break; } case c_oAscFill.FILL_TYPE_SOLID: { if(_fill.color) { this.FillUniColor = _fill.color.RGBA; } else { this.FillUniColor = new AscFormat.CUniColor().RGBA; } break; } case c_oAscFill.FILL_TYPE_GRAD: { var _c = _fill.colors; if (_c.length == 0) this.FillUniColor = new AscFormat.CUniColor().RGBA; else { if(_fill.colors[0].color) { this.FillUniColor = _fill.colors[0].color.RGBA; } else { this.FillUniColor = new AscFormat.CUniColor().RGBA; } } bIsCheckBounds = true; break; } case c_oAscFill.FILL_TYPE_PATT: { bIsCheckBounds = true; break; } case c_oAscFill.FILL_TYPE_NOFILL: { this.bIsNoFillAttack = true; break; } default: { this.bIsNoFillAttack = true; break; } } } if (this.Ln == null || this.Ln.Fill == null || this.Ln.Fill.fill == null) { this.bIsNoStrokeAttack = true; } else { var _fill = this.Ln.Fill.fill; switch (_fill.type) { case c_oAscFill.FILL_TYPE_BLIP: { this.StrokeUniColor = new AscFormat.CUniColor().RGBA; break; } case c_oAscFill.FILL_TYPE_SOLID: { if(_fill.color) { this.StrokeUniColor = _fill.color.RGBA; } else { this.StrokeUniColor = new AscFormat.CUniColor().RGBA; } break; } case c_oAscFill.FILL_TYPE_GRAD: { var _c = _fill.colors; if (_c == 0) this.StrokeUniColor = new AscFormat.CUniColor().RGBA; else { if(_fill.colors[0].color) { this.StrokeUniColor = _fill.colors[0].color.RGBA; } else { this.StrokeUniColor = new AscFormat.CUniColor().RGBA; } } break; } case c_oAscFill.FILL_TYPE_PATT: { if(_fill.fgClr) { this.StrokeUniColor = _fill.fgClr.RGBA; } else { this.StrokeUniColor = new AscFormat.CUniColor().RGBA; } break; } case c_oAscFill.FILL_TYPE_NOFILL: { this.bIsNoStrokeAttack = true; break; } default: { this.bIsNoStrokeAttack = true; break; } } this.StrokeWidth = (this.Ln.w == null) ? 12700 : parseInt(this.Ln.w); this.StrokeWidth /= 36000.0; this.p_width(1000 * this.StrokeWidth); this.CheckDash(); if (graphics.isBoundsChecker() && !this.bIsNoStrokeAttack) graphics.LineWidth = this.StrokeWidth; if (this.Graphics.m_oContext != null && this.Ln.Join != null && this.Ln.Join.type != null) this.OldLineJoin = this.Graphics.m_oContext.lineJoin; } if (this.bIsTexture || bIsCheckBounds) { // сначала нужно определить границы this.bIsCheckBounds = true; this.check_bounds(); this.bIsCheckBounds = false; } }, draw : function(geom) { if (this.bIsNoStrokeAttack && this.bIsNoFillAttack) return; var bIsPatt = false; if (this.UniFill != null && this.UniFill.fill != null && ((this.UniFill.fill.type == c_oAscFill.FILL_TYPE_PATT) || (this.UniFill.fill.type == c_oAscFill.FILL_TYPE_GRAD))) { bIsPatt = true; } if (this.isPdf() && (this.bIsTexture || bIsPatt)) { this.Graphics.put_TextureBoundsEnabled(true); this.Graphics.put_TextureBounds(this.min_x, this.min_y, this.max_x - this.min_x, this.max_y - this.min_y); } if(geom) { geom.draw(this); } else { this._s(); this._m(0, 0); this._l(this.Shape.extX, 0); this._l(this.Shape.extX, this.Shape.extY); this._l(0, this.Shape.extY); this._z(); this.drawFillStroke(true, "norm", true && !this.bIsNoStrokeAttack); this._e(); } if (this.isPdf() && (this.bIsTexture || bIsPatt)) { this.Graphics.put_TextureBoundsEnabled(false); } if (this.Graphics.isBoundsChecker() && this.Graphics.AutoCheckLineWidth) { this.Graphics.CorrectBounds2(); } this.Graphics.p_dash(null); }, p_width : function(w) { this.Graphics.p_width(w); }, _m : function(x, y) { if (this.bIsCheckBounds) { this.CheckPoint(x, y); return; } this.Graphics._m(x, y); }, _l : function(x, y) { if (this.bIsCheckBounds) { this.CheckPoint(x, y); return; } this.Graphics._l(x, y); }, _c : function(x1, y1, x2, y2, x3, y3) { if (this.bIsCheckBounds) { this.CheckPoint(x1, y1); this.CheckPoint(x2, y2); this.CheckPoint(x3, y3); return; } this.Graphics._c(x1, y1, x2, y2, x3, y3); }, /** * @param x1 - cpx * @param y1 - cpy * @param x2 - end x * @param y2 - end y */ _c2 : function(x1, y1, x2, y2) { if (this.bIsCheckBounds) { this.CheckPoint(x1, y1); this.CheckPoint(x2, y2); return; } this.Graphics._c2(x1, y1, x2, y2); }, /** * @param {{x: Number, y: Number, z? :Number}} startPoint * @param {{x: Number, y: Number, z? :Number}[]} controlPoints * @param {{x: Number, y: Number, z? :Number}} endPoint */ _cN : function(startPoint, controlPoints, endPoint) { if (this.bIsCheckBounds) { this.CheckPoint(startPoint.x, startPoint.y); controlPoints.forEach(function (controlPoint) { this.CheckPoint(controlPoint.x, controlPoint.y); }) this.CheckPoint(endPoint.x, endPoint.y); return; } this.Graphics._cN(startPoint, controlPoints, endPoint); }, _z : function() { this.IsCurrentPathCanArrows = false; if (this.bIsCheckBounds) return; this.Graphics._z(); }, _s : function() { this.IsCurrentPathCanArrows = true; this.Graphics._s(); }, _e : function() { this.IsCurrentPathCanArrows = true; this.Graphics._e(); }, drawTransitionTextures : function(oCanvas1, dAlpha1, oCanvas2, dAlpha2) { const dOldGlobalAlpha = this.Graphics.m_oContext.globalAlpha; const dX = this.min_x; const dY = this.min_y; const dW = this.max_x - this.min_x; const dH = this.max_y - this.min_y; this.Graphics.m_oContext.globalAlpha = dAlpha1; this.Graphics.drawImage(null, dX, dY, dW, dH, undefined, null, oCanvas1); this.Graphics.m_oContext.globalAlpha = dAlpha2; this.Graphics.drawImage(null, dX, dY, dW, dH, undefined, null, oCanvas2); this.Graphics.m_oContext.globalAlpha = dOldGlobalAlpha; }, drawArrows: function (bIsSaveToPdfMode) { this.IsArrowsDrawing = true; this.Graphics.p_dash(null); const graphicsCtx = this.Graphics.isTrack() && !bIsSaveToPdfMode ? this.Graphics.Graphics : this.Graphics; const fullTransform = bIsSaveToPdfMode ? (this.isPdf() ? this.Graphics.GetTransform() : this.Graphics.m_oFullTransform) : graphicsCtx.m_oFullTransform; const inverseTransform = AscCommon.global_MatrixTransformer.Invert(fullTransform); const point1 = { x: fullTransform.TransformPointX(0, 0), y: fullTransform.TransformPointY(0, 0) }; const point2 = { x: fullTransform.TransformPointX(1, 1), y: fullTransform.TransformPointY(1, 1) }; const transformScaleFactor = Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2)) / Math.sqrt(2); const lineSize = bIsSaveToPdfMode ? (this.isPdf() ? this.Graphics.GetLineWidth() : graphicsCtx.m_oContext.lineWidth) : graphicsCtx.m_oContext.lineWidth; const penWidth = lineSize * transformScaleFactor; const maxWidth = bIsSaveToPdfMode ? 2.5 / AscCommon.g_dKoef_mm_to_pix : (graphicsCtx.IsThumbnail === true ? 2 : undefined); const arrCoef = bIsSaveToPdfMode ? 1 : this.isArrPix ? (1 / AscCommon.g_dKoef_mm_to_pix) : 1; const geometry = this.Shape.getGeometry(); const paths = geometry.getContinuousSubpaths ? geometry.getContinuousSubpaths() : []; if (this.Ln.headEnd != null) { const arrowLength = this.Ln.headEnd.GetLen(penWidth, maxWidth) / transformScaleFactor; for (let i = 0; i < paths.length; i++) { const path = paths[i]; const headAngle = path.getHeadArrowAngle(arrowLength); if (AscFormat.isRealNumber(headAngle)) { // Each continuous subpath starts with a moveTo command // so we can use the first point of the path as the arrow tip point const arrowEndPoint = { x: fullTransform.TransformPointX(path.ArrPathCommand[0].X, path.ArrPathCommand[0].Y), y: fullTransform.TransformPointY(path.ArrPathCommand[0].X, path.ArrPathCommand[0].Y) }; const arrowStartPoint = { x: fullTransform.TransformPointX(path.ArrPathCommand[0].X - Math.cos(headAngle * Math.PI / 180), path.ArrPathCommand[0].Y - Math.sin(headAngle * Math.PI / 180)), y: fullTransform.TransformPointY(path.ArrPathCommand[0].X - Math.cos(headAngle * Math.PI / 180), path.ArrPathCommand[0].Y - Math.sin(headAngle * Math.PI / 180)) }; DrawLineEnd( arrowEndPoint.x, arrowEndPoint.y, arrowStartPoint.x, arrowStartPoint.y, this.Ln.headEnd.type, arrCoef * this.Ln.headEnd.GetWidth(penWidth, maxWidth), arrCoef * this.Ln.headEnd.GetLen(penWidth, maxWidth), this, inverseTransform ); } } } if (this.Ln.tailEnd != null) { const arrowLength = this.Ln.tailEnd.GetLen(penWidth, maxWidth) / transformScaleFactor; for (let i = 0; i < paths.length; i++) { const path = paths[i]; const tailAngle = path.getTailArrowAngle(arrowLength); if (AscFormat.isRealNumber(tailAngle)) { // Each continuous subpath starts with a moveTo command // so we can use the first point of the path as the arrow tip point function getPathEndPoint(commands) { for (let i = commands.length - 1; i >= 0; i--) { const command = commands[i]; if (command.id === AscFormat.lineTo) { return { x: command.X, y: command.Y }; } if (command.id === AscFormat.bezier4) { return { x: command.X2, y: command.Y2 }; } } return null; } const pathEndPoint = getPathEndPoint(path.ArrPathCommand); if (!pathEndPoint) { continue; } const arrowEndPoint = { x: fullTransform.TransformPointX(pathEndPoint.x, pathEndPoint.y), y: fullTransform.TransformPointY(pathEndPoint.x, pathEndPoint.y) }; const arrowStartPoint = { x: fullTransform.TransformPointX(pathEndPoint.x - Math.cos(tailAngle * Math.PI / 180), pathEndPoint.y - Math.sin(tailAngle * Math.PI / 180)), y: fullTransform.TransformPointY(pathEndPoint.x - Math.cos(tailAngle * Math.PI / 180), pathEndPoint.y - Math.sin(tailAngle * Math.PI / 180)) }; DrawLineEnd( arrowEndPoint.x, arrowEndPoint.y, arrowStartPoint.x, arrowStartPoint.y, this.Ln.tailEnd.type, arrCoef * this.Ln.tailEnd.GetWidth(penWidth, maxWidth), arrCoef * this.Ln.tailEnd.GetLen(penWidth, maxWidth), this, inverseTransform ); } } } this.IsArrowsDrawing = false; this.CheckDash(); }, drawBlipFill: function () { const graphics = this.Graphics.isTrack() ? this.Graphics.Graphics : this.Graphics; if (!graphics) return; const imageName = this.UniFill.fill.RasterImageId; const imageUrl = AscCommon.getFullImageSrc2(imageName); const imageData = Asc.editor.ImageLoader.map_image_index[imageUrl]; const isImageLoaded = imageData != undefined && imageData.Image != null && imageData.Status == AscFonts.ImageLoadStatus.Complete; if (!isImageLoaded) return; graphics.save(); graphics.clip(); const isTile = AscCommon.isRealObject(this.UniFill.fill.tile); const isTileSupported = !(AscCommon.AscBrowser.isIE && imageName && imageName.lastIndexOf('.svg') == imageName.length - 4); if (isTile && isTileSupported) { this.drawBlipFillTile(imageData); } else if (this.UniFill.IsTransitionTextures) { this.drawTransitionTextures(this.UniFill.canvas1, this.UniFill.alpha1, this.UniFill.canvas2, this.UniFill.alpha2); } else { this.drawBlipFillStretch(imageData); } graphics.restore(); }, drawBlipFillTile: function (imageData) { const graphics = this.Graphics.isTrack() ? this.Graphics.Graphics : this.Graphics; if (!graphics) return; const transform = this.Shape.getTransformMatrix ? this.Shape.getTransformMatrix() : new AscCommon.CMatrix(); const invertedTransform = AscCommon.global_MatrixTransformer.Invert(transform); const tile = this.UniFill.fill.tile; const rotWithShape = this.UniFill.fill.rotWithShape || this.UniFill.fill.rotWithShape === null; // Scaling const imageDPI = 96; // Image DPI is not supported yet (so we use a fixed value of 96 DPI) const canvasDPI = 96; const scaleCoefX = AscCommon.g_dKoef_pix_to_mm * (canvasDPI / imageDPI); const scaleCoefY = AscCommon.g_dKoef_pix_to_mm * (canvasDPI / imageDPI); const scaleX = tile.sx ? (tile.sx / 1000) / 100 : 1; const scaleY = tile.sy ? (tile.sy / 1000) / 100 : 1; // Offsets (aligning and direct offsets) function getAlignment(key) { switch (key) { case AscCommon.c_oAscRectAlignType.tl: return [0, 0]; case AscCommon.c_oAscRectAlignType.t: return [0.5, 0]; case AscCommon.c_oAscRectAlignType.tr: return [1, 0]; case AscCommon.c_oAscRectAlignType.l: return [0, 0.5]; case AscCommon.c_oAscRectAlignType.ctr: return [0.5, 0.5]; case AscCommon.c_oAscRectAlignType.r: return [1, 0.5]; case AscCommon.c_oAscRectAlignType.bl: return [0, 1]; case AscCommon.c_oAscRectAlignType.b: return [0.5, 1]; case AscCommon.c_oAscRectAlignType.br: return [1, 1]; default: return [0, 0]; } } const align = AscFormat.isRealNumber(tile.algn) && tile.algn >= 0 && tile.algn <= 8 ? tile.algn : AscCommon.c_oAscRectAlignType.tl; // AscCommon.c_oAscRectAlignType let alignOffsetX, alignOffsetY; if (rotWithShape) { const shapeWidth = this.max_x - this.min_x; const shapeHeight = this.max_y - this.min_y; const imageWidth = imageData.Image.width * scaleX * scaleCoefX; const imageHeight = imageData.Image.height * scaleY * scaleCoefY; alignOffsetX = getAlignment(align)[0] * (shapeWidth - imageWidth); alignOffsetY = getAlignment(align)[1] * (shapeHeight - imageHeight); } else { const shapeBounds = this.Shape.getBounds(); const shapeWidth = shapeBounds.w; const shapeHeight = shapeBounds.h; const imageWidth = imageData.Image.width * scaleX * scaleCoefX; const imageHeight = imageData.Image.height * scaleY * scaleCoefY; alignOffsetX = shapeBounds.x + getAlignment(align)[0] * (shapeWidth - imageWidth); alignOffsetY = shapeBounds.y + getAlignment(align)[1] * (shapeHeight - imageHeight); } const offsetX = tile.tx ? tile.tx * AscCommonWord.g_dKoef_emu_to_mm : 0; const offsetY = tile.ty ? tile.ty * AscCommonWord.g_dKoef_emu_to_mm : 0; // Mirroring const flipH = tile.flip === AscFormat.CBlipFillTile.flipTypes.x || tile.flip === AscFormat.CBlipFillTile.flipTypes.xy; const flipV = tile.flip === AscFormat.CBlipFillTile.flipTypes.y || tile.flip === AscFormat.CBlipFillTile.flipTypes.xy; // Opacity const isTransparent = this.UniFill.transparent != null && this.UniFill.transparent != 255; const useTransparency = this.Graphics.isSupportTextDraw() && isTransparent; const alpha = useTransparency ? this.UniFill.transparent / 255 : 1; graphics.drawBlipFillTile( rotWithShape ? null : invertedTransform, imageData.src, alpha, scaleX * scaleCoefX, scaleY * scaleCoefY, offsetX + alignOffsetX, offsetY + alignOffsetY, flipH, flipV ); graphics.m_bPenColorInit = false; graphics.m_bBrushColorInit = false; }, drawBlipFillStretch: function (imageData) { const graphics = this.Graphics.isTrack() ? this.Graphics.Graphics : this.Graphics; if (!graphics) return; const transform = this.Shape.getTransformMatrix ? this.Shape.getTransformMatrix() : new AscCommon.CMatrix(); const invertedTransform = AscCommon.global_MatrixTransformer.Invert(transform); const rotWithShape = this.UniFill.fill.rotWithShape || this.UniFill.fill.rotWithShape === null; // Margins const fillRect = AscCommon.isRealObject(this.UniFill.fill.stretch) && AscCommon.isRealObject(this.UniFill.fill.stretch.fillRect) ? this.UniFill.fill.stretch.fillRect : new AscFormat.CFillRect(0, 0, 100, 100); let dstRect; if (rotWithShape) { const shapeWidth = this.max_x - this.min_x; const shapeHeight = this.max_y - this.min_y; dstRect = { l: this.min_x + shapeWidth * fillRect.l / 100, t: this.min_y + shapeHeight * fillRect.t / 100, r: this.max_x - shapeWidth * (100 - fillRect.r) / 100, b: this.max_y - shapeHeight * (100 - fillRect.b) / 100, }; } else { const shapeBounds = this.Shape.getBounds(); const shapeWidth = shapeBounds.w; const shapeHeight = shapeBounds.h; dstRect = { l: shapeBounds.x + shapeWidth * (fillRect.l / 100), t: shapeBounds.y + shapeHeight * (fillRect.t / 100), r: shapeBounds.x + shapeWidth - shapeWidth * (100 - fillRect.r) / 100, b: shapeBounds.y + shapeHeight - shapeHeight * (100 - fillRect.b) / 100, }; } // Opacity const isTransparent = this.UniFill.transparent != null && this.UniFill.transparent != 255; const useTransparency = this.IsRectShape ? true : graphics.isSupportTextDraw() && !graphics.isTrack(); const alpha = (isTransparent && useTransparency) ? this.UniFill.transparent / 255 : 1; // this.UniFill.fill.srcRect === this.Shape.brush.fill.srcRect === this.Shape.blipFill.srcRect const srcRect = this.UniFill.fill.srcRect; graphics.drawBlipFillStretch( rotWithShape ? null : invertedTransform, imageData.src, alpha, dstRect.l, dstRect.t, dstRect.r - dstRect.l, dstRect.b - dstRect.t, srcRect, this.UniFill.fill.canvas ); }, df: function (mode) { if (mode == "none" || this.bIsNoFillAttack) return; if (this.Graphics.isTrack()) this.Graphics.m_oOverlay.ClearAll = true; if (this.Graphics.isBoundsChecker() === true) return; var bIsIntegerGridTRUE = false; if (this.bIsTexture) { if (this.Graphics.m_bIntegerGrid === true) { this.Graphics.SetIntegerGrid(false); bIsIntegerGridTRUE = true; } if (this.isPdf()) { const image = getFullImageSrc2(this.UniFill.fill.RasterImageId); const type = this.UniFill.fill.tile != null && this.Graphics.m_oContext !== undefined ? 1 : 0; this.Graphics.put_brushTexture(image, type); } else { this.drawBlipFill(); } if (bIsIntegerGridTRUE) { this.Graphics.SetIntegerGrid(true); } return; } if (this.UniFill != null && this.UniFill.fill != null) { var _fill = this.UniFill.fill; if (_fill.type == c_oAscFill.FILL_TYPE_PATT) { if (this.Graphics.m_bIntegerGrid === true) { this.Graphics.SetIntegerGrid(false); bIsIntegerGridTRUE = true; } var _is_ctx = false; if (!this.Graphics.isSupportTextDraw() || undefined === this.Graphics.m_oContext || (null == this.UniFill.transparent) || (this.UniFill.transparent == 255)) { _is_ctx = false; } else { _is_ctx = true; } var _gr = this.Graphics.isTrack() ? this.Graphics.Graphics : this.Graphics; var _ctx = _gr.m_oContext; var _patt_name = AscCommon.global_hatch_names[_fill.ftype]; if (undefined == _patt_name) _patt_name = "cross"; var _fc = _fill.fgClr && _fill.fgClr.RGBA || {R: 0, G: 0, B: 0, A: 255}; var _bc = _fill.bgClr && _fill.bgClr.RGBA || {R: 255, G: 255, B: 255, A: 255}; var __fa = (null === this.UniFill.transparent) ? _fc.A : 255; var __ba = (null === this.UniFill.transparent) ? _bc.A : 255; var _test_pattern = AscCommon.GetHatchBrush(_patt_name, _fc.R, _fc.G, _fc.B, __fa, _bc.R, _bc.G, _bc.B, __ba); var patt = _ctx.createPattern(_test_pattern.Canvas, "repeat"); _ctx.save(); const editorInfo = this.getEditorInfo(); var koefX = editorInfo.scale; var koefY = editorInfo.scale; if (this.Graphics.IsThumbnail) { koefX = 1; koefY = 1; } // TODO: !!! _ctx.translate(this.min_x, this.min_y); if (this.Graphics.MaxEpsLine === undefined) { _ctx.scale(koefX * this.Graphics.TextureFillTransformScaleX, koefY * this.Graphics.TextureFillTransformScaleY); } else { _ctx.scale(koefX * this.Graphics.Graphics.TextureFillTransformScaleX, koefY * this.Graphics.Graphics.TextureFillTransformScaleY); } if (_is_ctx === true) { var _old_global_alpha = _ctx.globalAlpha; if (null != this.UniFill.transparent) _ctx.globalAlpha = this.UniFill.transparent / 255; _ctx.fillStyle = patt; _ctx.fill(); _ctx.globalAlpha = _old_global_alpha; } else { _ctx.fillStyle = patt; _ctx.fill(); } _ctx.restore(); _gr.m_bPenColorInit = false; _gr.m_bBrushColorInit = false; if (bIsIntegerGridTRUE) { this.Graphics.SetIntegerGrid(true); } return; } else if (_fill.type == c_oAscFill.FILL_TYPE_GRAD) { if (this.Graphics.m_bIntegerGrid === true) { this.Graphics.SetIntegerGrid(false); bIsIntegerGridTRUE = true; } var _is_ctx = false; if (!this.Graphics.isSupportTextDraw() || undefined === this.Graphics.m_oContext || (null == this.UniFill.transparent) || (this.UniFill.transparent == 255)) { _is_ctx = false; } else { _is_ctx = true; } var _gr = this.Graphics.isTrack() ? this.Graphics.Graphics : this.Graphics; var _ctx = _gr.m_oContext; var gradObj = null; if (_fill.lin) { var _angle = _fill.lin.angle; if (_fill.rotateWithShape === false) { var matrix_transform = this.Graphics.isTrack() ? this.Graphics.Graphics.m_oTransform : this.Graphics.m_oTransform; if (matrix_transform) { //_angle -= (60000 * this.Graphics.m_oTransform.GetRotation()); _angle = AscCommon.GradientGetAngleNoRotate(_angle, matrix_transform); } } var points = this.getGradientPoints(this.min_x, this.min_y, this.max_x, this.max_y, _angle, _fill.lin.scale); gradObj = _ctx.createLinearGradient(points.x0, points.y0, points.x1, points.y1); } else if (_fill.path) { var _cx = (this.min_x + this.max_x) / 2; var _cy = (this.min_y + this.max_y) / 2; var _r = Math.max(this.max_x - this.min_x, this.max_y - this.min_y) / 2; gradObj = _ctx.createRadialGradient(_cx, _cy, 1, _cx, _cy, _r); } else { //gradObj = _ctx.createLinearGradient(this.min_x, this.min_y, this.max_x, this.min_y); var points = this.getGradientPoints(this.min_x, this.min_y, this.max_x, this.max_y, 0, false); gradObj = _ctx.createLinearGradient(points.x0, points.y0, points.x1, points.y1); } const nTransparent = this.UniFill.transparent; let bUseGlobalAlpha = (null !== nTransparent && undefined !== nTransparent); const aColors = _fill.colors; const nClrCount = aColors.length; if(_fill.path && AscCommon.AscBrowser.isMozilla && bUseGlobalAlpha) { bUseGlobalAlpha = false; const dTransparent = nTransparent / 255.0; for (let nClr = 0; nClr < nClrCount; nClr++) { let oClr = aColors[nClr]; gradObj.addColorStop(oClr.pos / 100000, oClr.color.getCSSWithTransparent(dTransparent)); } } else { for (let nClr = 0; nClr < nClrCount; nClr++) { let oClr = aColors[nClr]; gradObj.addColorStop(oClr.pos / 100000, oClr.color.getCSSColor(nTransparent)); } } _ctx.fillStyle = gradObj; if (bUseGlobalAlpha) { var _old_global_alpha = this.Graphics.m_oContext.globalAlpha; _ctx.globalAlpha = this.UniFill.transparent / 255; _ctx.fill(); _ctx.globalAlpha = _old_global_alpha; } else { _ctx.fill(); } _gr.m_bPenColorInit = false; _gr.m_bBrushColorInit = false; if (bIsIntegerGridTRUE) { this.Graphics.SetIntegerGrid(true); } return; } } var rgba = this.FillUniColor; if (mode == "darken") { var _color1 = new CShapeColor(rgba.R, rgba.G, rgba.B); var rgb = _color1.darken(); rgba = { R: rgb.r, G: rgb.g, B: rgb.b, A: rgba.A }; } else if (mode == "darkenLess") { var _color1 = new CShapeColor(rgba.R, rgba.G, rgba.B); var rgb = _color1.darkenLess(); rgba = { R: rgb.r, G: rgb.g, B: rgb.b, A: rgba.A }; } else if (mode == "lighten") { var _color1 = new CShapeColor(rgba.R, rgba.G, rgba.B); var rgb = _color1.lighten(); rgba = { R: rgb.r, G: rgb.g, B: rgb.b, A: rgba.A }; } else if (mode == "lightenLess") { var _color1 = new CShapeColor(rgba.R, rgba.G, rgba.B); var rgb = _color1.lightenLess(); rgba = { R: rgb.r, G: rgb.g, B: rgb.b, A: rgba.A }; } if(rgba) { if (this.UniFill != null && this.UniFill.transparent != null) rgba.A = this.UniFill.transparent; this.Graphics.b_color1(rgba.R, rgba.G, rgba.B, rgba.A); } this.Graphics.df(); }, isArrowPresent: function() { if(this.IsCurrentPathCanArrows && this.Ln && this.Ln.isArrowPresent() && !this.IsArrowsDrawing) return true; return false; }, ds : function() { if (this.bIsNoStrokeAttack) return; if (this.Graphics.isTrack()) this.Graphics.m_oOverlay.ClearAll = true; if (null != this.OldLineJoin && !this.IsArrowsDrawing) { switch (this.Ln.Join.type) { case AscFormat.LineJoinType.Round: { this.Graphics.m_oContext.lineJoin = "round"; break; } case AscFormat.LineJoinType.Bevel: { this.Graphics.m_oContext.lineJoin = "bevel"; break; } case AscFormat.LineJoinType.Empty: { this.Graphics.m_oContext.lineJoin = "miter"; break; } case AscFormat.LineJoinType.Miter: { this.Graphics.m_oContext.lineJoin = "miter"; break; } } } var isArrowsPresent = this.isArrowPresent(); var rgba = this.StrokeUniColor; let nAlpha = 0xFF; if(!isArrowsPresent && !this.IsArrowsDrawing || Asc.editor.isPdfEditor() || this.Shape.isShadowSp) { if (this.Ln && this.Ln.Fill != null && this.Ln.Fill.transparent != null) nAlpha = this.Ln.Fill.transparent; } this.Graphics.p_color(rgba.R, rgba.G, rgba.B, nAlpha); if (this.IsRectShape && this.Graphics.AddSmartRect !== undefined) { if (undefined !== this.Shape.extX) this.Graphics.AddSmartRect(0, 0, this.Shape.extX, this.Shape.extY, this.StrokeWidth); else this.Graphics.ds(); } else { this.Graphics.ds(); } if (null != this.OldLineJoin && !this.IsArrowsDrawing) { this.Graphics.m_oContext.lineJoin = this.OldLineJoin; } if (isArrowsPresent) { const bIsSaveToPdfMode = false; this.drawArrows(bIsSaveToPdfMode); } }, drawFillStroke : function(bIsFill, fill_mode, bIsStroke) { if (this.Graphics.isTrack()) this.Graphics.m_oOverlay.ClearAll = true; if(this.Graphics.isBoundsChecker()) return; if (!this.isPdf()) { if (bIsFill) this.df(fill_mode); if (bIsStroke) this.ds(); } else { if (this.bIsNoStrokeAttack) bIsStroke = false; var isArrowsPresent = this.isArrowPresent(); if (bIsStroke) { if (null != this.OldLineJoin && !this.IsArrowsDrawing) { this.Graphics.put_PenLineJoin(AscFormat.ConvertJoinAggType(this.Ln.Join.type)); } var rgba = this.StrokeUniColor; let nAlpha = 0xFF; if(!isArrowsPresent && !this.IsArrowsDrawing) { if (this.Ln && this.Ln.Fill != null && this.Ln.Fill.transparent != null) nAlpha = this.Ln.Fill.transparent; } this.Graphics.p_color(rgba.R, rgba.G, rgba.B, nAlpha); } if (fill_mode == "none" || this.bIsNoFillAttack) bIsFill = false; var bIsPattern = false; if (bIsFill) { if (this.bIsTexture) { if (null == this.UniFill.fill.tile) { if (null == this.UniFill.fill.srcRect) { if (this.UniFill.fill.RasterImageId && this.UniFill.fill.RasterImageId.indexOf(".svg") != 0) { this.Graphics.put_brushTexture(getFullImageSrc2(this.UniFill.fill.RasterImageId), 0); } else { if (this.UniFill.fill.canvas) { this.Graphics.put_brushTexture(this.UniFill.fill.canvas.toDataURL("image/png"), 0); } else { this.Graphics.put_brushTexture(getFullImageSrc2(this.UniFill.fill.RasterImageId), 0); } } } else { if (this.IsRectShape) { this.Graphics.drawImage(getFullImageSrc2(this.UniFill.fill.RasterImageId), this.min_x, this.min_y, (this.max_x - this.min_x), (this.max_y - this.min_y), undefined, this.UniFill.fill.srcRect); bIsFill = false; } else { // TODO: support srcRect this.Graphics.put_brushTexture(getFullImageSrc2(this.UniFill.fill.RasterImageId), 0); } } } else { if (this.UniFill.fill.canvas) { this.Graphics.put_brushTexture(this.UniFill.fill.canvas.toDataURL("image/png"), 1); } else { this.Graphics.put_brushTexture(getFullImageSrc2(this.UniFill.fill.RasterImageId), 1); } } this.Graphics.put_BrushTextureAlpha(this.UniFill.transparent); } else { var _fill = this.UniFill.fill; if (_fill.type == c_oAscFill.FILL_TYPE_PATT) { var _patt_name = AscCommon.global_hatch_names[_fill.ftype]; if (undefined == _patt_name) _patt_name = "cross"; var _fc = _fill.fgClr && _fill.fgClr.RGBA || {R: 0, G: 0, B: 0, A: 255}; var _bc = _fill.bgClr && _fill.bgClr.RGBA || {R: 255, G: 255, B: 255, A: 255}; var __fa = (null === this.UniFill.transparent) ? _fc.A : 255; var __ba = (null === this.UniFill.transparent) ? _bc.A : 255; var _pattern = AscCommon.GetHatchBrush(_patt_name, _fc.R, _fc.G, _fc.B, __fa, _bc.R, _bc.G, _bc.B, __ba); var _url64 = ""; try { _url64 = _pattern.toDataURL(); } catch (err) { _url64 = ""; } this.Graphics.put_brushTexture(_url64, 1); if (null != this.UniFill.transparent) this.Graphics.put_BrushTextureAlpha(this.UniFill.transparent); else this.Graphics.put_BrushTextureAlpha(255); bIsPattern = true; } else if (_fill.type == c_oAscFill.FILL_TYPE_GRAD) { var points = null; if (_fill.lin) { var _angle = _fill.lin.angle; if (_fill.rotateWithShape === false && this.Graphics.m_oTransform) { //_angle -= (60000 * this.Graphics.m_oTransform.GetRotation()); _angle = AscCommon.GradientGetAngleNoRotate(_angle, this.Graphics.m_oTransform); } points = this.getGradientPoints(this.min_x, this.min_y, this.max_x, this.max_y, _angle, _fill.lin.scale); } else if (_fill.path) { var _cx = (this.min_x + this.max_x) / 2; var _cy = (this.min_y + this.max_y) / 2; var _r = Math.max(this.max_x - this.min_x, this.max_y - this.min_y) / 2; points = { x0 : _cx, y0 : _cy, x1 : _cx, y1 : _cy, r0 : 1, r1 : _r }; } else { points = this.getGradientPoints(this.min_x, this.min_y, this.max_x, this.max_y, 0, false); } this.Graphics.put_BrushGradient(_fill, points, this.UniFill.transparent); } else { var rgba = this.FillUniColor; if (fill_mode == "darken") { var _color1 = new CShapeColor(rgba.R, rgba.G, rgba.B); var rgb = _color1.darken(); rgba = { R: rgb.r, G: rgb.g, B: rgb.b, A: rgba.A }; } else if (fill_mode == "darkenLess") { var _color1 = new CShapeColor(rgba.R, rgba.G, rgba.B); var rgb = _color1.darkenLess(); rgba = { R: rgb.r, G: rgb.g, B: rgb.b, A: rgba.A }; } else if (fill_mode == "lighten") { var _color1 = new CShapeColor(rgba.R, rgba.G, rgba.B); var rgb = _color1.lighten(); rgba = { R: rgb.r, G: rgb.g, B: rgb.b, A: rgba.A }; } else if (fill_mode == "lightenLess") { var _color1 = new CShapeColor(rgba.R, rgba.G, rgba.B); var rgb = _color1.lightenLess(); rgba = { R: rgb.r, G: rgb.g, B: rgb.b, A: rgba.A }; } if (rgba) { if (this.UniFill != null && this.UniFill.transparent != null) rgba.A = this.UniFill.transparent; this.Graphics.b_color1(rgba.R, rgba.G, rgba.B, rgba.A); } } } } if (bIsFill && bIsStroke) { if (this.bIsTexture || bIsPattern) { this.Graphics.drawpath(256); this.Graphics.drawpath(1); } else { this.Graphics.drawpath(256 + 1); } } else if (bIsFill) { this.Graphics.drawpath(256); } else if (bIsStroke) { this.Graphics.drawpath(1); } else if (false) { // такого быть не должно по идее this.Graphics.b_color1(0, 0, 0, 0); this.Graphics.drawpath(256); } if (isArrowsPresent) { const bIsSaveToPdfMode = true; this.drawArrows(bIsSaveToPdfMode); } } }, drawStrokeFillStyle : function() { if (!this.isPdf()) { var gr = this.Graphics.isTrack() ? this.Graphics.Graphics : this.Graphics; var tmp = gr.m_oBrush.Color1; var p_c = gr.m_oPen.Color; gr.b_color1(p_c.R, p_c.G, p_c.B, p_c.A); gr.df(); gr.b_color1(tmp.R, tmp.G, tmp.B, tmp.A); } else { var tmp = this.Graphics.GetBrush().Color1; var p_c = this.Graphics.GetPen().Color; this.Graphics.b_color1(p_c.R, p_c.G, p_c.B, p_c.A); this.Graphics.df(); this.Graphics.b_color1(tmp.R, tmp.G, tmp.B, tmp.A); } }, check_bounds : function() { this.Shape.check_bounds(this); }, // common funcs getNormalPoint : function(x0, y0, angle, x1, y1) { return AscCommon.getNormalPoint(x0, y0, angle, x1, y1); }, getGradientPoints : function(min_x, min_y, max_x, max_y, _angle, scale) { return AscCommon.getGradientPoints(min_x, min_y, max_x, max_y, _angle, scale); }, DrawPresentationComment : function(type, x, y, w, h) { }, getEditorInfo: function() { var _ret = {}; _ret.editor = Asc.editor || window.editor; switch (_ret.editor.editorId) { case AscCommon.c_oEditorId.Word: case AscCommon.c_oEditorId.Presentation: { _ret.scale = _ret.editor.WordControl.m_nZoomValue / 100; break; } case AscCommon.c_oEditorId.Spreadsheet: { _ret.scale = _ret.editor.asc_getZoom(); break; } default: break; } return _ret; } }; function ShapeToImageConverter(shape, pageIndex, sImageFormat) { AscCommon.IsShapeToImageConverter = true; var _bounds_cheker = new AscFormat.CSlideBoundsChecker(); var dKoef = AscCommon.g_dKoef_mm_to_pix; var w_mm = 210; var h_mm = 297; var w_px = (w_mm * dKoef) >> 0; var h_px = (h_mm * dKoef) >> 0; _bounds_cheker.init(w_px, h_px, w_mm, h_mm); _bounds_cheker.transform(1,0,0,1,0,0); _bounds_cheker.AutoCheckLineWidth = true; _bounds_cheker.CheckLineWidth(shape); shape.draw(_bounds_cheker, /*pageIndex*/0); _bounds_cheker.CorrectBounds2(); var _need_pix_width = _bounds_cheker.Bounds.max_x - _bounds_cheker.Bounds.min_x + 1; var _need_pix_height = _bounds_cheker.Bounds.max_y - _bounds_cheker.Bounds.min_y + 1; if (_need_pix_width <= 0 || _need_pix_height <= 0) return null; /* if (shape.pen) { var _w_pen = (shape.pen.w == null) ? 12700 : parseInt(shape.pen.w); _w_pen /= 36000.0; _w_pen *= g_dKoef_mm_to_pix; _need_pix_width += (2 * _w_pen); _need_pix_height += (2 * _w_pen); _bounds_cheker.Bounds.min_x -= _w_pen; _bounds_cheker.Bounds.min_y -= _w_pen; }*/ var _canvas = null; if (window["NATIVE_EDITOR_ENJINE"] === true && window["IS_NATIVE_EDITOR"] !== true) { _need_pix_width = _need_pix_width >> 0; _need_pix_height = _need_pix_height >> 0; _canvas = new CNativeGraphics(); _canvas.width = _need_pix_width; _canvas.height = _need_pix_height; _canvas.create(window["native"], _need_pix_width, _need_pix_height, _need_pix_width / dKoef, _need_pix_height / dKoef); _canvas.CoordTransformOffset(-_bounds_cheker.Bounds.min_x, -_bounds_cheker.Bounds.min_y); _canvas.transform(1, 0, 0, 1, 0, 0); shape.draw(_canvas, 0); } else { _canvas = document.createElement("canvas"); _canvas.width = _need_pix_width >> 0; _canvas.height = _need_pix_height >> 0; var _ctx = _canvas.getContext("2d"); var g = new AscCommon.CGraphics; g.init(_ctx, w_px, h_px, w_mm, h_mm); g.m_oFontManager = AscCommon.g_fontManager; g.m_oCoordTransform.tx = -_bounds_cheker.Bounds.min_x; g.m_oCoordTransform.ty = -_bounds_cheker.Bounds.min_y; g.transform(1, 0, 0, 1, 0, 0); shape.draw(g, 0); } if (AscCommon.g_fontManager) { AscCommon.g_fontManager.m_pFont = null; } if (AscCommon.g_fontManager2) { AscCommon.g_fontManager2.m_pFont = null; } AscCommon.IsShapeToImageConverter = false; var _ret = { ImageNative : _canvas, ImageUrl : "" }; try { const sFormat = sImageFormat || "image/png"; _ret.ImageUrl = _canvas.toDataURL(sFormat); } catch (err) { if (shape.brush != null && shape.brush.fill && shape.brush.fill.RasterImageId) _ret.ImageUrl = getFullImageSrc2(shape.brush.fill.RasterImageId); else _ret.ImageUrl = ""; } if (_canvas.isNativeGraphics === true) _canvas.Destroy(); return _ret; } //------------------------------------------------------------export---------------------------------------------------- window['AscCommon'] = window['AscCommon'] || {}; window['AscCommon'].CShapeDrawer = CShapeDrawer; window['AscCommon'].ShapeToImageConverter = ShapeToImageConverter; window['AscCommon'].IsShapeToImageConverter = false; window['AscCommon'].DrawLineEnd = DrawLineEnd; })(window);