1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008-2010 Ricardo Quesada
  4  Copyright (c) 2011      Zynga Inc.
  5 
  6  http://www.cocos2d-x.org
  7 
  8  Permission is hereby granted, free of charge, to any person obtaining a copy
  9  of this software and associated documentation files (the "Software"), to deal
 10  in the Software without restriction, including without limitation the rights
 11  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12  copies of the Software, and to permit persons to whom the Software is
 13  furnished to do so, subject to the following conditions:
 14 
 15  The above copyright notice and this permission notice shall be included in
 16  all copies or substantial portions of the Software.
 17 
 18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24  THE SOFTWARE.
 25  ****************************************************************************/
 26 
 27 /**
 28  * <p>
 29  *   Drawing primitives Utility Class. this class is base class, it contain some render type version: Canvas, WebGL, DOM.<br/>
 30  *   this class contain some primitive Drawing Method: <br/>
 31  *     - drawPoint<br/>
 32  *     - drawLine<br/>
 33  *     - drawPoly<br/>
 34  *     - drawCircle<br/>
 35  *     - drawQuadBezier<br/>
 36  *     - drawCubicBezier<br/>
 37  *     You can change the color, width and other property by calling these WebGL API:<br/>
 38  *     glColor4ub(), glLineWidth(), glPointSize().<br/>
 39  * </p>
 40  * @class
 41  * @extends cc.Class
 42  * @warning These functions draws the Line, Point, Polygon, immediately. They aren't batched. <br/>
 43  *   If you are going to make a game that depends on these primitives, I suggest creating a batch.
 44  */
 45 cc.DrawingPrimitive = cc.Class.extend(/** @lends cc.DrawingPrimitive# */{
 46     _renderContext:null,
 47 
 48     /**
 49      * set render context of drawing primitive
 50      * @param context
 51      */
 52     setRenderContext:function (context) {
 53         this._renderContext = context;
 54     },
 55 
 56     /**
 57      * returns render context of drawing primitive
 58      * @return {CanvasRenderingContext2D}
 59      */
 60     getRenderContext:function () {
 61         return this._renderContext;
 62     },
 63 
 64     /**
 65      * Constructor
 66      * @param {CanvasRenderingContext2D} renderContext
 67      */
 68     ctor:function (renderContext) {
 69         this._renderContext = renderContext;
 70     },
 71 
 72     /**
 73      * draws a point given x and y coordinate measured in points
 74      * @param {cc.Point} point
 75      */
 76     drawPoint:function (point) {
 77         cc.log("DrawingPrimitive.drawPoint() not implement!");
 78     },
 79 
 80     /**
 81      * draws an array of points.
 82      * @param {Array} points point of array
 83      * @param {Number} numberOfPoints
 84      */
 85     drawPoints:function (points, numberOfPoints) {
 86         cc.log("DrawingPrimitive.drawPoints() not implement!");
 87     },
 88 
 89     /**
 90      * draws a line given the origin and destination point measured in points
 91      * @param {cc.Point} origin
 92      * @param {cc.Point} destination
 93      */
 94     drawLine:function (origin, destination) {
 95         cc.log("DrawingPrimitive.drawLine() not implement!");
 96     },
 97 
 98     /**
 99      * draws a rectangle given the origin and destination point measured in points.
100      * @param {cc.Point} origin
101      * @param {cc.Point} destination
102      */
103     drawRect:function (origin, destination) {
104         cc.log("DrawingPrimitive.drawRect() not implement!");
105     },
106 
107     /**
108      * draws a solid rectangle given the origin and destination point measured in points.
109      * @param {cc.Point} origin
110      * @param {cc.Point} destination
111      * @param {cc.Color} color
112      */
113     drawSolidRect:function (origin, destination, color) {
114         cc.log("DrawingPrimitive.drawSolidRect() not implement!");
115     },
116 
117     /**
118      * draws a poligon given a pointer to cc.Point coordiantes and the number of vertices measured in points.
119      * @param {Array} vertices a pointer to cc.Point coordiantes
120      * @param {Number} numOfVertices the number of vertices measured in points
121      * @param {Boolean} closePolygon The polygon can be closed or open
122      * @param {Boolean} fill The polygon can be closed or open and optionally filled with current color
123      */
124     drawPoly:function (vertices, numOfVertices, closePolygon, fill) {
125         cc.log("DrawingPrimitive.drawPoly() not implement!");
126     },
127 
128     /**
129      * draws a solid polygon given a pointer to CGPoint coordiantes, the number of vertices measured in points, and a color.
130      * @param {Array} poli
131      * @param {Number} numberOfPoints
132      * @param {cc.Color} color
133      */
134     drawSolidPoly:function (poli, numberOfPoints, color) {
135         cc.log("DrawingPrimitive.drawSolidPoly() not implement!");
136     },
137 
138     /**
139      * draws a circle given the center, radius and number of segments.
140      * @param {cc.Point} center center of circle
141      * @param {Number} radius
142      * @param {Number} angle angle in radians
143      * @param {Number} segments
144      * @param {Boolean} drawLineToCenter
145      */
146     drawCircle:function (center, radius, angle, segments, drawLineToCenter) {
147         cc.log("DrawingPrimitive.drawCircle() not implement!");
148     },
149 
150     /**
151      * draws a quad bezier path
152      * @param {cc.Point} origin
153      * @param {cc.Point} control
154      * @param {cc.Point} destination
155      * @param {Number} segments
156      */
157     drawQuadBezier:function (origin, control, destination, segments) {
158         cc.log("DrawingPrimitive.drawQuadBezier() not implement!");
159     },
160 
161     /**
162      * draws a cubic bezier path
163      * @param {cc.Point} origin
164      * @param {cc.Point} control1
165      * @param {cc.Point} control2
166      * @param {cc.Point} destination
167      * @param {Number} segments
168      */
169     drawCubicBezier:function (origin, control1, control2, destination, segments) {
170         cc.log("DrawingPrimitive.drawCubicBezier() not implement!");
171     },
172 
173     /**
174      * draw a catmull rom line
175      * @param {Array} points
176      * @param {Number} segments
177      */
178     drawCatmullRom:function (points, segments) {
179         cc.log("DrawingPrimitive.drawCardinalSpline() not implement!");
180     },
181 
182     /**
183      * draw a cardinal spline path
184      * @param {Array} config
185      * @param {Number} tension
186      * @param {Number} segments
187      */
188     drawCardinalSpline:function (config, tension, segments) {
189         cc.log("DrawingPrimitive.drawCardinalSpline() not implement!");
190     }
191 });
192 
193 /**
194  * Canvas of DrawingPrimitive implement version
195  * @class
196  * @extends cc.DrawingPrimitive
197  */
198 cc.DrawingPrimitiveCanvas = cc.DrawingPrimitive.extend(/** @lends cc.DrawingPrimitiveCanvas# */{
199     _cacheArray:[],
200     /**
201      * draws a point given x and y coordinate measured in points
202      * @override
203      * @param {cc.Point} point
204      * @param {Number} size
205      */
206     drawPoint:function (point, size) {
207         if (!size) {
208             size = 1;
209         }
210         var locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY();
211         var newPoint = cc.p(point.x  * locScaleX, point.y * locScaleY);
212         this._renderContext.beginPath();
213         this._renderContext.arc(newPoint.x, -newPoint.y, size * locScaleX, 0, Math.PI * 2, false);
214         this._renderContext.closePath();
215         this._renderContext.fill();
216     },
217 
218     /**
219      * draws an array of points.
220      * @override
221      * @param {Array} points point of array
222      * @param {Number} numberOfPoints
223      * @param {Number} size
224      */
225     drawPoints:function (points, numberOfPoints, size) {
226         if (points == null) {
227             return;
228         }
229         if (!size) {
230             size = 1;
231         }
232         var locContext = this._renderContext,locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY();
233 
234         locContext.beginPath();
235         for (var i = 0, len = points.length; i < len; i++)
236             locContext.arc(points[i].x * locScaleX, -points[i].y * locScaleY, size * locScaleX, 0, Math.PI * 2, false);
237         locContext.closePath();
238         locContext.fill();
239     },
240 
241     /**
242      * draws a line given the origin and destination point measured in points
243      * @override
244      * @param {cc.Point} origin
245      * @param {cc.Point} destination
246      */
247     drawLine:function (origin, destination) {
248         var locContext = this._renderContext, locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY();
249         locContext.beginPath();
250         locContext.moveTo(origin.x * locScaleX, -origin.y * locScaleY);
251         locContext.lineTo(destination.x * locScaleX, -destination.y * locScaleY);
252         locContext.closePath();
253         locContext.stroke();
254     },
255 
256     /**
257      * draws a rectangle given the origin and destination point measured in points.
258      * @param {cc.Point} origin
259      * @param {cc.Point} destination
260      */
261     drawRect:function (origin, destination) {
262         this.drawLine(cc.p(origin.x, origin.y), cc.p(destination.x, origin.y));
263         this.drawLine(cc.p(destination.x, origin.y), cc.p(destination.x, destination.y));
264         this.drawLine(cc.p(destination.x, destination.y), cc.p(origin.x, destination.y));
265         this.drawLine(cc.p(origin.x, destination.y), cc.p(origin.x, origin.y));
266     },
267 
268     /**
269      * draws a solid rectangle given the origin and destination point measured in points.
270      * @param {cc.Point} origin
271      * @param {cc.Point} destination
272      * @param {cc.Color} color
273      */
274     drawSolidRect:function (origin, destination, color) {
275         var vertices = [
276             origin,
277             cc.p(destination.x, origin.y),
278             destination,
279             cc.p(origin.x, destination.y)
280         ];
281 
282         this.drawSolidPoly(vertices, 4, color);
283     },
284 
285     /**
286      * draws a polygon given a pointer to cc.Point coordinates and the number of vertices measured in points.
287      * @override
288      * @param {Array} vertices a pointer to cc.Point coordinates
289      * @param {Number} numOfVertices the number of vertices measured in points
290      * @param {Boolean} closePolygon The polygon can be closed or open
291      * @param {Boolean} [fill=] The polygon can be closed or open and optionally filled with current color
292      */
293     drawPoly:function (vertices, numOfVertices, closePolygon, fill) {
294         fill = fill || false;
295 
296         if (vertices == null)
297             return;
298 
299         if (vertices.length < 3)
300             throw new Error("Polygon's point must greater than 2");
301 
302         var firstPoint = vertices[0], locContext = this._renderContext;
303         var locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY();
304         locContext.beginPath();
305         locContext.moveTo(firstPoint.x * locScaleX, -firstPoint.y * locScaleY);
306         for (var i = 1, len = vertices.length; i < len; i++)
307             locContext.lineTo(vertices[i].x * locScaleX, -vertices[i].y * locScaleY);
308 
309         if (closePolygon)
310             locContext.closePath();
311 
312         if (fill)
313             locContext.fill();
314         else
315             locContext.stroke();
316     },
317 
318     /**
319      * draws a solid polygon given a pointer to CGPoint coordinates, the number of vertices measured in points, and a color.
320      * @param {Array} polygons
321      * @param {Number} numberOfPoints
322      * @param {cc.Color} color
323      */
324     drawSolidPoly:function (polygons, numberOfPoints, color) {
325         this.setDrawColor(color.r, color.g, color.b, color.a);
326         this.drawPoly(polygons, numberOfPoints, true, true);
327     },
328 
329     /**
330      * draws a circle given the center, radius and number of segments.
331      * @override
332      * @param {cc.Point} center center of circle
333      * @param {Number} radius
334      * @param {Number} angle angle in radians
335      * @param {Number} segments
336      * @param {Boolean} [drawLineToCenter=]
337      */
338     drawCircle: function (center, radius, angle, segments, drawLineToCenter) {
339         drawLineToCenter = drawLineToCenter || false;
340         var locContext = this._renderContext;
341         var locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY();
342         locContext.beginPath();
343         var endAngle = angle - Math.PI * 2;
344         locContext.arc(0 | (center.x * locScaleX), 0 | -(center.y * locScaleY), radius * locScaleX, -angle, -endAngle, false);
345         if (drawLineToCenter) {
346             locContext.lineTo(0 | (center.x * locScaleX), 0 | -(center.y * locScaleY));
347         }
348         locContext.stroke();
349     },
350 
351     /**
352      * draws a quad bezier path
353      * @override
354      * @param {cc.Point} origin
355      * @param {cc.Point} control
356      * @param {cc.Point} destination
357      * @param {Number} segments
358      */
359     drawQuadBezier:function (origin, control, destination, segments) {
360         //this is OpenGL Algorithm
361         var vertices = this._cacheArray;
362         vertices.length =0;
363 
364         var t = 0.0;
365         for (var i = 0; i < segments; i++) {
366             var x = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x;
367             var y = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y;
368             vertices.push(cc.p(x, y));
369             t += 1.0 / segments;
370         }
371         vertices.push(cc.p(destination.x, destination.y));
372 
373         this.drawPoly(vertices, segments + 1, false, false);
374     },
375 
376     /**
377      * draws a cubic bezier path
378      * @override
379      * @param {cc.Point} origin
380      * @param {cc.Point} control1
381      * @param {cc.Point} control2
382      * @param {cc.Point} destination
383      * @param {Number} segments
384      */
385     drawCubicBezier:function (origin, control1, control2, destination, segments) {
386         //this is OpenGL Algorithm
387         var vertices = this._cacheArray;
388         vertices.length =0;
389 
390         var t = 0;
391         for (var i = 0; i < segments; i++) {
392             var x = Math.pow(1 - t, 3) * origin.x + 3.0 * Math.pow(1 - t, 2) * t * control1.x + 3.0 * (1 - t) * t * t * control2.x + t * t * t * destination.x;
393             var y = Math.pow(1 - t, 3) * origin.y + 3.0 * Math.pow(1 - t, 2) * t * control1.y + 3.0 * (1 - t) * t * t * control2.y + t * t * t * destination.y;
394             vertices.push(cc.p(x , y ));
395             t += 1.0 / segments;
396         }
397         vertices.push(cc.p(destination.x , destination.y));
398 
399         this.drawPoly(vertices, segments + 1, false, false);
400     },
401 
402     /**
403      * draw a CatmullRom curve
404      * @override
405      * @param {Array} points
406      * @param {Number} segments
407      */
408     drawCatmullRom:function (points, segments) {
409         this.drawCardinalSpline(points, 0.5, segments);
410     },
411 
412     /**
413      * draw a cardinal spline path
414      * @override
415      * @param {Array} config
416      * @param {Number} tension
417      * @param {Number} segments
418      */
419     drawCardinalSpline:function (config, tension, segments) {
420         //lazy_init();
421         cc._renderContext.strokeStyle = "rgba(255,255,255,1)";
422         var points = this._cacheArray;
423         points.length = 0;
424         var p, lt;
425         var deltaT = 1.0 / config.length;
426 
427         for (var i = 0; i < segments + 1; i++) {
428             var dt = i / segments;
429 
430             // border
431             if (dt == 1) {
432                 p = config.length - 1;
433                 lt = 1;
434             } else {
435                 p = 0 | (dt / deltaT);
436                 lt = (dt - deltaT * p) / deltaT;
437             }
438 
439             // Interpolate
440             var newPos = cc.CardinalSplineAt(
441                 cc.getControlPointAt(config, p - 1),
442                 cc.getControlPointAt(config, p - 0),
443                 cc.getControlPointAt(config, p + 1),
444                 cc.getControlPointAt(config, p + 2),
445                 tension, lt);
446             points.push(newPos);
447         }
448         this.drawPoly(points, segments + 1, false, false);
449     },
450 
451     /**
452      * draw an image
453      * @override
454      * @param {HTMLImageElement|HTMLCanvasElement} image
455      * @param {cc.Point} sourcePoint
456      * @param {cc.Size} sourceSize
457      * @param {cc.Point} destPoint
458      * @param {cc.Size} destSize
459      */
460     drawImage:function (image, sourcePoint, sourceSize, destPoint, destSize) {
461         var len = arguments.length;
462         switch (len) {
463             case 2:
464                 var height = image.height;
465                 this._renderContext.drawImage(image, sourcePoint.x, -(sourcePoint.y + height));
466                 break;
467             case 3:
468                 this._renderContext.drawImage(image, sourcePoint.x, -(sourcePoint.y + sourceSize.height), sourceSize.width, sourceSize.height);
469                 break;
470             case 5:
471                 this._renderContext.drawImage(image, sourcePoint.x, sourcePoint.y, sourceSize.width, sourceSize.height, destPoint.x, -(destPoint.y + destSize.height),
472                     destSize.width, destSize.height);
473                 break;
474             default:
475                 throw new Error("Argument must be non-nil");
476                 break;
477         }
478     },
479 
480     /**
481      * draw a star
482      * @param {CanvasRenderingContext2D} ctx canvas context
483      * @param {Number} radius
484      * @param {cc.Color} color
485      */
486     drawStar:function (ctx, radius, color) {
487         var context = ctx || this._renderContext;
488         radius *= cc.view.getScaleX();
489         var colorStr = "rgba(" + (0 | color.r) + "," + (0 | color.g) + "," + (0 | color.b);
490         context.fillStyle = colorStr + ",1)";
491         var subRadius = radius / 10;
492 
493         context.beginPath();
494         context.moveTo(-radius, radius);
495         context.lineTo(0, subRadius);
496         context.lineTo(radius, radius);
497         context.lineTo(subRadius, 0);
498         context.lineTo(radius, -radius);
499         context.lineTo(0, -subRadius);
500         context.lineTo(-radius, -radius);
501         context.lineTo(-subRadius, 0);
502         context.lineTo(-radius, radius);
503         context.closePath();
504         context.fill();
505 
506         var g1 = context.createRadialGradient(0, 0, subRadius, 0, 0, radius);
507         g1.addColorStop(0, colorStr + ", 1)");
508         g1.addColorStop(0.3, colorStr + ", 0.8)");
509         g1.addColorStop(1.0, colorStr + ", 0.0)");
510         context.fillStyle = g1;
511         context.beginPath();
512         var startAngle_1 = 0;
513         var endAngle_1 = cc.PI2;
514         context.arc(0, 0, radius - subRadius, startAngle_1, endAngle_1, false);
515         context.closePath();
516         context.fill();
517     },
518 
519     /**
520      * draw a color ball
521      * @param {CanvasRenderingContext2D} ctx canvas context
522      * @param {Number} radius
523      * @param {cc.Color} color
524      */
525     drawColorBall:function (ctx, radius, color) {
526         var context = ctx || this._renderContext;
527         radius *= cc.view.getScaleX();
528         var colorStr = "rgba(" +(0|color.r) + "," + (0|color.g) + "," + (0|color.b);
529         var subRadius = radius / 10;
530 
531         var g1 = context.createRadialGradient(0, 0, subRadius, 0, 0, radius);
532         g1.addColorStop(0, colorStr + ", 1)");
533         g1.addColorStop(0.3, colorStr + ", 0.8)");
534         g1.addColorStop(0.6, colorStr + ", 0.4)");
535         g1.addColorStop(1.0, colorStr + ", 0.0)");
536         context.fillStyle = g1;
537         context.beginPath();
538         var startAngle_1 = 0;
539         var endAngle_1 = cc.PI2;
540         context.arc(0, 0, radius, startAngle_1, endAngle_1, false);
541         context.closePath();
542         context.fill();
543     },
544 
545     /**
546      * fill text
547      * @param {String} strText
548      * @param {Number} x
549      * @param {Number} y
550      */
551     fillText:function (strText, x, y) {
552         this._renderContext.fillText(strText, x, -y);
553     },
554 
555     /**
556      * set the drawing color with 4 unsigned bytes
557      * @param {Number} r red value (0 to 255)
558      * @param {Number} g green value (0 to 255)
559      * @param {Number} b blue value (0 to 255)
560      * @param {Number} a Alpha value (0 to 255)
561      */
562     setDrawColor:function (r, g, b, a) {
563         this._renderContext.fillStyle = "rgba(" + r + "," + g + "," + b + "," + a / 255 + ")";
564         this._renderContext.strokeStyle = "rgba(" + r + "," + g + "," + b + "," + a / 255 + ")";
565     },
566 
567     /**
568      * set the point size in points. Default 1.
569      * @param {Number} pointSize
570      */
571     setPointSize:function (pointSize) {
572     },
573 
574     /**
575      * set the line width. Default 1.
576      * @param {Number} width
577      */
578     setLineWidth:function (width) {
579         this._renderContext.lineWidth = width * cc.view.getScaleX();
580     }
581 });
582 
583 /**
584  * Canvas of DrawingPrimitive implement version
585  * @class
586  * @extends cc.DrawingPrimitive
587  */
588 cc.DrawingPrimitiveWebGL = cc.DrawingPrimitive.extend({
589     _initialized:false,
590     _shader: null,
591     _colorLocation:-1,
592     _colorArray: null,
593     _pointSizeLocation:-1,
594     _pointSize:-1,
595     ctor:function (ctx) {
596         if (ctx == null)
597             ctx = cc._renderContext;
598 
599         if (!ctx instanceof  WebGLRenderingContext)
600             throw "Can't initialise DrawingPrimitiveWebGL. context need is WebGLRenderingContext";
601 
602         cc.DrawingPrimitive.prototype.ctor.call(this, ctx);
603         this._colorArray = new Float32Array([1.0, 1.0, 1.0, 1.0]);
604     },
605 
606     lazy_init:function () {
607         if (!this._initialized) {
608             //
609             // Position and 1 color passed as a uniform (to similate glColor4ub )
610             //
611             this._shader = cc.shaderCache.programForKey(cc.SHADER_POSITION_UCOLOR);
612             this._colorLocation = this._renderContext.getUniformLocation(this._shader.getProgram(), "u_color");
613             this._pointSizeLocation = this._renderContext.getUniformLocation(this._shader.getProgram(), "u_pointSize");
614             //cc.CHECK_GL_ERROR_DEBUG();
615 
616             this._initialized = true;
617         }
618     },
619 
620     /**
621      * initlialize context
622      */
623     drawInit:function () {
624         this._initialized = false;
625     },
626 
627     /**
628      * draws a point given x and y coordinate measured in points
629      * @param {cc.Point} point
630      */
631     drawPoint:function (point) {
632         this.lazy_init();
633 
634         var glContext = this._renderContext;
635         this._shader.use();
636         this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
637         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
638         glContext.uniform4fv(this._colorLocation, this._colorArray);
639         this._shader.setUniformLocationWith1f(this._pointSizeLocation, this._pointSize);
640 
641         var pointBuffer = glContext.createBuffer();
642         glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
643         glContext.bufferData(glContext.ARRAY_BUFFER, new Float32Array([point.x, point.y]), glContext.STATIC_DRAW);
644         glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
645 
646         glContext.drawArrays(glContext.POINTS, 0, 1);
647         glContext.deleteBuffer(pointBuffer);
648 
649         cc.INCREMENT_GL_DRAWS(1);
650     },
651 
652     /**
653      * draws an array of points.
654      * @param {Array} points point of array
655      * @param {Number} numberOfPoints
656      */
657     drawPoints:function (points, numberOfPoints) {
658         if (!points || points.length == 0)
659             return;
660 
661         this.lazy_init();
662 
663         var glContext = this._renderContext;
664         this._shader.use();
665         this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
666         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
667         glContext.uniform4fv(this._colorLocation, this._colorArray);
668         this._shader.setUniformLocationWith1f(this._pointSizeLocation, this._pointSize);
669 
670         var pointBuffer = glContext.createBuffer();
671         glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
672         glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray(points), glContext.STATIC_DRAW);
673         glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
674 
675         glContext.drawArrays(glContext.POINTS, 0, points.length);
676         glContext.deleteBuffer(pointBuffer);
677 
678         cc.INCREMENT_GL_DRAWS(1);
679     },
680 
681     _pointsToTypeArray:function (points) {
682         var typeArr = new Float32Array(points.length * 2);
683         for (var i = 0; i < points.length; i++) {
684             typeArr[i * 2] = points[i].x;
685             typeArr[i * 2 + 1] = points[i].y;
686         }
687         return typeArr;
688     },
689 
690     /**
691      * draws a line given the origin and destination point measured in points
692      * @param {cc.Point} origin
693      * @param {cc.Point} destination
694      */
695     drawLine:function (origin, destination) {
696         this.lazy_init();
697 
698         var glContext = this._renderContext;
699         this._shader.use();
700         this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
701         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
702         glContext.uniform4fv(this._colorLocation, this._colorArray);
703 
704         var pointBuffer = glContext.createBuffer();
705         glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
706         glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray([origin, destination]), glContext.STATIC_DRAW);
707         glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
708 
709         glContext.drawArrays(glContext.LINES, 0, 2);
710         glContext.deleteBuffer(pointBuffer);
711 
712         cc.INCREMENT_GL_DRAWS(1);
713     },
714 
715     /**
716      * draws a rectangle given the origin and destination point measured in points.
717      * @param {cc.Point} origin
718      * @param {cc.Point} destination
719      */
720     drawRect:function (origin, destination) {
721         this.drawLine(cc.p(origin.x, origin.y), cc.p(destination.x, origin.y));
722         this.drawLine(cc.p(destination.x, origin.y), cc.p(destination.x, destination.y));
723         this.drawLine(cc.p(destination.x, destination.y), cc.p(origin.x, destination.y));
724         this.drawLine(cc.p(origin.x, destination.y), cc.p(origin.x, origin.y));
725     },
726 
727     /**
728      * draws a solid rectangle given the origin and destination point measured in points.
729      * @param {cc.Point} origin
730      * @param {cc.Point} destination
731      * @param {cc.Color} color
732      */
733     drawSolidRect:function (origin, destination, color) {
734         var vertices = [
735             origin,
736             cc.p(destination.x, origin.y),
737             destination,
738             cc.p(origin.x, destination.y)
739         ];
740 
741         this.drawSolidPoly(vertices, 4, color);
742     },
743 
744     /**
745      * draws a polygon given a pointer to cc.Point coordiantes and the number of vertices measured in points.
746      * @param {Array} vertices a pointer to cc.Point coordiantes
747      * @param {Number} numOfVertices the number of vertices measured in points
748      * @param {Boolean} closePolygon The polygon can be closed or open
749      */
750     drawPoly:function (vertices, numOfVertices, closePolygon) {
751         this.lazy_init();
752 
753         var glContext = this._renderContext;
754         this._shader.use();
755         this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
756         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
757         glContext.uniform4fv(this._colorLocation, this._colorArray);
758 
759         var pointBuffer = glContext.createBuffer();
760         glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
761         glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray(vertices), glContext.STATIC_DRAW);
762         glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
763 
764         if (closePolygon)
765             glContext.drawArrays(glContext.LINE_LOOP, 0, vertices.length);
766         else
767             glContext.drawArrays(glContext.LINE_STRIP, 0, vertices.length);
768         glContext.deleteBuffer(pointBuffer);
769 
770         cc.INCREMENT_GL_DRAWS(1);
771     },
772 
773     /**
774      * draws a solid polygon given a pointer to CGPoint coordiantes, the number of vertices measured in points, and a color.
775      * @param {Array} poli
776      * @param {Number} numberOfPoints
777      * @param {cc.Color} color
778      */
779     drawSolidPoly:function (poli, numberOfPoints, color) {
780         this.lazy_init();
781         if (color)
782             this.setDrawColor(color.r, color.g, color.b, color.a);
783 
784         var glContext = this._renderContext;
785         this._shader.use();
786         this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
787         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
788         glContext.uniform4fv(this._colorLocation, this._colorArray);
789 
790         var pointBuffer = glContext.createBuffer();
791         glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
792         glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray(poli), glContext.STATIC_DRAW);
793         glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
794         glContext.drawArrays(glContext.TRIANGLE_FAN, 0, poli.length);
795         glContext.deleteBuffer(pointBuffer);
796 
797         cc.INCREMENT_GL_DRAWS(1);
798     },
799 
800     /**
801      * draws a circle given the center, radius and number of segments.
802      * @param {cc.Point} center center of circle
803      * @param {Number} radius
804      * @param {Number} angle angle in radians
805      * @param {Number} segments
806      * @param {Boolean} drawLineToCenter
807      */
808     drawCircle:function (center, radius, angle, segments, drawLineToCenter) {
809         this.lazy_init();
810 
811         var additionalSegment = 1;
812         if (drawLineToCenter)
813             additionalSegment++;
814 
815         var coef = 2.0 * Math.PI / segments;
816 
817         var vertices = new Float32Array((segments + 2) * 2);
818         if (!vertices)
819             return;
820 
821         for (var i = 0; i <= segments; i++) {
822             var rads = i * coef;
823             var j = radius * Math.cos(rads + angle) + center.x;
824             var k = radius * Math.sin(rads + angle) + center.y;
825 
826             vertices[i * 2] = j;
827             vertices[i * 2 + 1] = k;
828         }
829         vertices[(segments + 1) * 2] = center.x;
830         vertices[(segments + 1) * 2 + 1] = center.y;
831 
832         var glContext = this._renderContext;
833         this._shader.use();
834         this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
835         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
836         glContext.uniform4fv(this._colorLocation, this._colorArray);
837 
838         var pointBuffer = glContext.createBuffer();
839         glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
840         glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW);
841         glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
842 
843         glContext.drawArrays(glContext.LINE_STRIP, 0, segments + additionalSegment);
844         glContext.deleteBuffer(pointBuffer);
845 
846         cc.INCREMENT_GL_DRAWS(1);
847     },
848 
849     /**
850      * draws a quad bezier path
851      * @param {cc.Point} origin
852      * @param {cc.Point} control
853      * @param {cc.Point} destination
854      * @param {Number} segments
855      */
856     drawQuadBezier:function (origin, control, destination, segments) {
857         this.lazy_init();
858 
859         var vertices = new Float32Array((segments + 1) * 2);
860 
861         var t = 0.0;
862         for (var i = 0; i < segments; i++) {
863             vertices[i * 2] = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x;
864             vertices[i * 2 + 1] = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y;
865             t += 1.0 / segments;
866         }
867         vertices[segments * 2] = destination.x;
868         vertices[segments * 2 + 1] = destination.y;
869 
870         var glContext = this._renderContext;
871         this._shader.use();
872         this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
873         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
874         glContext.uniform4fv(this._colorLocation, this._colorArray);
875 
876         var pointBuffer = glContext.createBuffer();
877         glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
878         glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW);
879         glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
880 
881         glContext.drawArrays(glContext.LINE_STRIP, 0, segments + 1);
882         glContext.deleteBuffer(pointBuffer);
883 
884         cc.INCREMENT_GL_DRAWS(1);
885     },
886 
887     /**
888      * draws a cubic bezier path
889      * @param {cc.Point} origin
890      * @param {cc.Point} control1
891      * @param {cc.Point} control2
892      * @param {cc.Point} destination
893      * @param {Number} segments
894      */
895     drawCubicBezier:function (origin, control1, control2, destination, segments) {
896         this.lazy_init();
897 
898         var vertices = new Float32Array((segments + 1) * 2);
899 
900         var t = 0;
901         for (var i = 0; i < segments; i++) {
902             vertices[i * 2] = Math.pow(1 - t, 3) * origin.x + 3.0 * Math.pow(1 - t, 2) * t * control1.x + 3.0 * (1 - t) * t * t * control2.x + t * t * t * destination.x;
903             vertices[i * 2 + 1] = Math.pow(1 - t, 3) * origin.y + 3.0 * Math.pow(1 - t, 2) * t * control1.y + 3.0 * (1 - t) * t * t * control2.y + t * t * t * destination.y;
904             t += 1.0 / segments;
905         }
906         vertices[segments * 2] = destination.x;
907         vertices[segments * 2 + 1] = destination.y;
908 
909         var glContext = this._renderContext;
910         this._shader.use();
911         this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
912         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
913         glContext.uniform4fv(this._colorLocation, this._colorArray);
914 
915         var pointBuffer = glContext.createBuffer();
916         glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
917         glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW);
918         glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
919         glContext.drawArrays(glContext.LINE_STRIP, 0, segments + 1);
920         glContext.deleteBuffer(pointBuffer);
921 
922         cc.INCREMENT_GL_DRAWS(1);
923     },
924 
925     /**
926      * draw a catmull rom line
927      * @param {Array} points
928      * @param {Number} segments
929      */
930     drawCatmullRom:function (points, segments) {
931         this.drawCardinalSpline(points, 0.5, segments);
932     },
933 
934     /**
935      * draw a cardinal spline path
936      * @param {Array} config
937      * @param {Number} tension
938      * @param {Number} segments
939      */
940     drawCardinalSpline:function (config, tension, segments) {
941         this.lazy_init();
942 
943         var vertices = new Float32Array((segments + 1) * 2);
944         var p, lt, deltaT = 1.0 / config.length;
945         for (var i = 0; i < segments + 1; i++) {
946             var dt = i / segments;
947 
948             // border
949             if (dt == 1) {
950                 p = config.length - 1;
951                 lt = 1;
952             } else {
953                 p = 0 | (dt / deltaT);
954                 lt = (dt - deltaT * p) / deltaT;
955             }
956 
957             var newPos = cc.CardinalSplineAt(
958                 cc.getControlPointAt(config, p - 1),
959                 cc.getControlPointAt(config, p),
960                 cc.getControlPointAt(config, p + 1),
961                 cc.getControlPointAt(config, p + 2),
962                 tension, lt);
963             // Interpolate
964 
965             vertices[i * 2] = newPos.x;
966             vertices[i * 2 + 1] = newPos.y;
967         }
968 
969         var glContext = this._renderContext;
970         this._shader.use();
971         this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
972         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
973         glContext.uniform4fv(this._colorLocation, this._colorArray);
974 
975         var pointBuffer = glContext.createBuffer();
976         glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
977         glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW);
978         glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
979         glContext.drawArrays(glContext.LINE_STRIP, 0, segments + 1);
980         glContext.deleteBuffer(pointBuffer);
981 
982         cc.INCREMENT_GL_DRAWS(1);
983     },
984 
985     /**
986      * set the drawing color with 4 unsigned bytes
987      * @param {Number} r red value (0 to 255)
988      * @param {Number} g green value (0 to 255)
989      * @param {Number} b blue value (0 to 255)
990      * @param {Number} a Alpha value (0 to 255)
991      */
992     setDrawColor:function (r, g, b, a) {
993         this._colorArray[0] = r / 255.0;
994         this._colorArray[1] = g / 255.0;
995         this._colorArray[2] = b / 255.0;
996         this._colorArray[3] = a / 255.0;
997     },
998 
999     /**
1000      * set the point size in points. Default 1.
1001      * @param {Number} pointSize
1002      */
1003     setPointSize:function (pointSize) {
1004         this._pointSize = pointSize * cc.CONTENT_SCALE_FACTOR();
1005     },
1006 
1007     /**
1008      * set the line width. Default 1.
1009      * @param {Number} width
1010      */
1011     setLineWidth:function (width) {
1012         if(this._renderContext.lineWidth)
1013             this._renderContext.lineWidth(width);
1014     }
1015 });
1016 
1017 cc.PI2 = Math.PI * 2;
1018