Files
Yajbir Singh f1b860b25c
Some checks failed
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

651 lines
26 KiB
JavaScript

/*
* (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 HitInBezier4 = AscFormat.HitInBezier4;
// arcTo new version
function Arc3(ctx, fX, fY, fWidth, fHeight, fStartAngle, fSweepAngle, ellipseRotation)
{
// Params transform
var sin1 = Math.sin(fStartAngle);
var cos1 = Math.cos(fStartAngle);
var __x = cos1 / fWidth;
var __y = sin1 / fHeight;
var l = 1 / Math.sqrt(__x * __x + __y * __y);
var cx = fX - l * cos1;
var cy = fY - l * sin1;
// ellipseRotation can be undefined in old version calls and it is passed down anyway
Arc2(ctx, cx - fWidth, cy - fHeight, 2 * fWidth, 2 * fHeight, fStartAngle, fSweepAngle, ellipseRotation);
}
function Arc2(ctx, fX, fY, fWidth, fHeight, fStartAngle, fSweepAngle, ellipseRotation)
{
// Calls Ellipse or EllipseArc
if (0 >= fWidth || 0 >= fHeight)
return;
fStartAngle = -fStartAngle;
fSweepAngle = -fSweepAngle;
if (false /*is path closed*/ )
{
var fStartX = fX + fWidth / 2.0 + fWidth / 2 * Math.cos( AngToEllPrm( fStartAngle, fWidth / 2, fHeight / 2 ) );
var fStartY = fY + fHeight / 2.0 - fHeight / 2 * Math.sin( AngToEllPrm ( fStartAngle, fWidth / 2, fHeight / 2 ) );
if ( fSweepAngle < (2 * Math.PI) )
{
ctx._m(fStartX, fStartY);
}
}
var bClockDirection = false;
var fEndAngle = (2 * Math.PI) -(fSweepAngle + fStartAngle);
var fSrtAngle = (2 * Math.PI) - fStartAngle;
// by this moment we have endAngle( = fEndAngle) and startAngle( = fSrtAngle) clockwise
if( fSweepAngle > 0 )
bClockDirection = true;
if(Math.abs(fSweepAngle) >= (2 * Math.PI))
{
Ellipse(ctx, fX + fWidth / 2, fY + fHeight / 2, fWidth / 2, fHeight / 2);
}
else
{
EllipseArc(ctx, fX + fWidth / 2, fY + fHeight / 2, fWidth / 2, fHeight / 2, fSrtAngle, fEndAngle, bClockDirection, ellipseRotation);
}
}
function AngToEllPrm(fAngle, fXRad, fYRad)
{
// to ellipse parametric equation angle parameter - t
// https://www.mathopenref.com/coordparamellipse.html
return Math.atan2( Math.sin( fAngle ) / fYRad, Math.cos( fAngle ) / fXRad );
}
function Ellipse(ctx, fX, fY, fXRad, fYRad)
{
ctx._m(fX - fXRad, fY);
var c_fKappa = 0.552;
ctx._c(fX - fXRad, fY + fYRad * c_fKappa, fX - fXRad * c_fKappa, fY + fYRad, fX, fY + fYRad);
ctx._c(fX + fXRad * c_fKappa, fY + fYRad, fX + fXRad, fY + fYRad * c_fKappa, fX + fXRad, fY);
ctx._c(fX + fXRad, fY - fYRad * c_fKappa, fX + fXRad * c_fKappa, fY - fYRad, fX, fY - fYRad);
ctx._c(fX - fXRad * c_fKappa, fY - fYRad, fX - fXRad, fY - fYRad * c_fKappa, fX - fXRad, fY);
}
function EllipseArc(ctx, fX, fY, fXRad, fYRad, fAngle1, fAngle2, bClockDirection, ellipseRotation)
{
// If arc comes through 0 angle - splits one to two EllipseArc2 calls
while ( fAngle1 < 0 )
fAngle1 += (2 * Math.PI);
while ( fAngle1 > (2 * Math.PI) )
fAngle1 -= (2 * Math.PI);
while ( fAngle2 < 0 )
fAngle2 += (2 * Math.PI);
while ( fAngle2 >= (2 * Math.PI) )
fAngle2 -= (2 * Math.PI);
let rotatePoint;
// fX = cx, fY = cy, fAngle1 = startAngle, fAngle2 = endAngle
// rotatePoint added later for ellipse rotation. it is arc start point.
// it is not used if ellipseRotation not used
if (ellipseRotation !== undefined) {
rotatePoint = {x : fX + fXRad * Math.cos( AngToEllPrm( fAngle1, fXRad, fYRad ) ),
y : fY + fYRad * Math.sin( AngToEllPrm( fAngle1, fXRad, fYRad ) )};
}
// let rotatePoint = {x : fX - fXRad, y : fY};
if ( !bClockDirection )
{
if ( fAngle1 <= fAngle2 )
EllipseArc2(ctx, fX, fY, fXRad, fYRad, fAngle1, fAngle2, false, ellipseRotation, rotatePoint);
else
{
// if arc comes through 0 angle - split it
EllipseArc2(ctx, fX, fY, fXRad, fYRad, fAngle1, 2 * Math.PI, false, ellipseRotation, rotatePoint);
EllipseArc2(ctx, fX, fY, fXRad, fYRad, 0, fAngle2, false, ellipseRotation, rotatePoint);
}
}
else
{
if ( fAngle1 >= fAngle2 )
EllipseArc2(ctx, fX, fY, fXRad, fYRad, fAngle1, fAngle2, true, ellipseRotation, rotatePoint);
else
{
// if arc comes through 0 angle - split it
EllipseArc2(ctx, fX, fY, fXRad, fYRad, fAngle1, 0, true, ellipseRotation, rotatePoint);
EllipseArc2(ctx, fX, fY, fXRad, fYRad, 2 * Math.PI, fAngle2, true, ellipseRotation, rotatePoint);
}
}
}
function EllipseArc2(ctx, fX, fY, fXRad, fYRad, dAngle1, dAngle2, bClockDirection, ellipseRotation, rotatePoint)
{
// Splits calls to EllipseArc3 on each quadrant
var nFirstPointQuard = ((2 * dAngle1 / Math.PI) >> 0) + 1;
var nSecondPointQuard = ((2 * dAngle2 / Math.PI) >> 0) + 1;
nSecondPointQuard = Math.min( 4, Math.max( 1, nSecondPointQuard ) );
nFirstPointQuard = Math.min( 4, Math.max( 1, nFirstPointQuard ) );
// fX = cx, fY = cy, fAngle1 = startAngle, fAngle2 = endAngle
var fStartX = fX + fXRad * Math.cos( AngToEllPrm( dAngle1, fXRad, fYRad ) );
var fStartY = fY + fYRad * Math.sin( AngToEllPrm( dAngle1, fXRad, fYRad ) );
var EndPoint = {X: 0, Y: 0};
//ctx._l(fStartX, fStartY);
var fCurX = fStartX, fCurY = fStartY;
var dStartAngle = dAngle1;
var dEndAngle = 0;
if ( !bClockDirection )
{
for( var nIndex = nFirstPointQuard; nIndex <= nSecondPointQuard; nIndex++ )
{
if ( nIndex == nSecondPointQuard )
dEndAngle = dAngle2;
else
dEndAngle = nIndex * Math.PI / 2;
if ( !( nIndex == nFirstPointQuard ) )
dStartAngle = (nIndex - 1 ) * Math.PI / 2;
EndPoint = EllipseArc3(ctx, fX, fY, fXRad, fYRad, AngToEllPrm( dStartAngle, fXRad, fYRad ), AngToEllPrm( dEndAngle, fXRad, fYRad ), false, ellipseRotation, rotatePoint);
}
}
else
{
for( var nIndex = nFirstPointQuard; nIndex >= nSecondPointQuard; nIndex-- )
{
if ( nIndex == nFirstPointQuard )
dStartAngle = dAngle1;
else
dStartAngle = nIndex * Math.PI / 2;
if ( !( nIndex == nSecondPointQuard ) )
dEndAngle = (nIndex - 1 ) * Math.PI / 2;
else
dEndAngle = dAngle2;
EndPoint = EllipseArc3(ctx, fX, fY, fXRad, fYRad, AngToEllPrm( dStartAngle, fXRad, fYRad ), AngToEllPrm( dEndAngle, fXRad, fYRad ), false, ellipseRotation, rotatePoint);
}
}
}
function EllipseArc3(ctx, fX, fY, fXRad, fYRad, dAngle1, dAngle2, bClockDirection, ellipseRotation, rotatePoint)
{
// fX = cx, fY = cy, fAngle1 = startAngle after AngToEllPrm, fAngle2 = endAngle after AngToEllPrm
var fAlpha = Math.sin( dAngle2 - dAngle1 ) * ( Math.sqrt( 4.0 + 3.0 * Math.tan( (dAngle2 - dAngle1) / 2.0 ) * Math.tan( (dAngle2 - dAngle1) / 2.0 ) ) - 1.0 ) / 3.0;
var sin1 = Math.sin(dAngle1);
var cos1 = Math.cos(dAngle1);
var sin2 = Math.sin(dAngle2);
var cos2 = Math.cos(dAngle2);
// calculate start point
var fX1 = fX + fXRad * cos1;
var fY1 = fY + fYRad * sin1;
// calculate end point
var fX2 = fX + fXRad * cos2;
var fY2 = fY + fYRad * sin2;
// bezier control point 1
var fCX1 = fX1 - fAlpha * fXRad * sin1;
var fCY1 = fY1 + fAlpha * fYRad * cos1;
// bezier control point 2
var fCX2 = fX2 + fAlpha * fXRad * sin2;
var fCY2 = fY2 - fAlpha * fYRad * cos2;
if (ellipseRotation !== undefined) {
// https://www.figma.com/file/hs43oiAUyuoqFULVoJ5lyZ/EllipticArcConvert?type=design&node-id=265-2&mode=design&t=pla9h2OkZAde8Xim-0
// ellipseRotation = 0;
// TODO import
/**
* afin rotate clockwise
* @param {number} x
* @param {number} y
* @param {number} radiansRotateAngle radians Rotate AntiClockWise Angle. E.g. 30 degrees rotates does DOWN.
* @returns {{x: number, y: number}} point
*/
function rotatePointAroundCordsStartClockWise(x, y, radiansRotateAngle) {
let newX = x * Math.cos(radiansRotateAngle) + y * Math.sin(radiansRotateAngle);
let newY = x * (-1) * Math.sin(radiansRotateAngle) + y * Math.cos(radiansRotateAngle);
return {x : newX, y: newY};
}
let startPointRelative = {x : fX1 - rotatePoint.x, y : rotatePoint.y - fY1};
let endPointRelative = {x : fX2 - rotatePoint.x, y : rotatePoint.y - fY2};
let controlPoint1Relative = {x : fCX1 - rotatePoint.x, y : rotatePoint.y - fCY1};
let controlPoint2Relative = {x : fCX2 - rotatePoint.x, y : rotatePoint.y - fCY2};
let startPointRelativeRotated = rotatePointAroundCordsStartClockWise(startPointRelative.x, startPointRelative.y, ellipseRotation);
let endPointRelativeRotated = rotatePointAroundCordsStartClockWise(endPointRelative.x, endPointRelative.y, ellipseRotation);
let controlPoint1RelativeRotated = rotatePointAroundCordsStartClockWise(controlPoint1Relative.x, controlPoint1Relative.y, ellipseRotation);
let controlPoint2RelativeRotated = rotatePointAroundCordsStartClockWise(controlPoint2Relative.x, controlPoint2Relative.y, ellipseRotation);
// go to initial cord system
let startPointRotated = {x : startPointRelativeRotated.x + rotatePoint.x, y : rotatePoint.y - startPointRelativeRotated.y};
let endPointRotated = {x : endPointRelativeRotated.x + rotatePoint.x, y : rotatePoint.y - endPointRelativeRotated.y};
let controlPoint1Rotated = {x : controlPoint1RelativeRotated.x + rotatePoint.x, y : rotatePoint.y - controlPoint1RelativeRotated.y};
let controlPoint2Rotated = {x : controlPoint2RelativeRotated.x + rotatePoint.x, y : rotatePoint.y - controlPoint2RelativeRotated.y};
fX1 = startPointRotated.x;
fY1 = startPointRotated.y;
fX2 = endPointRotated.x;
fY2 = endPointRotated.y;
fCX1 = controlPoint1Rotated.x;
fCY1 = controlPoint1Rotated.y;
fCX2 = controlPoint2Rotated.x;
fCY2 = controlPoint2Rotated.y;
}
if ( !bClockDirection )
{
ctx._c(fCX1, fCY1, fCX2, fCY2, fX2, fY2);
return {X: fX2, Y: fY2};
}
else
{
ctx._c(fCX2, fCY2, fCX1, fCY1, fX1, fY1);
return {X: fX1, Y: fY1};
}
}
// ----------------------------------------------------------------------- //
function _ArcToOnCanvas(context, start_x, start_y, width_r, height_r, start_ang, sweep_ang)
{
var _sin = Math.sin(start_ang);
var _cos = Math.cos(start_ang);
var _x = _cos / width_r;
var _y = _sin / height_r;
var _l = 1 / Math.sqrt(_x * _x + _y * _y);
var _cx = start_x - _l * _cos;
var _cy = start_y - _l * _sin;
ArcTo2OnCanvas(context, _cx - width_r, _cy - height_r, 2 * width_r, 2 * height_r, start_ang, sweep_ang);
}
function ArcTo2OnCanvas(context, _l_c_x, _l_c_y, width, height, start_ang, sweep_ang)
{
if (0 >= width || 0 >= height)
return;
start_ang = -start_ang;
sweep_ang = -sweep_ang;
var bClockDirection = false;
var fEndAngle = (2 * Math.PI) - (sweep_ang + start_ang);
var fSrtAngle = (2 * Math.PI) - start_ang;
if (sweep_ang > 0)
{
bClockDirection = true;
}
if (Math.abs(sweep_ang) >= (2 * Math.PI))
{
EllipseOnCanvas(context, _l_c_x + width / 2, _l_c_y + height / 2, width / 2, height / 2);
}
else
{
EllipseArcOnCanvas(context, _l_c_x + width / 2, _l_c_y + height / 2, width / 2, height / 2, fSrtAngle, fEndAngle, bClockDirection);
}
}
function EllipseOnCanvas(ctx, fX, fY, fXRad, fYRad)
{
ctx.moveTo(fX - fXRad, fY);
var c_fKappa = 0.552;
ctx.bezierCurveTo(fX - fXRad, fY + fYRad * c_fKappa, fX - fXRad * c_fKappa, fY + fYRad, fX, fY + fYRad);
ctx.bezierCurveTo(fX + fXRad * c_fKappa, fY + fYRad, fX + fXRad, fY + fYRad * c_fKappa, fX + fXRad, fY);
ctx.bezierCurveTo(fX + fXRad, fY - fYRad * c_fKappa, fX + fXRad * c_fKappa, fY - fYRad, fX, fY - fYRad);
ctx.bezierCurveTo(fX - fXRad * c_fKappa, fY - fYRad, fX - fXRad, fY - fYRad * c_fKappa, fX - fXRad, fY);
}
function EllipseArcOnCanvas(ctx, fX, fY, fXRad, fYRad, fAngle1, fAngle2, bClockDirection)
{
while ( fAngle1 < 0 )
fAngle1 += (2 * Math.PI);
while ( fAngle1 > (2 * Math.PI) )
fAngle1 -= (2 * Math.PI);
while ( fAngle2 < 0 )
fAngle2 += (2 * Math.PI);
while ( fAngle2 >= (2 * Math.PI) )
fAngle2 -= (2 * Math.PI);
if ( !bClockDirection )
{
if ( fAngle1 <= fAngle2 )
EllipseArc2OnCanvas(ctx, fX, fY, fXRad, fYRad, fAngle1, fAngle2, false);
else
{
EllipseArc2OnCanvas(ctx, fX, fY, fXRad, fYRad, fAngle1, 2 * Math.PI, false);
EllipseArc2OnCanvas(ctx, fX, fY, fXRad, fYRad, 0, fAngle2, false);
}
}
else
{
if ( fAngle1 >= fAngle2 )
EllipseArc2OnCanvas(ctx, fX, fY, fXRad, fYRad, fAngle1, fAngle2, true);
else
{
EllipseArc2OnCanvas(ctx, fX, fY, fXRad, fYRad, fAngle1, 0, true);
EllipseArc2OnCanvas(ctx, fX, fY, fXRad, fYRad, 2 * Math.PI, fAngle2, true);
}
}
}
function EllipseArc2OnCanvas(ctx, fX, fY, fXRad, fYRad, dAngle1, dAngle2, bClockDirection)
{
var nFirstPointQuard = ((2 * dAngle1 / Math.PI) >> 0) + 1;
var nSecondPointQuard = ((2 * dAngle2 / Math.PI) >> 0) + 1;
nSecondPointQuard = Math.min( 4, Math.max( 1, nSecondPointQuard ) );
nFirstPointQuard = Math.min( 4, Math.max( 1, nFirstPointQuard ) );
var fStartX = fX + fXRad * Math.cos( AngToEllPrm( dAngle1, fXRad, fYRad ) );
var fStartY = fY + fYRad * Math.sin( AngToEllPrm( dAngle1, fXRad, fYRad ) );
var EndPoint = {X: 0, Y: 0};
ctx.lineTo(fStartX, fStartY);
var fCurX = fStartX, fCurY = fStartY;
var dStartAngle = dAngle1;
var dEndAngle = 0;
if ( !bClockDirection )
{
for( var nIndex = nFirstPointQuard; nIndex <= nSecondPointQuard; nIndex++ )
{
if ( nIndex == nSecondPointQuard )
dEndAngle = dAngle2;
else
dEndAngle = nIndex * Math.PI / 2;
if ( !( nIndex == nFirstPointQuard ) )
dStartAngle = (nIndex - 1 ) * Math.PI / 2;
EndPoint = EllipseArc3OnCanvas(ctx, fX, fY, fXRad, fYRad, AngToEllPrm( dStartAngle, fXRad, fYRad ), AngToEllPrm( dEndAngle, fXRad, fYRad ), false);
}
}
else
{
for( var nIndex = nFirstPointQuard; nIndex >= nSecondPointQuard; nIndex-- )
{
if ( nIndex == nFirstPointQuard )
dStartAngle = dAngle1;
else
dStartAngle = nIndex * Math.PI / 2;
if ( !( nIndex == nSecondPointQuard ) )
dEndAngle = (nIndex - 1 ) * Math.PI / 2;
else
dEndAngle = dAngle2;
EndPoint = EllipseArc3OnCanvas(ctx, fX, fY, fXRad, fYRad, AngToEllPrm( dStartAngle, fXRad, fYRad ), AngToEllPrm( dEndAngle, fXRad, fYRad ), false);
}
}
}
function EllipseArc3OnCanvas(ctx, fX, fY, fXRad, fYRad, dAngle1, dAngle2, bClockDirection)
{
var fAlpha = Math.sin( dAngle2 - dAngle1 ) * ( Math.sqrt( 4.0 + 3.0 * Math.tan( (dAngle2 - dAngle1) / 2.0 ) * Math.tan( (dAngle2 - dAngle1) / 2.0 ) ) - 1.0 ) / 3.0;
var sin1 = Math.sin(dAngle1);
var cos1 = Math.cos(dAngle1);
var sin2 = Math.sin(dAngle2);
var cos2 = Math.cos(dAngle2);
var fX1 = fX + fXRad * cos1;
var fY1 = fY + fYRad * sin1;
var fX2 = fX + fXRad * cos2;
var fY2 = fY + fYRad * sin2;
var fCX1 = fX1 - fAlpha * fXRad * sin1;
var fCY1 = fY1 + fAlpha * fYRad * cos1;
var fCX2 = fX2 + fAlpha * fXRad * sin2;
var fCY2 = fY2 - fAlpha * fYRad * cos2;
if ( !bClockDirection )
{
ctx.bezierCurveTo(fCX1, fCY1, fCX2, fCY2, fX2, fY2);
return {X: fX2, Y: fY2};
}
else
{
ctx.bezierCurveTo(fCX2, fCY2, fCX1, fCY1, fX1, fY1);
return {X: fX1, Y: fY1};
}
}
function _HitToArc(context, px, py, start_x, start_y, width_r, height_r, start_ang, sweep_ang)
{
var _sin = Math.sin(start_ang);
var _cos = Math.cos(start_ang);
var _x = _cos / width_r;
var _y = _sin / height_r;
var _l = 1 / Math.sqrt(_x * _x + _y * _y);
var _cx = start_x - _l * _cos;
var _cy = start_y - _l * _sin;
return HitToArc2(px, py, context, _cx - width_r, _cy - height_r, 2 * width_r, 2 * height_r, start_ang, sweep_ang);
}
function HitToArc2(px, py, context, _l_c_x, _l_c_y, width, height, start_ang, sweep_ang)
{
if (0 >= width || 0 >= height)
return;
start_ang = -start_ang;
sweep_ang = -sweep_ang;
var bClockDirection = false;
var fEndAngle = (2 * Math.PI) - (sweep_ang + start_ang);
var fSrtAngle = (2 * Math.PI) - start_ang;
if (sweep_ang > 0)
{
bClockDirection = true;
}
if (Math.abs(sweep_ang) >= (2 * Math.PI))
{
return HitToEllipseOnCanvas(px, py, context, _l_c_x + width / 2, _l_c_y + height / 2, width / 2, height / 2);
}
else
{
return HitToEllipseArcOnCanvas(px, py, context, _l_c_x + width / 2, _l_c_y + height / 2, width / 2, height / 2, fSrtAngle, fEndAngle, bClockDirection);
}
}
function HitToEllipseOnCanvas(px, py, ctx, fX, fY, fXRad, fYRad)
{
var c_fKappa = 0.552;
return HitInBezier4(ctx, px, py, fX - fXRad, fY, fX - fXRad, fY + fYRad * c_fKappa, fX - fXRad * c_fKappa, fY + fYRad, fX, fY + fYRad) ||
HitInBezier4(ctx, px, py, fX, fY + fYRad, fX + fXRad * c_fKappa, fY + fYRad, fX + fXRad, fY + fYRad * c_fKappa, fX + fXRad, fY)||
HitInBezier4(ctx, px, py, fX + fXRad, fY, fX + fXRad, fY - fYRad * c_fKappa, fX + fXRad * c_fKappa, fY - fYRad, fX, fY - fYRad)||
HitInBezier4(ctx, px, py, fX, fY - fYRad, fX - fXRad * c_fKappa, fY - fYRad, fX - fXRad, fY - fYRad * c_fKappa, fX - fXRad, fY);
}
function HitToEllipseArcOnCanvas(px, py, ctx, fX, fY, fXRad, fYRad, fAngle1, fAngle2, bClockDirection)
{
while ( fAngle1 < 0 )
fAngle1 += (2 * Math.PI);
while ( fAngle1 > (2 * Math.PI) )
fAngle1 -= (2 * Math.PI);
while ( fAngle2 < 0 )
fAngle2 += (2 * Math.PI);
while ( fAngle2 >= (2 * Math.PI) )
fAngle2 -= (2 * Math.PI);
if ( !bClockDirection )
{
if ( fAngle1 <= fAngle2 )
return HitToEllipseArc2OnCanvas(px, py,ctx, fX, fY, fXRad, fYRad, fAngle1, fAngle2, false);
else
{
return HitToEllipseArc2OnCanvas(px, py,ctx, fX, fY, fXRad, fYRad, fAngle1, 2 * Math.PI, false)|| HitToEllipseArc2OnCanvas(px, py,ctx, fX, fY, fXRad, fYRad, 0, fAngle2, false);
}
}
else
{
if ( fAngle1 >= fAngle2 )
return HitToEllipseArc2OnCanvas(px, py,ctx, fX, fY, fXRad, fYRad, fAngle1, fAngle2, true);
else
{
return HitToEllipseArc2OnCanvas(px, py, ctx, fX, fY, fXRad, fYRad, fAngle1, 0, true) || HitToEllipseArc2OnCanvas(px, py,ctx, fX, fY, fXRad, fYRad, 2 * Math.PI, fAngle2, true);
}
}
}
function HitToEllipseArc2OnCanvas(px, py, ctx, fX, fY, fXRad, fYRad, dAngle1, dAngle2, bClockDirection)
{
var nFirstPointQuard = ((2 * dAngle1 / Math.PI) >> 0) + 1;
var nSecondPointQuard = ((2 * dAngle2 / Math.PI) >> 0) + 1;
nSecondPointQuard = Math.min( 4, Math.max( 1, nSecondPointQuard ) );
nFirstPointQuard = Math.min( 4, Math.max( 1, nFirstPointQuard ) );
var fStartX = fX + fXRad * Math.cos( AngToEllPrm( dAngle1, fXRad, fYRad ) );
var fStartY = fY + fYRad * Math.sin( AngToEllPrm( dAngle1, fXRad, fYRad ) );
var EndPoint = {X: fStartX, Y: fStartY, hit : false};
var dStartAngle = dAngle1;
var dEndAngle = 0;
if ( !bClockDirection )
{
for( var nIndex = nFirstPointQuard; nIndex <= nSecondPointQuard; nIndex++ )
{
if ( nIndex == nSecondPointQuard )
dEndAngle = dAngle2;
else
dEndAngle = nIndex * Math.PI / 2;
if ( !( nIndex == nFirstPointQuard ) )
dStartAngle = (nIndex - 1 ) * Math.PI / 2;
EndPoint = HitToEllipseArc3OnCanvas(px, py, EndPoint, ctx, fX, fY, fXRad, fYRad, AngToEllPrm( dStartAngle, fXRad, fYRad ), AngToEllPrm( dEndAngle, fXRad, fYRad ), false);
if(EndPoint.hit)
{
return true;
}
}
}
else
{
for( var nIndex = nFirstPointQuard; nIndex >= nSecondPointQuard; nIndex-- )
{
if ( nIndex == nFirstPointQuard )
dStartAngle = dAngle1;
else
dStartAngle = nIndex * Math.PI / 2;
if ( !( nIndex == nSecondPointQuard ) )
dEndAngle = (nIndex - 1 ) * Math.PI / 2;
else
dEndAngle = dAngle2;
EndPoint = HitToEllipseArc3OnCanvas(px, py, EndPoint, ctx, fX, fY, fXRad, fYRad, AngToEllPrm( dStartAngle, fXRad, fYRad ), AngToEllPrm( dEndAngle, fXRad, fYRad ), false);
if(EndPoint.hit)
{
return true;
}
}
}
return false;
}
function HitToEllipseArc3OnCanvas(px, py, EndPoint, ctx, fX, fY, fXRad, fYRad, dAngle1, dAngle2, bClockDirection)
{
var fAlpha = Math.sin( dAngle2 - dAngle1 ) * ( Math.sqrt( 4.0 + 3.0 * Math.tan( (dAngle2 - dAngle1) / 2.0 ) * Math.tan( (dAngle2 - dAngle1) / 2.0 ) ) - 1.0 ) / 3.0;
var sin1 = Math.sin(dAngle1);
var cos1 = Math.cos(dAngle1);
var sin2 = Math.sin(dAngle2);
var cos2 = Math.cos(dAngle2);
var fX1 = fX + fXRad * cos1;
var fY1 = fY + fYRad * sin1;
var fX2 = fX + fXRad * cos2;
var fY2 = fY + fYRad * sin2;
var fCX1 = fX1 - fAlpha * fXRad * sin1;
var fCY1 = fY1 + fAlpha * fYRad * cos1;
var fCX2 = fX2 + fAlpha * fXRad * sin2;
var fCY2 = fY2 - fAlpha * fYRad * cos2;
if ( !bClockDirection )
{
return {X: fX2, Y: fY2, hit : HitInBezier4(ctx, px, py,EndPoint.X, EndPoint.Y, fCX1, fCY1, fCX2, fCY2, fX2, fY2)};
}
else
{
return {X: fX1, Y: fY1, hit : HitInBezier4(ctx, px, py,EndPoint.X, EndPoint.Y, fCX2, fCY2, fCX1, fCY1, fX1, fY1)};
}
}
//--------------------------------------------------------export----------------------------------------------------
window['AscFormat'] = window['AscFormat'] || {};
window['AscFormat'].ArcToCurvers = Arc3;
window['AscFormat'].HitToArc = _HitToArc;
window['AscFormat'].ArcToOnCanvas = _ArcToOnCanvas;
window['AscFormat'].EllipseOnCanvas = EllipseOnCanvas;
})(window);