Move parseFontFaceDescriptor to CSSPropertyParser.cpp
[chromium-blink-merge.git] / third_party / WebKit / LayoutTests / svg / carto.net / resources / helper_functions.js
blob1c8607048a91f387f08bfad8e936420bd816229d
1 /*
2 ECMAScript helper functions
3 Copyright (C) <2004> <Andreas Neumann>
4 Version 1.1, 2004-11-18
5 neumann@karto.baug.ethz.ch
6 http://www.carto.net/
7 http://www.carto.net/neumann/
9 Credits: numerous people on svgdevelopers@yahoogroups.com
11 This ECMA script library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 2.1 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library (http://www.carto.net/papers/svg/resources/lesser_gpl.txt); if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 ----
27 original document site: http://www.carto.net/papers/svg/resources/helper_functions.js
28 Please contact the author in case you want to use code or ideas commercially.
29 If you use this code, please include this copyright header, the included full
30 LGPL 2.1 text and read the terms provided in the LGPL 2.1 license
31 (http://www.gnu.org/copyleft/lesser.txt)
33 -------------------------------
35 Please report bugs and send improvements to neumann@karto.baug.ethz.ch
36 If you use these scripts, please link to the original (http://www.carto.net/papers/svg/navigationTools/)
37 somewhere in the source-code-comment or the "about" of your project and give credits, thanks!
41 //global variables necessary to create elements in these namespaces, do not delete them!!!!
42 var svgNS = "http://www.w3.org/2000/svg";
43 var xlinkNS = "http://www.w3.org/1999/xlink";
44 var cartoNS = "http://www.carto.net/attrib";
45 var attribNS = "http://www.carto.net/attrib";
46 var batikNS = "http://xml.apache.org/batik/ext";
48 /* ----------------------- helper functions to calculate stuff ---------------- */
49 /* ---------------------------------------------------------------------------- */
50 function toPolarDir(xdiff,ydiff) { // Subroutine for calculating polar Coordinates
51 direction = (Math.atan2(ydiff,xdiff));
52 //result is angle in radian
53 return(direction);
56 function toPolarDist(xdiff,ydiff) { // Subroutine for calculating polar Coordinates
57 distance = Math.sqrt(xdiff * xdiff + ydiff * ydiff);
58 return(distance);
61 function toRectX(direction,distance) { // Subroutine for calculating cartesic coordinates
62 x = distance * Math.cos(direction);
63 y = distance * Math.sin(direction);
64 return(x);
67 function toRectY(direction,distance) { // Subroutine for calculating cartesic coordinates
68 x = distance * Math.cos(direction);
69 y = distance * Math.sin(direction);
70 return(y);
73 //Converts degrees to radians.
74 function DegToRad(deg) {
75 return (deg / 180.0 * Math.PI);
78 //Converts radians to degrees.
79 function RadToDeg(rad) {
80 return (rad / Math.PI * 180.0);
83 //converts decimal degrees to degree/minutes/seconds
84 function dd2dms(dd) {
85 var minutes = (Math.abs(dd) - Math.floor(Math.abs(dd))) * 60;
86 var seconds = (minutes - Math.floor(minutes)) * 60;
87 var minutes = Math.floor(minutes);
88 var degrees = Math.floor(dd);
89 return {deg:degrees,min:minutes,sec:seconds};
92 //converts degree/minutes/seconds to decimal degrees
93 function dms2dd(deg,min,sec) {
94 return deg + (min / 60) + (sec / 3600);
97 //log functions that do not exist in Math object
98 function log(x,b) {
99 if(b==null) b=Math.E;
100 return Math.log(x)/Math.log(b);
103 //gets 4 z-values (4 corners), a position, delta x and delty and a cellsize as input and returns interpolated z-value
104 function intBilinear(za,zb,zc,zd,xpos,ypos,ax,ay,cellsize) { //bilinear interpolation function
105 e = (xpos - ax) / cellsize;
106 f = (ypos - ay) / cellsize;
108 //calculation of weights
109 wa = (1 - e) * (1 - f);
110 wb = e * (1 - f);
111 wc = e * f;
112 wd = f * (1 - e);
114 height_interpol = wa * zc + wb * zd + wc * za + wd * zb;
116 return (height_interpol);
119 //test if point is left of or right of, result is 1 (leftof) or 0 (rightof)
120 function leftOfTest(pointx,pointy,linex1,liney1,linex2,liney2) {
121 result = (liney1 - pointy) * (linex2 - linex1) - (linex1 - pointx) * (liney2 - liney1);
122 if (result < 0) {
123 leftof = 1; //case left of
125 else {
126 leftof = 0; //case left of
128 return(leftof);
131 //input is point coordinate, and 2 line coordinates
132 function distFromLine(xpoint,ypoint,linex1,liney1,linex2,liney2) {
133 dx = linex2 - linex1;
134 dy = liney2 - liney1;
135 distance = (dy * (xpoint - linex1) - dx * (ypoint - liney1)) / Math.sqrt(Math.pow(dx,2) + Math.pow(dy,2));
136 return(distance);
139 //converts radian value to degrees
140 function radian2deg(radian) {
141 deg = radian / Math.PI * 180;
142 return(deg);
145 //input is two vectors (a1,a2 is vector a, b1,b2 is vector b), output is angle in radian
146 //Formula: Acos from Scalaproduct of the two vectors divided by ( norm (deutsch Betrag) vector 1 by norm vector 2
147 //see http://www.mathe-online.at/mathint/vect2/i.html#Winkel
148 function angleBetwTwoLines(a1,a2,b1,b2) {
149 angle = Math.acos((a1 * b1 + a2 * b2) / (Math.sqrt(Math.pow(a1,2) + Math.pow(a2,2)) * Math.sqrt(Math.pow(b1,2) + Math.pow(b2,2))));
150 return(angle);
153 //input is two vectors (a1,a2 is vector a, b1,b2 is vector b), output is new vector c2 returned as array
154 //Formula: Vektor a divided by Norm Vector a (Betrag) plus Vektor b divided by Norm Vector b (Betrag)
155 //see http://www.mathe-online.at/mathint/vect1/i.html#Winkelsymmetrale
156 function calcBisectorVector(a1,a2,b1,b2) {
157 betraga = Math.sqrt(Math.pow(a1,2) + Math.pow(a2,2));
158 betragb = Math.sqrt(Math.pow(b1,2) + Math.pow(b2,2));
159 c = new Array();
160 c[0] = a1 / betraga + b1 / betragb;
161 c[1] = a2 / betraga + b2 / betragb;
162 return(c);
165 //input is two vectors (a1,a2 is vector a, b1,b2 is vector b), output is angle in radian
166 //Formula: Vektor a divided by Norm Vector a (Betrag) plus Vektor b divided by Norm Vector b (Betrag)
167 //see http://www.mathe-online.at/mathint/vect1/i.html#Winkelsymmetrale
168 function calcBisectorAngle(a1,a2,b1,b2) {
169 betraga = Math.sqrt(Math.pow(a1,2) + Math.pow(a2,2));
170 betragb = Math.sqrt(Math.pow(b1,2) + Math.pow(b2,2));
171 c1 = a1 / betraga + b1 / betragb;
172 c2 = a2 / betraga + b2 / betragb;
173 angle = toPolarDir(c1,c2);
174 return(angle);
177 function intersect2lines(line1x1,line1y1,line1x2,line1y2,line2x1,line2y1,line2x2,line2y2) {
178 //formula see http://astronomy.swin.edu.au/~pbourke/geometry/lineline2d/
179 var result = new Array();
180 var denominator = (line2y2 - line2y1)*(line1x2 - line1x1) - (line2x2 - line2x1)*(line1y2 - line1y1);
181 if (denominator == 0) {
182 alert("lines are parallel");
184 else {
185 ua = ((line2x2 - line2x1)*(line1y1 - line2y1) - (line2y2 - line2y1)*(line1x1 - line2x1)) / denominator;
186 ub = ((line1x2 - line1x1)*(line1y1 - line2y1) - (line1y2 - line1y1)*(line1x1 - line2x1)) / denominator;
188 result["x"] = line1x1 + ua * (line1x2 - line1x1);
189 result["y"] = line1y1 + ua * (line1y2 - line1y1);
190 return(result);
193 /* ----------------------- helper function to sort arrays ---------------- */
194 /* ----------------------------------------------------------------------- */
195 //my own sort function, uses only first part of string (population value)
196 function mySort(a,b) {
197 var myResulta = a.split("+");
198 var myResultb = b.split("+");
199 if (parseFloat(myResulta[0]) < parseFloat(myResultb[0])) {
200 return 1;
202 else {
203 return -1;
207 /* ----------------------- helper function format number strings -------------- */
208 /* ---------------------------------------------------------------------------- */
209 //formatting number strings
210 //this function add's "'" to a number every third digit
211 function formatNumberString(myString) {
212 //check if of type string, if number, convert it to string
213 if (typeof(myString) == "number") {
214 myTempString = myString.toString();
216 else {
217 myTempString = myString;
219 var myNewString="";
220 //if it contains a comma, it will be split
221 var splitResults = myTempString.split(".");
222 var myCounter= splitResults[0].length;
223 if (myCounter > 3) {
224 while(myCounter > 0) {
225 if (myCounter > 3) {
226 myNewString = "," + splitResults[0].substr(myCounter - 3,3) + myNewString;
228 else {
229 myNewString = splitResults[0].substr(0,myCounter) + myNewString;
231 myCounter -= 3;
234 else {
235 myNewString = splitResults[0];
237 //concatenate if it contains a comma
238 if (splitResults[1]) {
239 myNewString = myNewString + "." + splitResults[1];
241 return myNewString;
244 //function for status Bar
245 function statusChange(statusText) {
246 document.getElementById("statusText").firstChild.nodeValue = "Statusbar: " + statusText;
249 //scale an object
250 function scaleObject(evt,factor) {
251 //reference to the currently selected object
252 var element = evt.currentTarget;
253 var myX = element.getAttributeNS(null,"x");
254 var myY = element.getAttributeNS(null,"y");
255 var newtransform = "scale(" + factor + ") translate(" + (myX * 1 / factor - myX) + " " + (myY * 1 / factor - myY) +")";
256 element.setAttributeNS(null,'transform', newtransform);
259 //this code is copied from Kevin Lindsey
260 //http://www.kevlindev.com/tutorials/basics/transformations/toUserSpace/index.htm
261 function getTransformToRootElement(node) {
262 try {
263 //this part is for fully conformant players
264 var CTM = node.getTransformToElement(document.documentElement);
266 catch (ex) {
267 //this part is for ASV3 or other non-conformant players
268 // Initialize our CTM the node's Current Transformation Matrix
269 var CTM = node.getCTM();
270 // Work our way through the ancestor nodes stopping at the SVG Document
271 while ( ( node = node.parentNode ) != document ) {
272 // Multiply the new CTM to the one with what we have accumulated so far
273 CTM = node.getCTM().multiply(CTM);
276 return CTM;
279 //this is because ASV does not implement the method SVGLocatable.getTransformToElement()
280 function getTransformToElement(node,targetNode) {
281 try {
282 //this part is for fully conformant players
283 var CTM = node.getTransformToElement(targetNode);
285 catch (ex) {
286 //this part is for ASV3 or other non-conformant players
287 // Initialize our CTM the node's Current Transformation Matrix
288 var CTM = node.getCTM();
289 // Work our way through the ancestor nodes stopping at the SVG Document
290 while ( ( node = node.parentNode ) != targetNode ) {
291 // Multiply the new CTM to the one with what we have accumulated so far
292 CTM = node.getCTM().multiply(CTM);
295 return CTM;
298 //calculate HSV 2 RGB: HSV (h 0 to 360, sat and val are between 0 and 1), RGB between 0 and 255
299 function hsv2rgb(hue,sat,val) {
300 //alert("Hue:"+hue);
301 var rgbArr = new Array();
302 if ( sat == 0) {
303 rgbArr["red"] = Math.round(val * 255);
304 rgbArr["green"] = Math.round(val * 255);
305 rgbArr["blue"] = Math.round(val * 255);
307 else {
308 var h = hue / 60;
309 var i = Math.floor(h);
310 var f = h - i;
311 if (i % 2 == 0) {
312 f = 1 - f;
314 var m = val * (1 - sat);
315 var n = val * (1 - sat * f);
316 switch(i) {
317 case 0:
318 rgbArr["red"] = val;
319 rgbArr["green"] = n;
320 rgbArr["blue"] = m;
321 break;
322 case 1:
323 rgbArr["red"] = n;
324 rgbArr["green"] = val;
325 rgbArr["blue"] = m;
326 break;
327 case 2:
328 rgbArr["red"] = m;
329 rgbArr["green"] = val;
330 rgbArr["blue"] = n;
331 break;
332 case 3:
333 rgbArr["red"] = m;
334 rgbArr["green"] = n;
335 rgbArr["blue"] = val;
336 break;
337 case 4:
338 rgbArr["red"] = n;
339 rgbArr["green"] = m;
340 rgbArr["blue"] = val;
341 break;
342 case 5:
343 rgbArr["red"] = val;
344 rgbArr["green"] = m;
345 rgbArr["blue"] = n;
346 break;
347 case 6:
348 rgbArr["red"] = val;
349 rgbArr["green"] = n;
350 rgbArr["blue"] = m;
351 break;
353 rgbArr["red"] = Math.round(rgbArr["red"] * 255);
354 rgbArr["green"] = Math.round(rgbArr["green"] * 255);
355 rgbArr["blue"] = Math.round(rgbArr["blue"] * 255);
357 return rgbArr;
360 //calculate rgb to hsv values
361 function rgb2hsv (red,green,blue) {
362 //input between 0 and 255 --> normalize to 0 to 1
363 //result =
364 var hsvArr = new Array();
365 red = red / 255;
366 green = green / 255;
367 blue = blue / 255;
368 myMax = Math.max(red, Math.max(green,blue));
369 myMin = Math.min(red, Math.min(green,blue));
370 v = myMax;
371 if (myMax > 0) {
372 s = (myMax - myMin) / myMax;
374 else {
375 s = 0;
377 if (s > 0) {
378 myDiff = myMax - myMin;
379 rc = (myMax - red) / myDiff;
380 gc = (myMax - green) / myDiff;
381 bc = (myMax - blue) / myDiff;
382 if (red == myMax) {
383 h = (bc - gc) / 6;
385 if (green == myMax) {
386 h = (2 + rc - bc) / 6;
388 if (blue == myMax) {
389 h = (4 + gc - rc) / 6;
392 else {
393 h = 0;
395 if (h < 0) {
396 h += 1;
398 hsvArr["hue"] = Math.round(h * 360);
399 hsvArr["sat"] = s;
400 hsvArr["val"] = v;
401 return hsvArr;
404 //populate an array that can be addressed by both a key or an index nr
405 function assArrayPopulate(arrayKeys,arrayValues) {
406 var returnArray = new Array();
407 if (arrayKeys.length != arrayValues.length) {
408 alert("error: arrays do not have same length!");
410 else {
411 for (i=0;i<arrayKeys.length;i++) {
412 returnArray[arrayKeys[i]] = arrayValues[i];
415 return returnArray;
418 //replace special (non-ASCII) characters with their charCode
419 function replaceSpecialChars(myString) {
420 for (i=161;i<256;i++) {
421 re = new RegExp("&#"+i+";","g");
422 myString = myString.replace(re,String.fromCharCode(i));
424 return myString;
427 /* ----------------------- getXMLData object ----------------------------- */
428 /* ----------------------------------------------------------------------- */
429 //this object allows to make network requests using getURL or XMLHttpRequest
430 //you may specify a url and a callBackFunction
431 //the callBackFunction receives a XML node representing the rootElement of the fragment received
432 function getXMLData(url,callBackFunction) {
433 this.url = url;
434 this.callBackFunction = callBackFunction;
435 this.xmlRequest = null;
438 getXMLData.prototype.getData = function() {
439 //call getURL() if available
440 if (window.getURL) {
441 getURL(this.url,this);
443 //or call XMLHttpRequest() if available
444 else if (window.XMLHttpRequest) {
445 var _this = this;
446 this.xmlRequest = new XMLHttpRequest();
447 this.xmlRequest.overrideMimeType("text/xml");
448 this.xmlRequest.open("GET",this.url,true);
449 this.xmlRequest.onreadystatechange = function() {_this.handleEvent()};
450 this.xmlRequest.send(null);
452 //write an error message if neither method is available
453 else {
454 alert("your browser/svg viewer neither supports window.getURL nor window.XMLHttpRequest!");
458 //this is the callback method for the getURL function
459 getXMLData.prototype.operationComplete = function(data) {
460 //check if data has a success property
461 if (data.success) {
462 //parse content of the XML format to the variable "node"
463 var node = parseXML(data.content,document);
464 this.callBackFunction(node.firstChild);
466 else {
467 alert("something went wrong with dynamic loading of geometry!");
471 //this method receives data from XMLHttpRequest
472 getXMLData.prototype.handleEvent = function() {
473 if (this.xmlRequest.readyState == 4) {
474 var importedNode = document.importNode(this.xmlRequest.responseXML.documentElement,true);
475 this.callBackFunction(importedNode);
479 //starts an animation with the given id
480 //this function is useful in combination with window.setTimeout()
481 function startAnimation(id) {
482 document.getElementById(id).beginElement();