2014-01-31 01:05:03 +00:00
/*globals $, svgedit, svgroot*/
/*jslint vars: true, eqeq: true, continue: true*/
2011-02-04 08:02:46 +00:00
/ * *
* Package : svgedit . path
*
2012-09-16 18:53:27 +00:00
* Licensed under the MIT License
2011-02-04 08:02:46 +00:00
*
* Copyright ( c ) 2011 Alexis Deveria
* Copyright ( c ) 2011 Jeff Schiller
* /
// Dependencies:
// 1) jQuery
// 2) browser.js
// 3) math.js
// 4) svgutils.js
2015-07-06 10:36:24 +00:00
( function ( ) { 'use strict' ;
2011-02-04 08:02:46 +00:00
if ( ! svgedit . path ) {
svgedit . path = { } ;
}
2013-02-16 15:02:26 +00:00
var NS = svgedit . NS ;
2011-02-04 08:02:46 +00:00
var uiStrings = {
2013-02-15 17:02:24 +00:00
'pathNodeTooltip' : 'Drag node to move it. Double-click node to change segment type' ,
'pathCtrlPtTooltip' : 'Drag control point to adjust curve properties'
2011-02-04 08:02:46 +00:00
} ;
var segData = {
2013-02-15 16:51:48 +00:00
2 : [ 'x' , 'y' ] ,
4 : [ 'x' , 'y' ] ,
6 : [ 'x' , 'y' , 'x1' , 'y1' , 'x2' , 'y2' ] ,
8 : [ 'x' , 'y' , 'x1' , 'y1' ] ,
10 : [ 'x' , 'y' , 'r1' , 'r2' , 'angle' , 'largeArcFlag' , 'sweepFlag' ] ,
2011-02-04 08:02:46 +00:00
12 : [ 'x' ] ,
14 : [ 'y' ] ,
2013-02-15 16:51:48 +00:00
16 : [ 'x' , 'y' , 'x2' , 'y2' ] ,
18 : [ 'x' , 'y' ]
2011-02-04 08:02:46 +00:00
} ;
var pathFuncs = [ ] ;
2011-02-04 16:06:25 +00:00
var link _control _pts = true ;
2011-02-23 16:24:07 +00:00
// Stores references to paths via IDs.
// TODO: Make this cross-document happy.
var pathData = { } ;
2011-02-04 16:06:25 +00:00
svgedit . path . setLinkControlPoints = function ( lcp ) {
link _control _pts = lcp ;
} ;
2011-02-04 08:02:46 +00:00
svgedit . path . path = null ;
var editorContext _ = null ;
svgedit . path . init = function ( editorContext ) {
editorContext _ = editorContext ;
2013-02-14 13:11:01 +00:00
2013-02-15 16:51:48 +00:00
pathFuncs = [ 0 , 'ClosePath' ] ;
2011-02-04 08:02:46 +00:00
var pathFuncsStrs = [ 'Moveto' , 'Lineto' , 'CurvetoCubic' , 'CurvetoQuadratic' , 'Arc' ,
2013-02-15 16:51:48 +00:00
'LinetoHorizontal' , 'LinetoVertical' , 'CurvetoCubicSmooth' , 'CurvetoQuadraticSmooth' ] ;
$ . each ( pathFuncsStrs , function ( i , s ) {
2011-02-04 08:02:46 +00:00
pathFuncs . push ( s + 'Abs' ) ;
pathFuncs . push ( s + 'Rel' ) ;
} ) ;
} ;
svgedit . path . insertItemBefore = function ( elem , newseg , index ) {
// Support insertItemBefore on paths for FF2
var list = elem . pathSegList ;
2013-02-14 13:11:01 +00:00
if ( svgedit . browser . supportsPathInsertItemBefore ( ) ) {
2011-02-04 08:02:46 +00:00
list . insertItemBefore ( newseg , index ) ;
return ;
}
var len = list . numberOfItems ;
var arr = [ ] ;
2014-01-31 01:05:03 +00:00
var i ;
for ( i = 0 ; i < len ; i ++ ) {
2011-02-04 08:02:46 +00:00
var cur _seg = list . getItem ( i ) ;
2013-02-14 13:11:01 +00:00
arr . push ( cur _seg ) ;
2011-02-04 08:02:46 +00:00
}
list . clear ( ) ;
2014-01-31 01:05:03 +00:00
for ( i = 0 ; i < len ; i ++ ) {
2013-02-14 13:11:01 +00:00
if ( i == index ) { //index+1
2011-02-04 08:02:46 +00:00
list . appendItem ( newseg ) ;
}
list . appendItem ( arr [ i ] ) ;
}
} ;
// TODO: See if this should just live in replacePathSeg
svgedit . path . ptObjToArr = function ( type , seg _item ) {
var arr = segData [ type ] , len = arr . length ;
2014-02-12 01:07:26 +00:00
var i , out = [ ] ;
2014-01-31 01:05:03 +00:00
for ( i = 0 ; i < len ; i ++ ) {
2011-02-04 08:02:46 +00:00
out [ i ] = seg _item [ arr [ i ] ] ;
}
return out ;
} ;
svgedit . path . getGripPt = function ( seg , alt _pt ) {
var out = {
x : alt _pt ? alt _pt . x : seg . item . x ,
y : alt _pt ? alt _pt . y : seg . item . y
} , path = seg . path ;
2013-02-14 13:11:01 +00:00
if ( path . matrix ) {
2011-02-04 08:02:46 +00:00
var pt = svgedit . math . transformPoint ( out . x , out . y , path . matrix ) ;
out = pt ;
}
2011-02-09 06:14:47 +00:00
out . x *= editorContext _ . getCurrentZoom ( ) ;
out . y *= editorContext _ . getCurrentZoom ( ) ;
2011-02-04 08:02:46 +00:00
return out ;
} ;
svgedit . path . getPointFromGrip = function ( pt , path ) {
var out = {
x : pt . x ,
y : pt . y
2013-02-14 13:11:01 +00:00
} ;
2011-02-04 08:02:46 +00:00
2013-02-14 13:11:01 +00:00
if ( path . matrix ) {
2014-01-31 01:05:03 +00:00
pt = svgedit . math . transformPoint ( out . x , out . y , path . imatrix ) ;
2011-02-04 08:02:46 +00:00
out . x = pt . x ;
out . y = pt . y ;
}
2011-02-09 06:14:47 +00:00
out . x /= editorContext _ . getCurrentZoom ( ) ;
out . y /= editorContext _ . getCurrentZoom ( ) ;
2011-02-04 08:02:46 +00:00
return out ;
} ;
svgedit . path . addPointGrip = function ( index , x , y ) {
// create the container of all the point grips
var pointGripContainer = svgedit . path . getGripContainer ( ) ;
2015-07-06 10:42:25 +00:00
2013-02-15 17:02:24 +00:00
var pointGrip = svgedit . utilities . getElem ( 'pathpointgrip_' + index ) ;
2011-02-04 08:02:46 +00:00
// create it
if ( ! pointGrip ) {
2013-02-16 15:02:26 +00:00
pointGrip = document . createElementNS ( NS . SVG , 'circle' ) ;
2011-02-04 08:02:46 +00:00
svgedit . utilities . assignAttributes ( pointGrip , {
2013-02-15 17:02:24 +00:00
'id' : 'pathpointgrip_' + index ,
'display' : 'none' ,
2011-02-04 08:02:46 +00:00
'r' : 4 ,
2013-02-15 17:02:24 +00:00
'fill' : '#0FF' ,
'stroke' : '#00F' ,
2011-02-04 08:02:46 +00:00
'stroke-width' : 2 ,
'cursor' : 'move' ,
'style' : 'pointer-events:all' ,
'xlink:title' : uiStrings . pathNodeTooltip
} ) ;
pointGrip = pointGripContainer . appendChild ( pointGrip ) ;
var grip = $ ( '#pathpointgrip_' + index ) ;
grip . dblclick ( function ( ) {
2014-01-31 01:05:03 +00:00
if ( svgedit . path . path ) {
svgedit . path . path . setSegType ( ) ;
}
2011-02-04 08:02:46 +00:00
} ) ;
}
2013-02-14 13:11:01 +00:00
if ( x && y ) {
2011-02-04 08:02:46 +00:00
// set up the point grip element and display it
svgedit . utilities . assignAttributes ( pointGrip , {
'cx' : x ,
'cy' : y ,
2013-02-15 17:02:24 +00:00
'display' : 'inline'
2011-02-04 08:02:46 +00:00
} ) ;
}
return pointGrip ;
} ;
svgedit . path . getGripContainer = function ( ) {
2013-02-15 17:02:24 +00:00
var c = svgedit . utilities . getElem ( 'pathpointgrip_container' ) ;
2011-02-04 08:02:46 +00:00
if ( ! c ) {
2013-02-15 17:02:24 +00:00
var parent = svgedit . utilities . getElem ( 'selectorParentGroup' ) ;
2013-02-16 15:02:26 +00:00
c = parent . appendChild ( document . createElementNS ( NS . SVG , 'g' ) ) ;
2013-02-15 17:02:24 +00:00
c . id = 'pathpointgrip_container' ;
2011-02-04 08:02:46 +00:00
}
return c ;
} ;
svgedit . path . addCtrlGrip = function ( id ) {
2013-02-15 17:02:24 +00:00
var pointGrip = svgedit . utilities . getElem ( 'ctrlpointgrip_' + id ) ;
2014-01-31 01:05:03 +00:00
if ( pointGrip ) { return pointGrip ; }
2013-02-14 13:11:01 +00:00
2013-02-16 15:02:26 +00:00
pointGrip = document . createElementNS ( NS . SVG , 'circle' ) ;
2011-02-04 08:02:46 +00:00
svgedit . utilities . assignAttributes ( pointGrip , {
2013-02-15 17:02:24 +00:00
'id' : 'ctrlpointgrip_' + id ,
'display' : 'none' ,
2011-02-04 08:02:46 +00:00
'r' : 4 ,
2013-02-15 17:02:24 +00:00
'fill' : '#0FF' ,
'stroke' : '#55F' ,
2011-02-04 08:02:46 +00:00
'stroke-width' : 1 ,
'cursor' : 'move' ,
'style' : 'pointer-events:all' ,
'xlink:title' : uiStrings . pathCtrlPtTooltip
} ) ;
svgedit . path . getGripContainer ( ) . appendChild ( pointGrip ) ;
return pointGrip ;
} ;
svgedit . path . getCtrlLine = function ( id ) {
2013-02-15 17:02:24 +00:00
var ctrlLine = svgedit . utilities . getElem ( 'ctrlLine_' + id ) ;
2014-01-31 01:05:03 +00:00
if ( ctrlLine ) { return ctrlLine ; }
2015-07-06 10:42:25 +00:00
2013-02-16 15:02:26 +00:00
ctrlLine = document . createElementNS ( NS . SVG , 'line' ) ;
2011-02-04 08:02:46 +00:00
svgedit . utilities . assignAttributes ( ctrlLine , {
2013-02-15 17:02:24 +00:00
'id' : 'ctrlLine_' + id ,
'stroke' : '#555' ,
2011-02-04 08:02:46 +00:00
'stroke-width' : 1 ,
2013-02-15 17:02:24 +00:00
'style' : 'pointer-events:none'
2011-02-04 08:02:46 +00:00
} ) ;
svgedit . path . getGripContainer ( ) . appendChild ( ctrlLine ) ;
return ctrlLine ;
} ;
svgedit . path . getPointGrip = function ( seg , update ) {
var index = seg . index ;
var pointGrip = svgedit . path . addPointGrip ( index ) ;
2013-02-14 13:11:01 +00:00
if ( update ) {
2011-02-04 08:02:46 +00:00
var pt = svgedit . path . getGripPt ( seg ) ;
svgedit . utilities . assignAttributes ( pointGrip , {
'cx' : pt . x ,
'cy' : pt . y ,
2013-02-15 17:02:24 +00:00
'display' : 'inline'
2011-02-04 08:02:46 +00:00
} ) ;
}
return pointGrip ;
} ;
svgedit . path . getControlPoints = function ( seg ) {
var item = seg . item ;
var index = seg . index ;
2014-02-17 00:46:24 +00:00
if ( ! ( 'x1' in item ) || ! ( 'x2' in item ) ) { return null ; }
2013-02-14 13:11:01 +00:00
var cpt = { } ;
2011-02-04 08:02:46 +00:00
var pointGripContainer = svgedit . path . getGripContainer ( ) ;
// Note that this is intentionally not seg.prev.item
var prev = svgedit . path . path . segs [ index - 1 ] . item ;
var seg _items = [ prev , item ] ;
2014-01-31 01:05:03 +00:00
var i ;
for ( i = 1 ; i < 3 ; i ++ ) {
2011-02-04 08:02:46 +00:00
var id = index + 'c' + i ;
2015-07-06 10:42:25 +00:00
2011-02-04 08:02:46 +00:00
var ctrlLine = cpt [ 'c' + i + '_line' ] = svgedit . path . getCtrlLine ( id ) ;
var pt = svgedit . path . getGripPt ( seg , { x : item [ 'x' + i ] , y : item [ 'y' + i ] } ) ;
var gpt = svgedit . path . getGripPt ( seg , { x : seg _items [ i - 1 ] . x , y : seg _items [ i - 1 ] . y } ) ;
svgedit . utilities . assignAttributes ( ctrlLine , {
'x1' : pt . x ,
'y1' : pt . y ,
'x2' : gpt . x ,
'y2' : gpt . y ,
2013-02-15 17:02:24 +00:00
'display' : 'inline'
2011-02-04 08:02:46 +00:00
} ) ;
cpt [ 'c' + i + '_line' ] = ctrlLine ;
// create it
2014-02-12 01:07:26 +00:00
var pointGrip = cpt [ 'c' + i ] = svgedit . path . addCtrlGrip ( id ) ;
2011-02-04 08:02:46 +00:00
svgedit . utilities . assignAttributes ( pointGrip , {
'cx' : pt . x ,
'cy' : pt . y ,
2013-02-15 17:02:24 +00:00
'display' : 'inline'
2011-02-04 08:02:46 +00:00
} ) ;
cpt [ 'c' + i ] = pointGrip ;
}
return cpt ;
} ;
// This replaces the segment at the given index. Type is given as number.
svgedit . path . replacePathSeg = function ( type , index , pts , elem ) {
var path = elem || svgedit . path . path . elem ;
2015-07-06 10:21:37 +00:00
2011-02-04 08:02:46 +00:00
var func = 'createSVGPathSeg' + pathFuncs [ type ] ;
var seg = path [ func ] . apply ( path , pts ) ;
2013-02-14 13:11:01 +00:00
if ( svgedit . browser . supportsPathReplaceItem ( ) ) {
2011-02-04 08:02:46 +00:00
path . pathSegList . replaceItem ( seg , index ) ;
} else {
var segList = path . pathSegList ;
var len = segList . numberOfItems ;
var arr = [ ] ;
2014-01-31 01:05:03 +00:00
var i ;
for ( i = 0 ; i < len ; i ++ ) {
2011-02-04 08:02:46 +00:00
var cur _seg = segList . getItem ( i ) ;
2013-02-14 13:11:01 +00:00
arr . push ( cur _seg ) ;
2011-02-04 08:02:46 +00:00
}
segList . clear ( ) ;
2014-01-31 01:05:03 +00:00
for ( i = 0 ; i < len ; i ++ ) {
2013-02-14 13:11:01 +00:00
if ( i == index ) {
2011-02-04 08:02:46 +00:00
segList . appendItem ( seg ) ;
} else {
segList . appendItem ( arr [ i ] ) ;
}
}
}
} ;
svgedit . path . getSegSelector = function ( seg , update ) {
var index = seg . index ;
2013-02-15 17:02:24 +00:00
var segLine = svgedit . utilities . getElem ( 'segline_' + index ) ;
2013-02-14 13:11:01 +00:00
if ( ! segLine ) {
2011-02-04 08:02:46 +00:00
var pointGripContainer = svgedit . path . getGripContainer ( ) ;
// create segline
2013-02-16 15:02:26 +00:00
segLine = document . createElementNS ( NS . SVG , 'path' ) ;
2011-02-04 08:02:46 +00:00
svgedit . utilities . assignAttributes ( segLine , {
2013-02-15 17:02:24 +00:00
'id' : 'segline_' + index ,
2011-02-04 08:02:46 +00:00
'display' : 'none' ,
2013-02-15 17:02:24 +00:00
'fill' : 'none' ,
'stroke' : '#0FF' ,
2011-02-04 08:02:46 +00:00
'stroke-width' : 2 ,
'style' : 'pointer-events:none' ,
'd' : 'M0,0 0,0'
} ) ;
pointGripContainer . appendChild ( segLine ) ;
2013-02-14 13:11:01 +00:00
}
2011-02-04 08:02:46 +00:00
2013-02-14 13:11:01 +00:00
if ( update ) {
2011-02-04 08:02:46 +00:00
var prev = seg . prev ;
2013-02-14 13:11:01 +00:00
if ( ! prev ) {
2013-02-15 17:02:24 +00:00
segLine . setAttribute ( 'display' , 'none' ) ;
2011-02-04 08:02:46 +00:00
return segLine ;
}
var pt = svgedit . path . getGripPt ( prev ) ;
// Set start point
svgedit . path . replacePathSeg ( 2 , 0 , [ pt . x , pt . y ] , segLine ) ;
var pts = svgedit . path . ptObjToArr ( seg . type , seg . item , true ) ;
2014-01-31 01:05:03 +00:00
var i ;
for ( i = 0 ; i < pts . length ; i += 2 ) {
pt = svgedit . path . getGripPt ( seg , { x : pts [ i ] , y : pts [ i + 1 ] } ) ;
2011-02-04 08:02:46 +00:00
pts [ i ] = pt . x ;
pts [ i + 1 ] = pt . y ;
}
2015-07-06 10:42:25 +00:00
2011-02-04 08:02:46 +00:00
svgedit . path . replacePathSeg ( seg . type , 1 , pts , segLine ) ;
}
return segLine ;
} ;
2011-02-09 06:14:47 +00:00
// Function: smoothControlPoints
// Takes three points and creates a smoother line based on them
//
// Parameters:
// ct1 - Object with x and y values (first control point)
// ct2 - Object with x and y values (second control point)
// pt - Object with x and y values (third point)
//
// Returns:
// Array of two "smoothed" point objects
2013-02-15 23:05:23 +00:00
svgedit . path . smoothControlPoints = function ( ct1 , ct2 , pt ) {
2011-02-09 06:14:47 +00:00
// each point must not be the origin
var x1 = ct1 . x - pt . x ,
y1 = ct1 . y - pt . y ,
x2 = ct2 . x - pt . x ,
y2 = ct2 . y - pt . y ;
2013-02-14 13:11:01 +00:00
2011-02-09 06:14:47 +00:00
if ( ( x1 != 0 || y1 != 0 ) && ( x2 != 0 || y2 != 0 ) ) {
2013-02-15 16:51:48 +00:00
var anglea = Math . atan2 ( y1 , x1 ) ,
angleb = Math . atan2 ( y2 , x2 ) ,
2011-02-09 06:14:47 +00:00
r1 = Math . sqrt ( x1 * x1 + y1 * y1 ) ,
r2 = Math . sqrt ( x2 * x2 + y2 * y2 ) ,
nct1 = editorContext _ . getSVGRoot ( ) . createSVGPoint ( ) ,
2013-02-14 13:11:01 +00:00
nct2 = editorContext _ . getSVGRoot ( ) . createSVGPoint ( ) ;
2011-02-09 06:14:47 +00:00
if ( anglea < 0 ) { anglea += 2 * Math . PI ; }
if ( angleb < 0 ) { angleb += 2 * Math . PI ; }
2013-02-14 13:11:01 +00:00
2011-02-09 06:14:47 +00:00
var angleBetween = Math . abs ( anglea - angleb ) ,
angleDiff = Math . abs ( Math . PI - angleBetween ) / 2 ;
2013-02-14 13:11:01 +00:00
2011-02-09 06:14:47 +00:00
var new _anglea , new _angleb ;
if ( anglea - angleb > 0 ) {
new _anglea = angleBetween < Math . PI ? ( anglea + angleDiff ) : ( anglea - angleDiff ) ;
new _angleb = angleBetween < Math . PI ? ( angleb - angleDiff ) : ( angleb + angleDiff ) ;
}
else {
new _anglea = angleBetween < Math . PI ? ( anglea - angleDiff ) : ( anglea + angleDiff ) ;
new _angleb = angleBetween < Math . PI ? ( angleb + angleDiff ) : ( angleb - angleDiff ) ;
}
2013-02-14 13:11:01 +00:00
2011-02-09 06:14:47 +00:00
// rotate the points
nct1 . x = r1 * Math . cos ( new _anglea ) + pt . x ;
nct1 . y = r1 * Math . sin ( new _anglea ) + pt . y ;
nct2 . x = r2 * Math . cos ( new _angleb ) + pt . x ;
nct2 . y = r2 * Math . sin ( new _angleb ) + pt . y ;
2013-02-14 13:11:01 +00:00
2011-02-09 06:14:47 +00:00
return [ nct1 , nct2 ] ;
}
return undefined ;
} ;
2011-02-04 08:02:46 +00:00
svgedit . path . Segment = function ( index , item ) {
this . selected = false ;
this . index = index ;
this . item = item ;
this . type = item . pathSegType ;
2013-02-14 13:11:01 +00:00
2011-02-04 08:02:46 +00:00
this . ctrlpts = [ ] ;
this . ptgrip = null ;
this . segsel = null ;
} ;
svgedit . path . Segment . prototype . showCtrlPts = function ( y ) {
2014-01-31 01:05:03 +00:00
var i ;
for ( i in this . ctrlpts ) {
2014-02-12 01:07:26 +00:00
if ( this . ctrlpts . hasOwnProperty ( i ) ) {
this . ctrlpts [ i ] . setAttribute ( 'display' , y ? 'inline' : 'none' ) ;
}
2011-02-04 08:02:46 +00:00
}
} ;
svgedit . path . Segment . prototype . selectCtrls = function ( y ) {
$ ( '#ctrlpointgrip_' + this . index + 'c1, #ctrlpointgrip_' + this . index + 'c2' ) .
attr ( 'fill' , y ? '#0FF' : '#EEE' ) ;
} ;
svgedit . path . Segment . prototype . show = function ( y ) {
2013-02-14 13:11:01 +00:00
if ( this . ptgrip ) {
2013-02-15 17:02:24 +00:00
this . ptgrip . setAttribute ( 'display' , y ? 'inline' : 'none' ) ;
this . segsel . setAttribute ( 'display' , y ? 'inline' : 'none' ) ;
2011-02-04 08:02:46 +00:00
// Show/hide all control points if available
this . showCtrlPts ( y ) ;
}
} ;
svgedit . path . Segment . prototype . select = function ( y ) {
2013-02-14 13:11:01 +00:00
if ( this . ptgrip ) {
2013-02-15 17:02:24 +00:00
this . ptgrip . setAttribute ( 'stroke' , y ? '#0FF' : '#00F' ) ;
this . segsel . setAttribute ( 'display' , y ? 'inline' : 'none' ) ;
2013-02-14 13:11:01 +00:00
if ( this . ctrlpts ) {
2011-02-04 08:02:46 +00:00
this . selectCtrls ( y ) ;
}
this . selected = y ;
}
} ;
svgedit . path . Segment . prototype . addGrip = function ( ) {
this . ptgrip = svgedit . path . getPointGrip ( this , true ) ;
this . ctrlpts = svgedit . path . getControlPoints ( this , true ) ;
this . segsel = svgedit . path . getSegSelector ( this , true ) ;
} ;
svgedit . path . Segment . prototype . update = function ( full ) {
2013-02-14 13:11:01 +00:00
if ( this . ptgrip ) {
2011-02-04 08:02:46 +00:00
var pt = svgedit . path . getGripPt ( this ) ;
svgedit . utilities . assignAttributes ( this . ptgrip , {
'cx' : pt . x ,
'cy' : pt . y
} ) ;
svgedit . path . getSegSelector ( this , true ) ;
2013-02-14 13:11:01 +00:00
if ( this . ctrlpts ) {
if ( full ) {
2011-02-04 08:02:46 +00:00
this . item = svgedit . path . path . elem . pathSegList . getItem ( this . index ) ;
this . type = this . item . pathSegType ;
}
svgedit . path . getControlPoints ( this ) ;
2013-02-14 13:11:01 +00:00
}
2013-02-15 17:02:24 +00:00
// this.segsel.setAttribute('display', y?'inline':'none');
2011-02-04 08:02:46 +00:00
}
} ;
svgedit . path . Segment . prototype . move = function ( dx , dy ) {
2014-02-12 01:07:26 +00:00
var cur _pts , item = this . item ;
2011-02-04 08:02:46 +00:00
2015-07-06 10:21:37 +00:00
// fix for path tool dom breakage, amending item does bad things now, so we take a copy and use that. Can probably improve to just take a shallow copy of object
var cloneItem = $ . extend ( { } , item ) ;
2015-07-15 11:02:03 +00:00
if ( this . ctrlpts ) {
cur _pts = [ cloneItem . x += dx , cloneItem . y += dy ,
2015-07-06 10:21:37 +00:00
cloneItem . x1 , cloneItem . y1 , cloneItem . x2 += dx , cloneItem . y2 += dy ] ;
} else {
2015-07-15 11:02:03 +00:00
cur _pts = [ cloneItem . x += dx , cloneItem . y += dy ] ;
2015-07-06 10:21:37 +00:00
}
//fix
2011-02-04 08:02:46 +00:00
svgedit . path . replacePathSeg ( this . type , this . index , cur _pts ) ;
2013-02-14 13:11:01 +00:00
if ( this . next && this . next . ctrlpts ) {
2011-02-04 08:02:46 +00:00
var next = this . next . item ;
var next _pts = [ next . x , next . y ,
next . x1 += dx , next . y1 += dy , next . x2 , next . y2 ] ;
svgedit . path . replacePathSeg ( this . next . type , this . next . index , next _pts ) ;
}
2013-02-14 13:11:01 +00:00
if ( this . mate ) {
2013-02-15 17:02:24 +00:00
// The last point of a closed subpath has a 'mate',
// which is the 'M' segment of the subpath
2014-01-31 01:05:03 +00:00
item = this . mate . item ;
2011-02-04 08:02:46 +00:00
var pts = [ item . x += dx , item . y += dy ] ;
svgedit . path . replacePathSeg ( this . mate . type , this . mate . index , pts ) ;
2013-02-15 17:02:24 +00:00
// Has no grip, so does not need 'updating'?
2011-02-04 08:02:46 +00:00
}
this . update ( true ) ;
2014-01-31 01:05:03 +00:00
if ( this . next ) { this . next . update ( true ) ; }
2011-02-04 08:02:46 +00:00
} ;
svgedit . path . Segment . prototype . setLinked = function ( num ) {
var seg , anum , pt ;
if ( num == 2 ) {
anum = 1 ;
seg = this . next ;
2014-01-31 01:05:03 +00:00
if ( ! seg ) { return ; }
2011-02-04 08:02:46 +00:00
pt = this . item ;
} else {
anum = 2 ;
seg = this . prev ;
2014-01-31 01:05:03 +00:00
if ( ! seg ) { return ; }
2011-02-04 08:02:46 +00:00
pt = seg . item ;
}
var item = seg . item ;
2015-07-06 10:21:37 +00:00
// fix for path tool dom breakage, amending item does bad things now, so we take a copy and use that. Can probably improve to just take a shallow copy of object
var cloneItem = $ . extend ( { } , item ) ;
cloneItem [ 'x' + anum ] = pt . x + ( pt . x - this . item [ 'x' + num ] ) ;
cloneItem [ 'y' + anum ] = pt . y + ( pt . y - this . item [ 'y' + num ] ) ;
2011-02-04 08:02:46 +00:00
2015-07-06 10:21:37 +00:00
var pts = [ cloneItem . x , cloneItem . y ,
cloneItem . x1 , cloneItem . y1 ,
cloneItem . x2 , cloneItem . y2 ] ;
//end fix
2011-02-04 08:02:46 +00:00
svgedit . path . replacePathSeg ( seg . type , seg . index , pts ) ;
seg . update ( true ) ;
} ;
svgedit . path . Segment . prototype . moveCtrl = function ( num , dx , dy ) {
var item = this . item ;
2015-07-06 10:21:37 +00:00
// fix for path tool dom breakage, amending item does bad things now, so we take a copy and use that. Can probably improve to just take a shallow copy of object
var cloneItem = $ . extend ( { } , item ) ;
cloneItem [ 'x' + num ] += dx ;
cloneItem [ 'y' + num ] += dy ;
var pts = [ cloneItem . x , cloneItem . y ,
cloneItem . x1 , cloneItem . y1 , cloneItem . x2 , cloneItem . y2 ] ;
// end fix
2011-02-04 08:02:46 +00:00
svgedit . path . replacePathSeg ( this . type , this . index , pts ) ;
this . update ( true ) ;
} ;
svgedit . path . Segment . prototype . setType = function ( new _type , pts ) {
svgedit . path . replacePathSeg ( new _type , this . index , pts ) ;
this . type = new _type ;
this . item = svgedit . path . path . elem . pathSegList . getItem ( this . index ) ;
this . showCtrlPts ( new _type === 6 ) ;
this . ctrlpts = svgedit . path . getControlPoints ( this ) ;
this . update ( true ) ;
} ;
2011-02-04 16:06:25 +00:00
svgedit . path . Path = function ( elem ) {
2013-02-15 17:02:24 +00:00
if ( ! elem || elem . tagName !== 'path' ) {
throw 'svgedit.path.Path constructed without a <path> element' ;
2011-02-04 16:06:25 +00:00
}
this . elem = elem ;
this . segs = [ ] ;
this . selected _pts = [ ] ;
svgedit . path . path = this ;
this . init ( ) ;
} ;
// Reset path data
svgedit . path . Path . prototype . init = function ( ) {
// Hide all grips, etc
2015-07-06 10:21:37 +00:00
2015-07-06 10:39:41 +00:00
//fixed, needed to work on all found elements, not just first
$ ( svgedit . path . getGripContainer ( ) ) . find ( '*' ) . each ( function ( ) { $ ( this ) . attr ( 'display' , 'none' ) } ) ;
2015-07-06 10:21:37 +00:00
2011-02-04 16:06:25 +00:00
var segList = this . elem . pathSegList ;
var len = segList . numberOfItems ;
this . segs = [ ] ;
this . selected _pts = [ ] ;
this . first _seg = null ;
2013-02-14 13:11:01 +00:00
2011-02-04 16:06:25 +00:00
// Set up segs array
2014-01-31 01:05:03 +00:00
var i ;
for ( i = 0 ; i < len ; i ++ ) {
2011-02-04 16:06:25 +00:00
var item = segList . getItem ( i ) ;
var segment = new svgedit . path . Segment ( i , item ) ;
segment . path = this ;
this . segs . push ( segment ) ;
2013-02-14 13:11:01 +00:00
}
2011-02-04 16:06:25 +00:00
var segs = this . segs ;
var start _i = null ;
2014-01-31 01:05:03 +00:00
for ( i = 0 ; i < len ; i ++ ) {
2013-02-14 13:11:01 +00:00
var seg = segs [ i ] ;
2011-02-04 16:06:25 +00:00
var next _seg = ( i + 1 ) >= len ? null : segs [ i + 1 ] ;
var prev _seg = ( i - 1 ) < 0 ? null : segs [ i - 1 ] ;
2014-01-31 01:05:03 +00:00
var start _seg ;
2013-02-14 13:11:01 +00:00
if ( seg . type === 2 ) {
if ( prev _seg && prev _seg . type !== 1 ) {
2011-02-04 16:06:25 +00:00
// New sub-path, last one is open,
// so add a grip to last sub-path's first point
2014-01-31 01:05:03 +00:00
start _seg = segs [ start _i ] ;
2011-02-04 16:06:25 +00:00
start _seg . next = segs [ start _i + 1 ] ;
start _seg . next . prev = start _seg ;
start _seg . addGrip ( ) ;
}
// Remember that this is a starter seg
start _i = i ;
2013-02-14 13:11:01 +00:00
} else if ( next _seg && next _seg . type === 1 ) {
2011-02-04 16:06:25 +00:00
// This is the last real segment of a closed sub-path
// Next is first seg after "M"
seg . next = segs [ start _i + 1 ] ;
2013-02-14 13:11:01 +00:00
2011-02-04 16:06:25 +00:00
// First seg after "M"'s prev is this
seg . next . prev = seg ;
seg . mate = segs [ start _i ] ;
seg . addGrip ( ) ;
2013-02-14 13:11:01 +00:00
if ( this . first _seg == null ) {
2011-02-04 16:06:25 +00:00
this . first _seg = seg ;
}
2013-02-14 13:11:01 +00:00
} else if ( ! next _seg ) {
if ( seg . type !== 1 ) {
2011-02-04 16:06:25 +00:00
// Last seg, doesn't close so add a grip
// to last sub-path's first point
2014-01-31 01:05:03 +00:00
start _seg = segs [ start _i ] ;
2011-02-04 16:06:25 +00:00
start _seg . next = segs [ start _i + 1 ] ;
start _seg . next . prev = start _seg ;
start _seg . addGrip ( ) ;
seg . addGrip ( ) ;
2013-02-14 13:11:01 +00:00
if ( ! this . first _seg ) {
2011-02-04 16:06:25 +00:00
// Open path, so set first as real first and add grip
this . first _seg = segs [ start _i ] ;
}
}
2013-02-14 13:11:01 +00:00
} else if ( seg . type !== 1 ) {
2011-02-04 16:06:25 +00:00
// Regular segment, so add grip and its "next"
seg . addGrip ( ) ;
2013-02-14 13:11:01 +00:00
2011-02-04 16:06:25 +00:00
// Don't set its "next" if it's an "M"
2013-02-14 13:11:01 +00:00
if ( next _seg && next _seg . type !== 2 ) {
2011-02-04 16:06:25 +00:00
seg . next = next _seg ;
seg . next . prev = seg ;
}
}
}
return this ;
} ;
svgedit . path . Path . prototype . eachSeg = function ( fn ) {
2014-01-31 01:05:03 +00:00
var i ;
2013-02-14 13:11:01 +00:00
var len = this . segs . length ;
2014-01-31 01:05:03 +00:00
for ( i = 0 ; i < len ; i ++ ) {
2011-02-04 16:06:25 +00:00
var ret = fn . call ( this . segs [ i ] , i ) ;
2014-01-31 01:05:03 +00:00
if ( ret === false ) { break ; }
2011-02-04 16:06:25 +00:00
}
} ;
svgedit . path . Path . prototype . addSeg = function ( index ) {
// Adds a new segment
var seg = this . segs [ index ] ;
2014-01-31 01:05:03 +00:00
if ( ! seg . prev ) { return ; }
2011-02-04 16:06:25 +00:00
var prev = seg . prev ;
2014-02-12 01:07:26 +00:00
var newseg , new _x , new _y ;
2011-02-04 16:06:25 +00:00
switch ( seg . item . pathSegType ) {
case 4 :
2014-02-12 01:07:26 +00:00
new _x = ( seg . item . x + prev . item . x ) / 2 ;
new _y = ( seg . item . y + prev . item . y ) / 2 ;
2011-02-04 16:06:25 +00:00
newseg = this . elem . createSVGPathSegLinetoAbs ( new _x , new _y ) ;
break ;
case 6 : //make it a curved segment to preserve the shape (WRS)
// http://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm#Geometric_interpretation
var p0 _x = ( prev . item . x + seg . item . x1 ) / 2 ;
var p1 _x = ( seg . item . x1 + seg . item . x2 ) / 2 ;
var p2 _x = ( seg . item . x2 + seg . item . x ) / 2 ;
var p01 _x = ( p0 _x + p1 _x ) / 2 ;
var p12 _x = ( p1 _x + p2 _x ) / 2 ;
2014-02-12 01:07:26 +00:00
new _x = ( p01 _x + p12 _x ) / 2 ;
2011-02-04 16:06:25 +00:00
var p0 _y = ( prev . item . y + seg . item . y1 ) / 2 ;
var p1 _y = ( seg . item . y1 + seg . item . y2 ) / 2 ;
var p2 _y = ( seg . item . y2 + seg . item . y ) / 2 ;
var p01 _y = ( p0 _y + p1 _y ) / 2 ;
var p12 _y = ( p1 _y + p2 _y ) / 2 ;
2014-02-12 01:07:26 +00:00
new _y = ( p01 _y + p12 _y ) / 2 ;
2013-02-15 16:51:48 +00:00
newseg = this . elem . createSVGPathSegCurvetoCubicAbs ( new _x , new _y , p0 _x , p0 _y , p01 _x , p01 _y ) ;
var pts = [ seg . item . x , seg . item . y , p12 _x , p12 _y , p2 _x , p2 _y ] ;
svgedit . path . replacePathSeg ( seg . type , index , pts ) ;
2011-02-04 16:06:25 +00:00
break ;
}
svgedit . path . insertItemBefore ( this . elem , newseg , index ) ;
} ;
svgedit . path . Path . prototype . deleteSeg = function ( index ) {
var seg = this . segs [ index ] ;
var list = this . elem . pathSegList ;
2013-02-14 13:11:01 +00:00
2011-02-04 16:06:25 +00:00
seg . show ( false ) ;
var next = seg . next ;
2014-01-31 01:05:03 +00:00
var pt ;
2013-02-14 13:11:01 +00:00
if ( seg . mate ) {
2011-02-04 16:06:25 +00:00
// Make the next point be the "M" point
2014-01-31 01:05:03 +00:00
pt = [ next . item . x , next . item . y ] ;
2011-02-04 16:06:25 +00:00
svgedit . path . replacePathSeg ( 2 , next . index , pt ) ;
2013-02-14 13:11:01 +00:00
2011-02-04 16:06:25 +00:00
// Reposition last node
svgedit . path . replacePathSeg ( 4 , seg . index , pt ) ;
2013-02-14 13:11:01 +00:00
2011-02-04 16:06:25 +00:00
list . removeItem ( seg . mate . index ) ;
2013-02-14 13:11:01 +00:00
} else if ( ! seg . prev ) {
2011-02-04 16:06:25 +00:00
// First node of open path, make next point the M
var item = seg . item ;
2014-01-31 01:05:03 +00:00
pt = [ next . item . x , next . item . y ] ;
2011-02-04 16:06:25 +00:00
svgedit . path . replacePathSeg ( 2 , seg . next . index , pt ) ;
list . removeItem ( index ) ;
} else {
list . removeItem ( index ) ;
}
} ;
svgedit . path . Path . prototype . subpathIsClosed = function ( index ) {
var closed = false ;
// Check if subpath is already open
svgedit . path . path . eachSeg ( function ( i ) {
2014-01-31 01:05:03 +00:00
if ( i <= index ) { return true ; }
2013-02-14 13:11:01 +00:00
if ( this . type === 2 ) {
2011-02-04 16:06:25 +00:00
// Found M first, so open
return false ;
2013-02-14 13:11:01 +00:00
}
if ( this . type === 1 ) {
2011-02-04 16:06:25 +00:00
// Found Z first, so closed
closed = true ;
return false ;
}
} ) ;
2013-02-14 13:11:01 +00:00
2011-02-04 16:06:25 +00:00
return closed ;
} ;
svgedit . path . Path . prototype . removePtFromSelection = function ( index ) {
var pos = this . selected _pts . indexOf ( index ) ;
2013-02-14 13:11:01 +00:00
if ( pos == - 1 ) {
2011-02-04 16:06:25 +00:00
return ;
2013-02-14 13:11:01 +00:00
}
2011-02-04 16:06:25 +00:00
this . segs [ index ] . select ( false ) ;
this . selected _pts . splice ( pos , 1 ) ;
} ;
svgedit . path . Path . prototype . clearSelection = function ( ) {
2013-02-14 13:11:01 +00:00
this . eachSeg ( function ( ) {
2011-02-04 16:06:25 +00:00
// 'this' is the segment here
this . select ( false ) ;
} ) ;
this . selected _pts = [ ] ;
} ;
svgedit . path . Path . prototype . storeD = function ( ) {
this . last _d = this . elem . getAttribute ( 'd' ) ;
} ;
svgedit . path . Path . prototype . show = function ( y ) {
// Shows this path's segment grips
this . eachSeg ( function ( ) {
// 'this' is the segment here
this . show ( y ) ;
} ) ;
2013-02-14 13:11:01 +00:00
if ( y ) {
2011-02-04 16:06:25 +00:00
this . selectPt ( this . first _seg . index ) ;
}
return this ;
} ;
2013-02-14 13:11:01 +00:00
// Move selected points
2011-02-04 16:06:25 +00:00
svgedit . path . Path . prototype . movePts = function ( d _x , d _y ) {
var i = this . selected _pts . length ;
while ( i -- ) {
var seg = this . segs [ this . selected _pts [ i ] ] ;
seg . move ( d _x , d _y ) ;
}
} ;
svgedit . path . Path . prototype . moveCtrl = function ( d _x , d _y ) {
var seg = this . segs [ this . selected _pts [ 0 ] ] ;
seg . moveCtrl ( this . dragctrl , d _x , d _y ) ;
2013-02-14 13:11:01 +00:00
if ( link _control _pts ) {
2011-02-04 16:06:25 +00:00
seg . setLinked ( this . dragctrl ) ;
}
} ;
svgedit . path . Path . prototype . setSegType = function ( new _type ) {
this . storeD ( ) ;
var i = this . selected _pts . length ;
var text ;
while ( i -- ) {
var sel _pt = this . selected _pts [ i ] ;
2013-02-14 13:11:01 +00:00
2011-02-04 16:06:25 +00:00
// Selected seg
var cur = this . segs [ sel _pt ] ;
var prev = cur . prev ;
2014-01-31 01:05:03 +00:00
if ( ! prev ) { continue ; }
2013-02-14 13:11:01 +00:00
if ( ! new _type ) { // double-click, so just toggle
2013-02-15 17:02:24 +00:00
text = 'Toggle Path Segment Type' ;
2011-02-04 16:06:25 +00:00
// Toggle segment to curve/straight line
var old _type = cur . type ;
2013-02-14 13:11:01 +00:00
2011-02-04 16:06:25 +00:00
new _type = ( old _type == 6 ) ? 4 : 6 ;
2013-02-14 13:11:01 +00:00
}
2014-02-12 01:07:26 +00:00
new _type = Number ( new _type ) ;
2013-02-14 13:11:01 +00:00
2011-02-04 16:06:25 +00:00
var cur _x = cur . item . x ;
var cur _y = cur . item . y ;
var prev _x = prev . item . x ;
var prev _y = prev . item . y ;
var points ;
switch ( new _type ) {
case 6 :
2013-02-14 13:11:01 +00:00
if ( cur . olditem ) {
2011-02-04 16:06:25 +00:00
var old = cur . olditem ;
2013-02-15 16:51:48 +00:00
points = [ cur _x , cur _y , old . x1 , old . y1 , old . x2 , old . y2 ] ;
2011-02-04 16:06:25 +00:00
} else {
var diff _x = cur _x - prev _x ;
var diff _y = cur _y - prev _y ;
// get control points from straight line segment
/ *
var ct1 _x = ( prev _x + ( diff _y / 2 ) ) ;
var ct1 _y = ( prev _y - ( diff _x / 2 ) ) ;
var ct2 _x = ( cur _x + ( diff _y / 2 ) ) ;
var ct2 _y = ( cur _y - ( diff _x / 2 ) ) ;
* /
//create control points on the line to preserve the shape (WRS)
var ct1 _x = ( prev _x + ( diff _x / 3 ) ) ;
var ct1 _y = ( prev _y + ( diff _y / 3 ) ) ;
var ct2 _x = ( cur _x - ( diff _x / 3 ) ) ;
var ct2 _y = ( cur _y - ( diff _y / 3 ) ) ;
2013-02-15 16:51:48 +00:00
points = [ cur _x , cur _y , ct1 _x , ct1 _y , ct2 _x , ct2 _y ] ;
2011-02-04 16:06:25 +00:00
}
break ;
case 4 :
2013-02-15 16:51:48 +00:00
points = [ cur _x , cur _y ] ;
2013-02-14 13:11:01 +00:00
2011-02-04 16:06:25 +00:00
// Store original prevve segment nums
cur . olditem = cur . item ;
break ;
}
2013-02-14 13:11:01 +00:00
2011-02-04 16:06:25 +00:00
cur . setType ( new _type , points ) ;
}
svgedit . path . path . endChanges ( text ) ;
} ;
svgedit . path . Path . prototype . selectPt = function ( pt , ctrl _num ) {
this . clearSelection ( ) ;
2013-02-14 13:11:01 +00:00
if ( pt == null ) {
2011-02-04 16:06:25 +00:00
this . eachSeg ( function ( i ) {
// 'this' is the segment here.
2013-02-14 13:11:01 +00:00
if ( this . prev ) {
2011-02-04 16:06:25 +00:00
pt = i ;
}
} ) ;
}
this . addPtsToSelection ( pt ) ;
2013-02-14 13:11:01 +00:00
if ( ctrl _num ) {
2011-02-04 16:06:25 +00:00
this . dragctrl = ctrl _num ;
2013-02-14 13:11:01 +00:00
if ( link _control _pts ) {
2011-02-04 16:06:25 +00:00
this . segs [ pt ] . setLinked ( ctrl _num ) ;
}
}
} ;
2011-02-09 06:14:47 +00:00
// Update position of all points
svgedit . path . Path . prototype . update = function ( ) {
var elem = this . elem ;
2013-02-14 13:11:01 +00:00
if ( svgedit . utilities . getRotationAngle ( elem ) ) {
2011-02-09 06:14:47 +00:00
this . matrix = svgedit . math . getMatrix ( elem ) ;
this . imatrix = this . matrix . inverse ( ) ;
} else {
this . matrix = null ;
this . imatrix = null ;
}
this . eachSeg ( function ( i ) {
this . item = elem . pathSegList . getItem ( i ) ;
this . update ( ) ;
} ) ;
return this ;
} ;
2011-03-07 18:26:12 +00:00
svgedit . path . getPath _ = function ( elem ) {
var p = pathData [ elem . id ] ;
2014-01-31 01:05:03 +00:00
if ( ! p ) {
p = pathData [ elem . id ] = new svgedit . path . Path ( elem ) ;
}
2011-03-07 18:26:12 +00:00
return p ;
} ;
svgedit . path . removePath _ = function ( id ) {
2014-02-17 00:46:24 +00:00
if ( id in pathData ) { delete pathData [ id ] ; }
2011-03-07 18:26:12 +00:00
} ;
2014-02-12 01:07:26 +00:00
var newcx , newcy , oldcx , oldcy , angle ;
2011-03-07 18:26:12 +00:00
var getRotVals = function ( x , y ) {
2014-02-12 01:07:26 +00:00
var dx = x - oldcx ;
var dy = y - oldcy ;
2013-02-14 13:11:01 +00:00
2011-02-24 16:13:26 +00:00
// rotate the point around the old center
2014-02-12 01:07:26 +00:00
var r = Math . sqrt ( dx * dx + dy * dy ) ;
var theta = Math . atan2 ( dy , dx ) + angle ;
2011-02-24 16:13:26 +00:00
dx = r * Math . cos ( theta ) + oldcx ;
dy = r * Math . sin ( theta ) + oldcy ;
2013-02-14 13:11:01 +00:00
2011-02-24 16:13:26 +00:00
// dx,dy should now hold the actual coordinates of each
// point after being rotated
// now we want to rotate them around the new center in the reverse direction
dx -= newcx ;
dy -= newcy ;
2013-02-14 13:11:01 +00:00
2011-02-24 16:13:26 +00:00
r = Math . sqrt ( dx * dx + dy * dy ) ;
2013-02-15 16:51:48 +00:00
theta = Math . atan2 ( dy , dx ) - angle ;
2013-02-14 13:11:01 +00:00
2014-02-12 01:07:26 +00:00
return { 'x' : r * Math . cos ( theta ) + newcx ,
'y' : r * Math . sin ( theta ) + newcy } ;
2011-02-24 16:13:26 +00:00
} ;
2011-03-07 18:26:12 +00:00
// If the path was rotated, we must now pay the piper:
// Every path point must be rotated into the rotated coordinate system of
// its old center, then determine the new center, then rotate it back
// This is because we want the path to remember its rotation
// TODO: This is still using ye olde transform methods, can probably
// be optimized or even taken care of by recalculateDimensions
svgedit . path . recalcRotatedPath = function ( ) {
var current _path = svgedit . path . path . elem ;
2014-02-12 01:07:26 +00:00
angle = svgedit . utilities . getRotationAngle ( current _path , true ) ;
2014-01-31 01:05:03 +00:00
if ( ! angle ) { return ; }
2011-03-07 18:26:12 +00:00
// selectedBBoxes[0] = svgedit.path.path.oldbbox;
var box = svgedit . utilities . getBBox ( current _path ) ,
2014-02-12 01:07:26 +00:00
oldbox = svgedit . path . path . oldbbox ; //selectedBBoxes[0],
oldcx = oldbox . x + oldbox . width / 2 ;
oldcy = oldbox . y + oldbox . height / 2 ;
newcx = box . x + box . width / 2 ;
newcy = box . y + box . height / 2 ;
2013-02-14 13:11:01 +00:00
2011-03-07 18:26:12 +00:00
// un-rotate the new center to the proper position
2014-02-12 01:07:26 +00:00
var dx = newcx - oldcx ,
2011-03-07 18:26:12 +00:00
dy = newcy - oldcy ,
r = Math . sqrt ( dx * dx + dy * dy ) ,
2013-02-15 16:51:48 +00:00
theta = Math . atan2 ( dy , dx ) + angle ;
2013-02-14 13:11:01 +00:00
2011-03-07 18:26:12 +00:00
newcx = r * Math . cos ( theta ) + oldcx ;
newcy = r * Math . sin ( theta ) + oldcy ;
2013-02-14 13:11:01 +00:00
2011-03-07 18:26:12 +00:00
var list = current _path . pathSegList ,
i = list . numberOfItems ;
while ( i ) {
i -= 1 ;
var seg = list . getItem ( i ) ,
type = seg . pathSegType ;
2014-01-31 01:05:03 +00:00
if ( type == 1 ) { continue ; }
2013-02-14 13:11:01 +00:00
2013-02-15 16:51:48 +00:00
var rvals = getRotVals ( seg . x , seg . y ) ,
2011-03-07 18:26:12 +00:00
points = [ rvals . x , rvals . y ] ;
2013-02-14 13:11:01 +00:00
if ( seg . x1 != null && seg . x2 != null ) {
2014-02-12 01:07:26 +00:00
var c _vals1 = getRotVals ( seg . x1 , seg . y1 ) ;
var c _vals2 = getRotVals ( seg . x2 , seg . y2 ) ;
2011-03-07 18:26:12 +00:00
points . splice ( points . length , 0 , c _vals1 . x , c _vals1 . y , c _vals2 . x , c _vals2 . y ) ;
}
svgedit . path . replacePathSeg ( type , i , points ) ;
} // loop for each point
2011-02-24 16:13:26 +00:00
2013-02-14 13:11:01 +00:00
box = svgedit . utilities . getBBox ( current _path ) ;
2011-03-07 18:26:12 +00:00
// selectedBBoxes[0].x = box.x; selectedBBoxes[0].y = box.y;
// selectedBBoxes[0].width = box.width; selectedBBoxes[0].height = box.height;
2013-02-14 13:11:01 +00:00
2011-03-07 18:26:12 +00:00
// now we must set the new transform to be rotated around the new center
var R _nc = svgroot . createSVGTransform ( ) ,
tlist = svgedit . transformlist . getTransformList ( current _path ) ;
R _nc . setRotate ( ( angle * 180.0 / Math . PI ) , newcx , newcy ) ;
tlist . replaceItem ( R _nc , 0 ) ;
2011-02-23 16:24:07 +00:00
} ;
// ====================================
// Public API starts here
svgedit . path . clearData = function ( ) {
pathData = { } ;
} ;
2014-01-31 01:05:03 +00:00
} ( ) ) ;