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.Color4F} 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.Color4F} 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     /**
200      * draws a point given x and y coordinate measured in points
201      * @override
202      * @param {cc.Point} point
203      * @param {Number} size
204      */
205     drawPoint:function (point, size) {
206         if (!size) {
207             size = 1;
208         }
209         var locScaleX = cc.EGLView.getInstance().getScaleX(), locScaleY = cc.EGLView.getInstance().getScaleY();
210         var newPoint = cc.p(point.x  * locScaleX, point.y * locScaleY);
211         this._renderContext.beginPath();
212         this._renderContext.arc(newPoint.x, -newPoint.y, size * locScaleX, 0, Math.PI * 2, false);
213         this._renderContext.closePath();
214         this._renderContext.fill();
215     },
216 
217     /**
218      * draws an array of points.
219      * @override
220      * @param {Array} points point of array
221      * @param {Number} numberOfPoints
222      * @param {Number} size
223      */
224     drawPoints:function (points, numberOfPoints, size) {
225         if (points == null) {
226             return;
227         }
228         if (!size) {
229             size = 1;
230         }
231         var locContext = this._renderContext,locScaleX = cc.EGLView.getInstance().getScaleX(), locScaleY = cc.EGLView.getInstance().getScaleY();
232 
233         locContext.beginPath();
234         for (var i = 0, len = points.length; i < len; i++)
235             locContext.arc(points[i].x * locScaleX, -points[i].y * locScaleY, size * locScaleX, 0, Math.PI * 2, false);
236         locContext.closePath();
237         locContext.fill();
238     },
239 
240     /**
241      * draws a line given the origin and destination point measured in points
242      * @override
243      * @param {cc.Point} origin
244      * @param {cc.Point} destination
245      */
246     drawLine:function (origin, destination) {
247         var locContext = this._renderContext, locScaleX = cc.EGLView.getInstance().getScaleX(), locScaleY = cc.EGLView.getInstance().getScaleY();
248         locContext.beginPath();
249         locContext.moveTo(origin.x * locScaleX, -origin.y * locScaleY);
250         locContext.lineTo(destination.x * locScaleX, -destination.y * locScaleY);
251         locContext.closePath();
252         locContext.stroke();
253     },
254 
255     /**
256      * draws a rectangle given the origin and destination point measured in points.
257      * @param {cc.Point} origin
258      * @param {cc.Point} destination
259      */
260     drawRect:function (origin, destination) {
261         this.drawLine(cc.p(origin.x, origin.y), cc.p(destination.x, origin.y));
262         this.drawLine(cc.p(destination.x, origin.y), cc.p(destination.x, destination.y));
263         this.drawLine(cc.p(destination.x, destination.y), cc.p(origin.x, destination.y));
264         this.drawLine(cc.p(origin.x, destination.y), cc.p(origin.x, origin.y));
265     },
266 
267     /**
268      * draws a solid rectangle given the origin and destination point measured in points.
269      * @param {cc.Point} origin
270      * @param {cc.Point} destination
271      * @param {cc.Color4F} color
272      */
273     drawSolidRect:function (origin, destination, color) {
274         var vertices = [
275             origin,
276             cc.p(destination.x, origin.y),
277             destination,
278             cc.p(origin.x, destination.y)
279         ];
280 
281         this.drawSolidPoly(vertices, 4, color);
282     },
283 
284     /**
285      * draws a polygon given a pointer to cc.Point coordiantes and the number of vertices measured in points.
286      * @override
287      * @param {Array} vertices a pointer to cc.Point coordiantes
288      * @param {Number} numOfVertices the number of vertices measured in points
289      * @param {Boolean} closePolygon The polygon can be closed or open
290      * @param {Boolean} [fill=] The polygon can be closed or open and optionally filled with current color
291      */
292     drawPoly:function (vertices, numOfVertices, closePolygon, fill) {
293         fill = fill || false;
294 
295         if (vertices == null)
296             return;
297 
298         if (vertices.length < 3)
299             throw new Error("Polygon's point must greater than 2");
300 
301         var firstPoint = vertices[0], locContext = this._renderContext;
302         var locScaleX = cc.EGLView.getInstance().getScaleX(), locScaleY = cc.EGLView.getInstance().getScaleY();
303         locContext.beginPath();
304         locContext.moveTo(firstPoint.x * locScaleX, -firstPoint.y * locScaleY);
305         for (var i = 1, len = vertices.length; i < len; i++)
306             locContext.lineTo(vertices[i].x * locScaleX, -vertices[i].y * locScaleY);
307 
308         if (closePolygon)
309             locContext.closePath();
310 
311         if (fill)
312             locContext.fill();
313         else
314             locContext.stroke();
315     },
316 
317     /**
318      * draws a solid polygon given a pointer to CGPoint coordiantes, the number of vertices measured in points, and a color.
319      * @param {Array} poli
320      * @param {Number} numberOfPoints
321      * @param {cc.Color4F} color
322      */
323     drawSolidPoly:function (poli, numberOfPoints, color) {
324         this.setDrawColor4F(color.r, color.g, color.b, color.a);
325         this.drawPoly(poli, numberOfPoints, true, true);
326     },
327 
328     /**
329      * draws a circle given the center, radius and number of segments.
330      * @override
331      * @param {cc.Point} center center of circle
332      * @param {Number} radius
333      * @param {Number} angle angle in radians
334      * @param {Number} segments
335      * @param {Boolean} [drawLineToCenter=]
336      */
337     drawCircle: function (center, radius, angle, segments, drawLineToCenter) {
338         drawLineToCenter = drawLineToCenter || false;
339         var locContext = this._renderContext;
340         var locScaleX = cc.EGLView.getInstance().getScaleX(), locScaleY = cc.EGLView.getInstance().getScaleY();
341         locContext.beginPath();
342         var endAngle = angle - Math.PI * 2;
343         locContext.arc(0 | (center.x * locScaleX), 0 | -(center.y * locScaleY), radius * locScaleX, -angle, -endAngle, false);
344         if (drawLineToCenter) {
345             locContext.lineTo(0 | (center.x * locScaleX), 0 | -(center.y * locScaleY));
346         }
347         locContext.stroke();
348     },
349 
350     /**
351      * draws a quad bezier path
352      * @override
353      * @param {cc.Point} origin
354      * @param {cc.Point} control
355      * @param {cc.Point} destination
356      * @param {Number} segments
357      */
358     drawQuadBezier:function (origin, control, destination, segments) {
359         //this is OpenGL Algorithm
360         var vertices = [];
361 
362         var t = 0.0;
363         for (var i = 0; i < segments; i++) {
364             var x = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x;
365             var y = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y;
366             vertices.push(cc.p(x, y));
367             t += 1.0 / segments;
368         }
369         vertices.push(cc.p(destination.x, destination.y));
370 
371         this.drawPoly(vertices, segments + 1, false, false);
372     },
373 
374     /**
375      * draws a cubic bezier path
376      * @override
377      * @param {cc.Point} origin
378      * @param {cc.Point} control1
379      * @param {cc.Point} control2
380      * @param {cc.Point} destination
381      * @param {Number} segments
382      */
383     drawCubicBezier:function (origin, control1, control2, destination, segments) {
384         //this is OpenGL Algorithm
385         var vertices = [];
386 
387         var t = 0;
388         for (var i = 0; i < segments; i++) {
389             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;
390             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;
391             vertices.push(cc.p(x , y ));
392             t += 1.0 / segments;
393         }
394         vertices.push(cc.p(destination.x , destination.y));
395 
396         this.drawPoly(vertices, segments + 1, false, false);
397     },
398 
399     /**
400      * draw a CatmullRom curve
401      * @override
402      * @param {Array} points
403      * @param {Number} segments
404      */
405     drawCatmullRom:function (points, segments) {
406         this.drawCardinalSpline(points, 0.5, segments);
407     },
408 
409     /**
410      * draw a cardinal spline path
411      * @override
412      * @param {Array} config
413      * @param {Number} tension
414      * @param {Number} segments
415      */
416     drawCardinalSpline:function (config, tension, segments) {
417         //lazy_init();
418         cc.renderContext.strokeStyle = "rgba(255,255,255,1)";
419         var points = [];
420         var p, lt;
421         var deltaT = 1.0 / config.length;
422 
423         for (var i = 0; i < segments + 1; i++) {
424             var dt = i / segments;
425 
426             // border
427             if (dt == 1) {
428                 p = config.length - 1;
429                 lt = 1;
430             } else {
431                 p = 0 | (dt / deltaT);
432                 lt = (dt - deltaT * p) / deltaT;
433             }
434 
435             // Interpolate
436             var newPos = cc.CardinalSplineAt(
437                 cc.getControlPointAt(config, p - 1),
438                 cc.getControlPointAt(config, p - 0),
439                 cc.getControlPointAt(config, p + 1),
440                 cc.getControlPointAt(config, p + 2),
441                 tension, lt);
442             points.push(newPos);
443         }
444         this.drawPoly(points, segments + 1, false, false);
445     },
446 
447     /**
448      * draw an image
449      * @override
450      * @param {HTMLImageElement|HTMLCanvasElement} image
451      * @param {cc.Point} sourcePoint
452      * @param {cc.Size} sourceSize
453      * @param {cc.Point} destPoint
454      * @param {cc.Size} destSize
455      */
456     drawImage:function (image, sourcePoint, sourceSize, destPoint, destSize) {
457         var len = arguments.length;
458         switch (len) {
459             case 2:
460                 var height = image.height;
461                 this._renderContext.drawImage(image, sourcePoint.x, -(sourcePoint.y + height));
462                 break;
463             case 3:
464                 this._renderContext.drawImage(image, sourcePoint.x, -(sourcePoint.y + sourceSize.height), sourceSize.width, sourceSize.height);
465                 break;
466             case 5:
467                 this._renderContext.drawImage(image, sourcePoint.x, sourcePoint.y, sourceSize.width, sourceSize.height, destPoint.x, -(destPoint.y + destSize.height),
468                     destSize.width, destSize.height);
469                 break;
470             default:
471                 throw new Error("Argument must be non-nil");
472                 break;
473         }
474     },
475 
476     /**
477      * draw a star
478      * @param {CanvasRenderingContext2D} ctx canvas context
479      * @param {Number} radius
480      * @param {cc.Color3B|cc.Color4B|cc.Color4F} color
481      */
482     drawStar:function (ctx, radius, color) {
483         var context = ctx || this._renderContext;
484         radius *= cc.EGLView.getInstance().getScaleX();
485         if (color instanceof cc.Color4F)
486             color = new cc.Color3B(0 | (color.r * 255), 0 | (color.g * 255), 0 | (color.b * 255));
487         var colorStr = "rgba(" + color.r + "," + color.g + "," + color.b;
488         context.fillStyle = colorStr + ",1)";
489         var subRadius = radius / 10;
490 
491         context.beginPath();
492         context.moveTo(-radius, radius);
493         context.lineTo(0, subRadius);
494         context.lineTo(radius, radius);
495         context.lineTo(subRadius, 0);
496         context.lineTo(radius, -radius);
497         context.lineTo(0, -subRadius);
498         context.lineTo(-radius, -radius);
499         context.lineTo(-subRadius, 0);
500         context.lineTo(-radius, radius);
501         context.closePath();
502         context.fill();
503 
504         var g1 = context.createRadialGradient(0, 0, subRadius, 0, 0, radius);
505         g1.addColorStop(0, colorStr + ", 1)");
506         g1.addColorStop(0.3, colorStr + ", 0.8)");
507         g1.addColorStop(1.0, colorStr + ", 0.0)");
508         context.fillStyle = g1;
509         context.beginPath();
510         var startAngle_1 = 0;
511         var endAngle_1 = cc.PI2;
512         context.arc(0, 0, radius - subRadius, startAngle_1, endAngle_1, false);
513         context.closePath();
514         context.fill();
515     },
516 
517     /**
518      * draw a color ball
519      * @param {CanvasRenderingContext2D} ctx canvas context
520      * @param {Number} radius
521      * @param {cc.Color3B|cc.Color4B|cc.Color4F} color
522      */
523     drawColorBall:function (ctx, radius, color) {
524         var context = ctx || this._renderContext;
525         radius *= cc.EGLView.getInstance().getScaleX();
526         if (color instanceof cc.Color4F)
527             color = new cc.Color3B(0 | (color.r * 255), 0 | (color.g * 255), 0 | (color.b * 255));
528         var colorStr = "rgba(" + color.r + "," + color.g + "," + 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     setDrawColor4B: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 drawing color with 4 floats
569      * @param {Number} r red value (0 to 1)
570      * @param {Number} g green value (0 to 1)
571      * @param {Number} b blue value (0 to 1)
572      * @param {Number} a Alpha value (0 to 1)
573      */
574     setDrawColor4F:function (r, g, b, a) {
575         this._renderContext.fillStyle = "rgba(" + (0 | (r * 255)) + "," + (0 | (g * 255)) + "," + (0 | (b * 255)) + "," + a + ")";
576         this._renderContext.strokeStyle = "rgba(" + (0 | (r * 255)) + "," + (0 | (g * 255)) + "," + (0 | (b * 255)) + "," + a + ")";
577     },
578 
579     /**
580      * set the point size in points. Default 1.
581      * @param {Number} pointSize
582      */
583     setPointSize:function (pointSize) {
584     },
585 
586     /**
587      * set the line width. Default 1.
588      * @param {Number} width
589      */
590     setLineWidth:function (width) {
591         this._renderContext.lineWidth = width * cc.EGLView.getInstance().getScaleX();
592     }
593 });
594 
595 /**
596  * Canvas of DrawingPrimitive implement version
597  * @class
598  * @extends cc.DrawingPrimitive
599  */
600 cc.DrawingPrimitiveWebGL = cc.DrawingPrimitive.extend({
601     _initialized:false,
602     _shader: null,
603     _colorLocation:-1,
604     _color: null,
605     _pointSizeLocation:-1,
606     _pointSize:-1,
607 
608     ctor:function (ctx) {
609         if (ctx == null)
610             ctx = cc.renderContext;
611 
612         if (!ctx instanceof  WebGLRenderingContext)
613             throw "Can't initialise DrawingPrimitiveWebGL. context need is WebGLRenderingContext";
614 
615         cc.DrawingPrimitive.prototype.ctor.call(this, ctx);
616         this._color = new cc.Color4F(1.0, 1.0, 1.0, 1.0);
617     },
618 
619     lazy_init:function () {
620         if (!this._initialized) {
621             //
622             // Position and 1 color passed as a uniform (to similate glColor4ub )
623             //
624             this._shader = cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_UCOLOR);
625             this._colorLocation = this._renderContext.getUniformLocation(this._shader.getProgram(), "u_color");
626             this._pointSizeLocation = this._renderContext.getUniformLocation(this._shader.getProgram(), "u_pointSize");
627             //cc.CHECK_GL_ERROR_DEBUG();
628 
629             this._initialized = true;
630         }
631     },
632 
633     /**
634      * initlialize context
635      */
636     drawInit:function () {
637         this._initialized = false;
638     },
639 
640     /**
641      * draws a point given x and y coordinate measured in points
642      * @param {cc.Point} point
643      */
644     drawPoint:function (point) {
645         this.lazy_init();
646 
647         this._shader.use();
648         this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
649         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
650         this._shader.setUniformLocationWith4fv(this._colorLocation, new Float32Array(this._color._arrayBuffer,0,4), 1);
651         this._shader.setUniformLocationWith1f(this._pointSizeLocation, this._pointSize);
652 
653         var glContext = this._renderContext;
654         var pointBuffer = glContext.createBuffer();
655         glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
656         glContext.bufferData(glContext.ARRAY_BUFFER, new Float32Array([point.x, point.y]), glContext.STATIC_DRAW);
657         glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
658 
659         glContext.drawArrays(glContext.POINTS, 0, 1);
660         glContext.deleteBuffer(pointBuffer);
661 
662         cc.INCREMENT_GL_DRAWS(1);
663     },
664 
665     /**
666      * draws an array of points.
667      * @param {Array} points point of array
668      * @param {Number} numberOfPoints
669      */
670     drawPoints:function (points, numberOfPoints) {
671         if (!points || points.length == 0)
672             return;
673 
674         this.lazy_init();
675 
676         this._shader.use();
677         this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
678         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
679         this._shader.setUniformLocationWith4fv(this._colorLocation, new Float32Array(this._color._arrayBuffer,0,4), 1);
680         this._shader.setUniformLocationWith1f(this._pointSizeLocation, this._pointSize);
681 
682         var glContext = this._renderContext;
683         var pointBuffer = glContext.createBuffer();
684         glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
685         glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray(points), glContext.STATIC_DRAW);
686         glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
687 
688         glContext.drawArrays(glContext.POINTS, 0, points.length);
689         glContext.deleteBuffer(pointBuffer);
690 
691         cc.INCREMENT_GL_DRAWS(1);
692     },
693 
694     _pointsToTypeArray:function (points) {
695         var typeArr = new Float32Array(points.length * 2);
696         for (var i = 0; i < points.length; i++) {
697             typeArr[i * 2] = points[i].x;
698             typeArr[i * 2 + 1] = points[i].y;
699         }
700         return typeArr;
701     },
702 
703     /**
704      * draws a line given the origin and destination point measured in points
705      * @param {cc.Point} origin
706      * @param {cc.Point} destination
707      */
708     drawLine:function (origin, destination) {
709         this.lazy_init();
710 
711         this._shader.use();
712         this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
713         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
714         this._shader.setUniformLocationWith4fv(this._colorLocation, new Float32Array(this._color._arrayBuffer,0,4), 1);
715 
716         var glContext = this._renderContext;
717         var pointBuffer = glContext.createBuffer();
718         glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
719         glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray([origin, destination]), glContext.STATIC_DRAW);
720         glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
721 
722         glContext.drawArrays(glContext.LINES, 0, 2);
723         glContext.deleteBuffer(pointBuffer);
724 
725         cc.INCREMENT_GL_DRAWS(1);
726     },
727 
728     /**
729      * draws a rectangle given the origin and destination point measured in points.
730      * @param {cc.Point} origin
731      * @param {cc.Point} destination
732      */
733     drawRect:function (origin, destination) {
734         this.drawLine(cc.p(origin.x, origin.y), cc.p(destination.x, origin.y));
735         this.drawLine(cc.p(destination.x, origin.y), cc.p(destination.x, destination.y));
736         this.drawLine(cc.p(destination.x, destination.y), cc.p(origin.x, destination.y));
737         this.drawLine(cc.p(origin.x, destination.y), cc.p(origin.x, origin.y));
738     },
739 
740     /**
741      * draws a solid rectangle given the origin and destination point measured in points.
742      * @param {cc.Point} origin
743      * @param {cc.Point} destination
744      * @param {cc.Color4F} color
745      */
746     drawSolidRect:function (origin, destination, color) {
747         var vertices = [
748             origin,
749             cc.p(destination.x, origin.y),
750             destination,
751             cc.p(origin.x, destination.y)
752         ];
753 
754         this.drawSolidPoly(vertices, 4, color);
755     },
756 
757     /**
758      * draws a polygon given a pointer to cc.Point coordiantes and the number of vertices measured in points.
759      * @param {Array} vertices a pointer to cc.Point coordiantes
760      * @param {Number} numOfVertices the number of vertices measured in points
761      * @param {Boolean} closePolygon The polygon can be closed or open
762      */
763     drawPoly:function (vertices, numOfVertices, closePolygon) {
764         this.lazy_init();
765 
766         this._shader.use();
767         this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
768         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
769         this._shader.setUniformLocationWith4fv(this._colorLocation, new Float32Array(this._color._arrayBuffer,0,4), 1);
770 
771         var glContext = this._renderContext;
772         var pointBuffer = glContext.createBuffer();
773         glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
774         glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray(vertices), glContext.STATIC_DRAW);
775         glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
776 
777         if (closePolygon)
778             glContext.drawArrays(glContext.LINE_LOOP, 0, vertices.length);
779         else
780             glContext.drawArrays(glContext.LINE_STRIP, 0, vertices.length);
781         glContext.deleteBuffer(pointBuffer);
782 
783         cc.INCREMENT_GL_DRAWS(1);
784     },
785 
786     /**
787      * draws a solid polygon given a pointer to CGPoint coordiantes, the number of vertices measured in points, and a color.
788      * @param {Array} poli
789      * @param {Number} numberOfPoints
790      * @param {cc.Color4F} color
791      */
792     drawSolidPoly:function (poli, numberOfPoints, color) {
793         this.lazy_init();
794         if (!color)
795             color = this._color;
796 
797         this._shader.use();
798         this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
799         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
800         this._shader.setUniformLocationWith4fv(this._colorLocation, new Float32Array(color._arrayBuffer,0,4), 1);
801 
802         var glContext = this._renderContext;
803         var pointBuffer = glContext.createBuffer();
804         glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
805         glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray(poli), glContext.STATIC_DRAW);
806         glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
807         glContext.drawArrays(glContext.TRIANGLE_FAN, 0, poli.length);
808         glContext.deleteBuffer(pointBuffer);
809 
810         cc.INCREMENT_GL_DRAWS(1);
811     },
812 
813     /**
814      * draws a circle given the center, radius and number of segments.
815      * @param {cc.Point} center center of circle
816      * @param {Number} radius
817      * @param {Number} angle angle in radians
818      * @param {Number} segments
819      * @param {Boolean} drawLineToCenter
820      */
821     drawCircle:function (center, radius, angle, segments, drawLineToCenter) {
822         this.lazy_init();
823 
824         var additionalSegment = 1;
825         if (drawLineToCenter)
826             additionalSegment++;
827 
828         var coef = 2.0 * Math.PI / segments;
829 
830         var vertices = new Float32Array((segments + 2) * 2);
831         if (!vertices)
832             return;
833 
834         for (var i = 0; i <= segments; i++) {
835             var rads = i * coef;
836             var j = radius * Math.cos(rads + angle) + center.x;
837             var k = radius * Math.sin(rads + angle) + center.y;
838 
839             vertices[i * 2] = j;
840             vertices[i * 2 + 1] = k;
841         }
842         vertices[(segments + 1) * 2] = center.x;
843         vertices[(segments + 1) * 2 + 1] = center.y;
844 
845         this._shader.use();
846         this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
847         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
848         this._shader.setUniformLocationWith4fv(this._colorLocation, new Float32Array(this._color._arrayBuffer,0,4), 1);
849 
850         var glContext = this._renderContext;
851         var pointBuffer = glContext.createBuffer();
852         glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
853         glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW);
854         glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
855 
856         glContext.drawArrays(glContext.LINE_STRIP, 0, segments + additionalSegment);
857         glContext.deleteBuffer(pointBuffer);
858 
859         cc.INCREMENT_GL_DRAWS(1);
860     },
861 
862     /**
863      * draws a quad bezier path
864      * @param {cc.Point} origin
865      * @param {cc.Point} control
866      * @param {cc.Point} destination
867      * @param {Number} segments
868      */
869     drawQuadBezier:function (origin, control, destination, segments) {
870         this.lazy_init();
871 
872         var vertices = new Float32Array((segments + 1) * 2);
873 
874         var t = 0.0;
875         for (var i = 0; i < segments; i++) {
876             vertices[i * 2] = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x;
877             vertices[i * 2 + 1] = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y;
878             t += 1.0 / segments;
879         }
880         vertices[segments * 2] = destination.x;
881         vertices[segments * 2 + 1] = destination.y;
882 
883         this._shader.use();
884         this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
885         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
886         this._shader.setUniformLocationWith4fv(this._colorLocation, new Float32Array(this._color._arrayBuffer,0,4), 1);
887 
888         var glContext = this._renderContext;
889         var pointBuffer = glContext.createBuffer();
890         glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
891         glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW);
892         glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
893 
894         glContext.drawArrays(glContext.LINE_STRIP, 0, segments + 1);
895         glContext.deleteBuffer(pointBuffer);
896 
897         cc.INCREMENT_GL_DRAWS(1);
898     },
899 
900     /**
901      * draws a cubic bezier path
902      * @param {cc.Point} origin
903      * @param {cc.Point} control1
904      * @param {cc.Point} control2
905      * @param {cc.Point} destination
906      * @param {Number} segments
907      */
908     drawCubicBezier:function (origin, control1, control2, destination, segments) {
909         this.lazy_init();
910 
911         var vertices = new Float32Array((segments + 1) * 2);
912 
913         var t = 0;
914         for (var i = 0; i < segments; i++) {
915             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;
916             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;
917             t += 1.0 / segments;
918         }
919         vertices[segments * 2] = destination.x;
920         vertices[segments * 2 + 1] = destination.y;
921 
922         this._shader.use();
923         this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
924         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
925         this._shader.setUniformLocationWith4fv(this._colorLocation, new Float32Array(this._color._arrayBuffer,0,4), 1);
926 
927         var glContext = this._renderContext;
928         var pointBuffer = glContext.createBuffer();
929         glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
930         glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW);
931         glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
932         glContext.drawArrays(glContext.LINE_STRIP, 0, segments + 1);
933         glContext.deleteBuffer(pointBuffer);
934 
935         cc.INCREMENT_GL_DRAWS(1);
936     },
937 
938     /**
939      * draw a catmull rom line
940      * @param {Array} points
941      * @param {Number} segments
942      */
943     drawCatmullRom:function (points, segments) {
944         this.drawCardinalSpline(points, 0.5, segments);
945     },
946 
947     /**
948      * draw a cardinal spline path
949      * @param {Array} config
950      * @param {Number} tension
951      * @param {Number} segments
952      */
953     drawCardinalSpline:function (config, tension, segments) {
954         this.lazy_init();
955 
956         var vertices = new Float32Array((segments + 1) * 2);
957         var p, lt, deltaT = 1.0 / config.length;
958         for (var i = 0; i < segments + 1; i++) {
959             var dt = i / segments;
960 
961             // border
962             if (dt == 1) {
963                 p = config.length - 1;
964                 lt = 1;
965             } else {
966                 p = 0 | (dt / deltaT);
967                 lt = (dt - deltaT * p) / deltaT;
968             }
969 
970             var newPos = cc.CardinalSplineAt(
971                 cc.getControlPointAt(config, p - 1),
972                 cc.getControlPointAt(config, p),
973                 cc.getControlPointAt(config, p + 1),
974                 cc.getControlPointAt(config, p + 2),
975                 tension, lt);
976             // Interpolate
977 
978             vertices[i * 2] = newPos.x;
979             vertices[i * 2 + 1] = newPos.y;
980         }
981 
982         this._shader.use();
983         this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
984         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
985         this._shader.setUniformLocationWith4fv(this._colorLocation, new Float32Array(this._color._arrayBuffer,0,4), 1);
986 
987         var glContext = this._renderContext;
988         var pointBuffer = glContext.createBuffer();
989         glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
990         glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW);
991         glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
992         glContext.drawArrays(glContext.LINE_STRIP, 0, segments + 1);
993         glContext.deleteBuffer(pointBuffer);
994 
995         cc.INCREMENT_GL_DRAWS(1);
996     },
997 
998     /**
999      * set the drawing color with 4 unsigned bytes
1000      * @param {Number} r red value (0 to 255)
1001      * @param {Number} g green value (0 to 255)
1002      * @param {Number} b blue value (0 to 255)
1003      * @param {Number} a Alpha value (0 to 255)
1004      */
1005     setDrawColor4B:function (r, g, b, a) {
1006         this._color.r = r / 255.0;
1007         this._color.g = g / 255.0;
1008         this._color.b = b / 255.0;
1009         this._color.a = a / 255.0;
1010     },
1011 
1012     /**
1013      * set the drawing color with 4 floats
1014      * @param {Number} r red value (0 to 1)
1015      * @param {Number} g green value (0 to 1)
1016      * @param {Number} b blue value (0 to 1)
1017      * @param {Number} a Alpha value (0 to 1)
1018      */
1019     setDrawColor4F:function (r, g, b, a) {
1020         this._color.r = r;
1021         this._color.g = g;
1022         this._color.b = b;
1023         this._color.a = a;
1024     },
1025 
1026     /**
1027      * set the point size in points. Default 1.
1028      * @param {Number} pointSize
1029      */
1030     setPointSize:function (pointSize) {
1031         this._pointSize = pointSize * cc.CONTENT_SCALE_FACTOR();
1032     },
1033 
1034     /**
1035      * set the line width. Default 1.
1036      * @param {Number} width
1037      */
1038     setLineWidth:function (width) {
1039         if(this._renderContext.lineWidth)
1040             this._renderContext.lineWidth(width);
1041     }
1042 });
1043 
1044 cc.PI2 = Math.PI * 2;
1045