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  * cc.LabelTTF is a subclass of cc.TextureNode that knows how to render text labels<br/>
 29  * All features from cc.TextureNode are valid in cc.LabelTTF<br/>
 30  * cc.LabelTTF objects are slow for js-binding on mobile devices.Consider using cc.LabelAtlas or cc.LabelBMFont instead. <br/>
 31  * Consider using cc.LabelAtlas or cc.LabelBMFont instead.<br/>
 32  * @class
 33  * @extends cc.Sprite
 34  *
 35  * @property {String}       string          - Content string of label
 36  * @property {Number}       textAlign       - Horizontal Alignment of label: cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT
 37  * @property {Number}       verticalAlign   - Vertical Alignment of label: cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM
 38  * @property {Number}       fontSize        - Font size of label
 39  * @property {String}       fontName        - Font name of label
 40  * @property {String}       font            - The label font with a style string: e.g. "18px Verdana"
 41  * @property {Number}       boundingWidth   - Width of the bounding box of label, the real content width is limited by boundingWidth
 42  * @property {Number}       boundingHeight  - Height of the bounding box of label, the real content height is limited by boundingHeight
 43  * @property {cc.Color}     fillStyle       - The fill color
 44  * @property {cc.Color}     strokeStyle     - The stroke color
 45  * @property {Number}       lineWidth       - The line width for stroke
 46  * @property {Number}       shadowOffsetX   - The x axis offset of shadow
 47  * @property {Number}       shadowOffsetY   - The y axis offset of shadow
 48  * @property {Number}       shadowOpacity   - The opacity of shadow
 49  * @property {Number}       shadowBlur      - The blur size of shadow
 50  *
 51  */
 52 cc.LabelTTF = cc.Sprite.extend(/** @lends cc.LabelTTF# */{
 53     _dimensions:null,
 54     _hAlignment:cc.TEXT_ALIGNMENT_CENTER,
 55     _vAlignment:cc.VERTICAL_TEXT_ALIGNMENT_TOP,
 56     _fontName: null,
 57     _fontSize:0.0,
 58     _string:"",
 59     _originalText: null,
 60     _isMultiLine:false,
 61     _fontStyleStr:null,
 62 
 63     // font shadow
 64     _shadowEnabled:false,
 65     _shadowOffset:null,
 66     _shadowOpacity:0,
 67     _shadowBlur:0,
 68     _shadowColorStr:null,
 69 
 70     // font stroke
 71     _strokeEnabled:false,
 72     _strokeColor:null,
 73     _strokeSize:0,
 74     _strokeColorStr:null,
 75 
 76     // font tint
 77     _textFillColor:null,
 78     _fillColorStr:null,
 79 
 80     _strokeShadowOffsetX:0,
 81     _strokeShadowOffsetY:0,
 82     _needUpdateTexture:false,
 83 
 84     _labelCanvas:null,
 85     _labelContext:null,
 86     _lineWidths:null,
 87     _className:"LabelTTF",
 88 
 89 
 90     /**
 91      * Constructor
 92      */
 93     ctor:function () {
 94         cc.Sprite.prototype.ctor.call(this);
 95 
 96         this._dimensions = cc.size(0, 0);
 97         this._hAlignment = cc.TEXT_ALIGNMENT_LEFT;
 98         this._vAlignment = cc.VERTICAL_TEXT_ALIGNMENT_TOP;
 99         this._opacityModifyRGB = false;
100         this._fontStyleStr = "";
101         this._fontName = "Arial";
102         this._isMultiLine = false;
103 
104         this._shadowEnabled = false;
105         this._shadowOffset = cc.p(0,0);
106         this._shadowOpacity = 0;
107         this._shadowBlur = 0;
108         this._shadowColorStr = "rgba(128, 128, 128, 0.5)";
109 
110         this._strokeEnabled = false;
111         this._strokeColor = cc.color(255, 255, 255, 255);
112         this._strokeSize = 0;
113         this._strokeColorStr = "";
114 
115         this._textFillColor = cc.color(255, 255, 255, 255);
116         this._fillColorStr = "rgba(255,255,255,1)";
117         this._strokeShadowOffsetX = 0;
118         this._strokeShadowOffsetY = 0;
119         this._needUpdateTexture = false;
120 
121         this._lineWidths = [];
122 
123         this._setColorsString();
124     },
125 
126     init:function () {
127         return this.initWithString(" ", this._fontName, this._fontSize);
128     },
129 
130     _measureConfig: function() {
131         this._getLabelContext().font = this._fontStyleStr;
132     },
133     _measure: function(text) {
134         return this._getLabelContext().measureText(text).width;
135     },
136     _checkNextline: function( text, width){
137         var tWidth = this._measure(text);
138         // Estimated word number per line
139         var baseNb = Math.floor( text.length * width / tWidth );
140         // Next line is a line with line break
141         var nextlinebreak = text.indexOf('\n');
142         if(baseNb*0.8 >= nextlinebreak && nextlinebreak > 0) return nextlinebreak+1;
143         // Text width smaller than requested width
144         if(tWidth < width) return text.length;
145 
146         var found = false, l = width + 1, idfound = -1, index = baseNb, result,
147             re = cc.LabelTTF._checkRegEx,
148             reversre = cc.LabelTTF._reverseCheckRegEx,
149             enre = cc.LabelTTF._checkEnRegEx,
150             substr = text.substr(baseNb);
151 
152         // Forward check
153         // Find next special caracter or chinese caracters
154         while (result = re.exec(substr)) {
155             index += result[0].length;
156 	        var tem = text.substr(0, index);
157 	        l = this._measure(tem);
158             if(result[2] == '\n' && l < width) {
159                 found = true;
160                 idfound = index;
161                 break;
162             }
163             if(l > width) {
164                 if(idfound != -1)
165                     found = true;
166                 break;
167             }
168             idfound = index;
169             substr = text.substr(index);
170         }
171         if(found) return idfound;
172 
173         // Backward check when forward check failed
174         substr = text.substr(0, baseNb);
175         idfound = baseNb;
176         while (result = reversre.exec(substr)) {
177             // BUG: Not secured if check with result[0]
178             idfound = result[1].length;
179             substr = result[1];
180             l = this._measure(substr);
181             if(l < width) {
182                 if(enre.test(result[2]))
183                     idfound++;
184                 break;
185             }
186         }
187 
188         // Avoid when idfound == 0, the process may enter in a infinite loop
189         return idfound || 1;
190     },
191 
192     /**
193      * Prints out a description of this class
194      * @return {String}
195      */
196     description:function () {
197         return "<cc.LabelTTF | FontName =" + this._fontName + " FontSize = " + this._fontSize.toFixed(1) + ">";
198     },
199 
200     setColor: null,
201 
202     _setColorForCanvas: function (color3) {
203         cc.NodeRGBA.prototype.setColor.call(this, color3);
204 
205         this._setColorsStringForCanvas();
206     },
207 
208     _setColorsString: null,
209 
210     _setColorsStringForCanvas: function () {
211         this._needUpdateTexture = true;
212 
213         var locDisplayColor = this._displayedColor, locDisplayedOpacity = this._displayedOpacity;
214         var locStrokeColor = this._strokeColor, locFontFillColor = this._textFillColor;
215 
216         this._shadowColorStr = "rgba(" + (0 | (locDisplayColor.r * 0.5)) + "," + (0 | (locDisplayColor.g * 0.5)) + "," + (0 | (locDisplayColor.b * 0.5)) + "," + this._shadowOpacity + ")";
217         this._fillColorStr = "rgba(" + (0 | (locDisplayColor.r /255 * locFontFillColor.r)) + "," + (0 | (locDisplayColor.g / 255 * locFontFillColor.g)) + ","
218             + (0 | (locDisplayColor.b / 255 * locFontFillColor.b)) + ", " + locDisplayedOpacity / 255 + ")";
219         this._strokeColorStr = "rgba(" + (0 | (locDisplayColor.r / 255 * locStrokeColor.r)) + "," + (0 | (locDisplayColor.g / 255 * locStrokeColor.g)) + ","
220             + (0 | (locDisplayColor.b / 255 * locStrokeColor.b)) + ", " + locDisplayedOpacity / 255 + ")";
221     },
222 
223     _setColorsStringForWebGL:function(){
224         this._needUpdateTexture = true;
225         var locStrokeColor = this._strokeColor, locFontFillColor = this._textFillColor;
226         this._shadowColorStr = "rgba(128,128,128," + this._shadowOpacity + ")";
227         this._fillColorStr = "rgba(" + (0 | locFontFillColor.r) + "," + (0 | locFontFillColor.g) + "," + (0 | locFontFillColor.b) + ", 1)";
228         this._strokeColorStr = "rgba(" + (0 | locStrokeColor.r) + "," + (0 | locStrokeColor.g) + "," + (0 | locStrokeColor.b) + ", 1)";
229     },
230 
231     updateDisplayedColor:null,
232     _updateDisplayedColorForCanvas:function(parentColor){
233         cc.NodeRGBA.prototype.updateDisplayedColor.call(this,parentColor);
234         this._setColorsString();
235     },
236 
237     setOpacity: null,
238 
239     _setOpacityForCanvas: function (opacity) {
240         if (this._opacity === opacity)
241             return;
242         cc.Sprite.prototype.setOpacity.call(this, opacity);
243         this._setColorsString();
244         this._needUpdateTexture = true;
245     },
246 
247     updateDisplayedOpacity: null,
248     updateDisplayedOpacityForCanvas: function(parentOpacity){
249         cc.NodeRGBA.prototype.updateDisplayedOpacity.call(this, parentOpacity);
250         this._setColorsString();
251     },
252 
253     /**
254      * returns the text of the label
255      * @return {String}
256      */
257     getString:function () {
258         return this._string;
259     },
260 
261     /**
262      * return Horizontal Alignment of cc.LabelTTF
263      * @return {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT}
264      */
265     getHorizontalAlignment:function () {
266         return this._hAlignment;
267     },
268 
269     /**
270      * return Vertical Alignment of cc.LabelTTF
271      * @return {cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM}
272      */
273     getVerticalAlignment:function () {
274         return this._vAlignment;
275     },
276 
277     /**
278      * return Dimensions of cc.LabelTTF
279      * @return {cc.Size}
280      */
281     getDimensions:function () {
282         return cc.size(this._dimensions.width, this._dimensions.height);
283     },
284 
285     /**
286      * return font size of cc.LabelTTF
287      * @return {Number}
288      */
289     getFontSize:function () {
290         return this._fontSize;
291     },
292 
293     /**
294      * return font name of cc.LabelTTF
295      * @return {String}
296      */
297     getFontName:function () {
298         return this._fontName;
299     },
300 
301     /**
302      * initializes the cc.LabelTTF with a font name, alignment, dimension and font size
303      * @param {String} label string
304      * @param {String} fontName
305      * @param {Number} fontSize
306      * @param {cc.Size} [dimensions=]
307      * @param {Number} [hAlignment=]
308      * @param {Number} [vAlignment=]
309      * @return {Boolean} return false on error
310      */
311     initWithString:function (label, fontName, fontSize, dimensions, hAlignment, vAlignment) {
312         var strInfo;
313         if(label)
314             strInfo = label + "";
315         else
316             strInfo = "";
317 
318         fontSize = fontSize || 16;
319         dimensions = dimensions || cc.size(0, fontSize);
320         hAlignment = hAlignment || cc.TEXT_ALIGNMENT_LEFT;
321         vAlignment = vAlignment || cc.VERTICAL_TEXT_ALIGNMENT_TOP;
322 
323         if (cc.Sprite.prototype.init.call(this)) {
324             this._opacityModifyRGB = false;
325             this._dimensions = cc.size(dimensions.width, dimensions.height);
326             this._fontName = fontName || "Arial";
327             this._hAlignment = hAlignment;
328             this._vAlignment = vAlignment;
329 
330             //this._fontSize = (cc._renderType === cc._RENDER_TYPE_CANVAS) ? fontSize : fontSize * cc.CONTENT_SCALE_FACTOR();
331             this._fontSize = fontSize;
332             this._fontStyleStr = this._fontSize + "px '" + fontName + "'";
333             this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(fontName,this._fontSize);
334             this.string = strInfo;
335             this._setColorsString();
336             this._updateTexture();
337             this._needUpdateTexture = false;
338             return true;
339         }
340         return false;
341     },
342 
343     /**
344      * initializes the CCLabelTTF with a font name, alignment, dimension and font size
345      * @param {String} text
346      * @param {cc.FontDefinition} textDefinition
347      * @return {Boolean}
348      */
349     initWithStringAndTextDefinition:null,
350 
351     _initWithStringAndTextDefinitionForCanvas:function(text, textDefinition){
352         if(!cc.Sprite.prototype.init.call(this))
353             return false;
354 
355         // prepare everything needed to render the label
356         this._updateWithTextDefinition(textDefinition, false);
357 
358         // set the string
359         this.string = text;
360 
361         return true;
362     },
363 
364     _initWithStringAndTextDefinitionForWebGL:function(text, textDefinition){
365         if(!cc.Sprite.prototype.init.call(this))
366             return false;
367 
368         // shader program
369         this.shaderProgram = cc.shaderCache.programForKey(cc.LabelTTF._SHADER_PROGRAM);
370 
371         // prepare everything needed to render the label
372         this._updateWithTextDefinition(textDefinition, false);
373 
374         // set the string
375         this.string = text;
376 
377         return true;
378     },
379 
380     /**
381      * set the text definition used by this label
382      * @param {cc.FontDefinition} theDefinition
383      */
384     setTextDefinition:function(theDefinition){
385         if (theDefinition)
386             this._updateWithTextDefinition(theDefinition, true);
387     },
388 
389     /**
390      * get the text definition used by this label
391      * @return {cc.FontDefinition}
392      */
393     getTextDefinition:function(){
394         return this._prepareTextDefinition(false);
395     },
396 
397     /**
398      * enable or disable shadow for the label
399      * @param {cc.Point} shadowOffset
400      * @param {Number} shadowOpacity (0 to 1)
401      * @param {Number} shadowBlur
402      */
403     enableShadow:function(shadowOffsetX, shadowOffsetY, shadowOpacity, shadowBlur){
404         shadowOpacity = shadowOpacity || 0.5;
405         if (false === this._shadowEnabled)
406             this._shadowEnabled = true;
407 
408         var locShadowOffset = this._shadowOffset;
409         if (locShadowOffset && (locShadowOffset.x != shadowOffsetX) || (locShadowOffset._y != shadowOffsetY)) {
410             locShadowOffset.x  = shadowOffsetX;
411             locShadowOffset.y = shadowOffsetY;
412         }
413 
414         if (this._shadowOpacity != shadowOpacity ){
415             this._shadowOpacity = shadowOpacity;
416         }
417         this._setColorsString();
418 
419         if (this._shadowBlur != shadowBlur)
420             this._shadowBlur = shadowBlur;
421 
422         this._needUpdateTexture = true;
423     },
424 
425 	_getShadowOffsetX: function () {
426 		return this._shadowOffset.x;
427 	},
428 	_setShadowOffsetX: function (x) {
429 		if (false === this._shadowEnabled)
430 			this._shadowEnabled = true;
431 
432 		if (this._shadowOffset.x != x) {
433 			this._shadowOffset.x = x;
434 			this._needUpdateTexture = true;
435 		}
436 	},
437 
438 	_getShadowOffsetY: function () {
439 		return this._shadowOffset._y;
440 	},
441 	_setShadowOffsetY: function (y) {
442 		if (false === this._shadowEnabled)
443 			this._shadowEnabled = true;
444 
445 		if (this._shadowOffset._y != y) {
446 			this._shadowOffset._y = y;
447 			this._needUpdateTexture = true;
448 		}
449 	},
450 
451 	_getShadowOffset: function () {
452 		return cc.p(this._shadowOffset.x, this._shadowOffset.y);
453 	},
454 	_setShadowOffset: function (offset) {
455 		if (false === this._shadowEnabled)
456 			this._shadowEnabled = true;
457 
458 		if (this._shadowOffset.x != offset.x || this._shadowOffset.y != offset.y) {
459 			this._shadowOffset.x = offset.x;
460 			this._shadowOffset.y = offset.y;
461 			this._needUpdateTexture = true;
462 		}
463 	},
464 
465 	_getShadowOpacity: function () {
466 		return this._shadowOpacity;
467 	},
468 	_setShadowOpacity: function (shadowOpacity) {
469 		if (false === this._shadowEnabled)
470 			this._shadowEnabled = true;
471 
472 		if (this._shadowOpacity != shadowOpacity ){
473 			this._shadowOpacity = shadowOpacity;
474 			this._setColorsString();
475 			this._needUpdateTexture = true;
476 		}
477 	},
478 
479 	_getShadowBlur: function () {
480 		return this._shadowBlur;
481 	},
482 	_setShadowBlur: function (shadowBlur) {
483 		if (false === this._shadowEnabled)
484 			this._shadowEnabled = true;
485 
486 		if (this._shadowBlur != shadowBlur) {
487 			this._shadowBlur = shadowBlur;
488 			this._needUpdateTexture = true;
489 		}
490 	},
491 
492     /**
493      * disable shadow rendering
494      */
495     disableShadow:function(){
496         if (this._shadowEnabled) {
497             this._shadowEnabled = false;
498             this._needUpdateTexture = true;
499         }
500     },
501 
502     /**
503      * enable or disable stroke
504      * @param {cc.Color} strokeColor
505      * @param {Number} strokeSize
506      */
507     enableStroke:function(strokeColor, strokeSize){
508         if(this._strokeEnabled === false)
509             this._strokeEnabled = true;
510 
511         var locStrokeColor = this._strokeColor;
512         if ( (locStrokeColor.r !== strokeColor.r) || (locStrokeColor.g !== strokeColor.g) || (locStrokeColor.b !== strokeColor.b) ) {
513             locStrokeColor.r = strokeColor.r;
514             locStrokeColor.g = strokeColor.g;
515             locStrokeColor.b = strokeColor.b;
516             this._setColorsString();
517         }
518 
519         if (this._strokeSize!== strokeSize)
520             this._strokeSize = strokeSize || 0;
521 
522         this._needUpdateTexture = true;
523     },
524 
525 	_getStrokeStyle: function () {
526 		return this._strokeColor;
527 	},
528 	_setStrokeStyle: function (strokeStyle) {
529 		if(this._strokeEnabled === false)
530 			this._strokeEnabled = true;
531 
532 		var locStrokeColor = this._strokeColor;
533 		if ( (locStrokeColor.r !== strokeStyle.r) || (locStrokeColor.g !== strokeStyle.g) || (locStrokeColor.b !== strokeStyle.b) ) {
534 			locStrokeColor.r = strokeStyle.r;
535 			locStrokeColor.g = strokeStyle.g;
536 			locStrokeColor.b = strokeStyle.b;
537 			this._setColorsString();
538 
539 			this._needUpdateTexture = true;
540 		}
541 	},
542 
543 	_getLineWidth: function () {
544 		return this._strokeSize;
545 	},
546 	_setLineWidth: function (lineWidth) {
547 		if(this._strokeEnabled === false)
548 			this._strokeEnabled = true;
549 
550 		if (this._strokeSize !== lineWidth) {
551 			this._strokeSize = lineWidth || 0;
552 			this._needUpdateTexture = true;
553 		}
554 	},
555 
556     /**
557      * disable stroke
558      */
559     disableStroke:function(){
560         if (this._strokeEnabled){
561             this._strokeEnabled = false;
562             this._needUpdateTexture = true;
563         }
564     },
565 
566     /**
567      * set text tinting
568      * @function
569      * @param {cc.Color} tintColor
570      */
571     setFontFillColor:null,
572 
573     _setFontFillColorForCanvas: function (tintColor) {
574         var locTextFillColor = this._textFillColor;
575         if (locTextFillColor.r != tintColor.r || locTextFillColor.g != tintColor.g || locTextFillColor.b != tintColor.b) {
576             locTextFillColor.r = tintColor.r;
577             locTextFillColor.g = tintColor.g;
578             locTextFillColor.b = tintColor.b;
579 
580             this._setColorsString();
581             this._needUpdateTexture = true;
582         }
583     },
584 
585     _setFontFillColorForWebGL: function (tintColor) {
586         var locTextFillColor = this._textFillColor;
587         if (locTextFillColor.r != tintColor.r || locTextFillColor.g != tintColor.g || locTextFillColor.b != tintColor.b) {
588             locTextFillColor.r = tintColor.r;
589             locTextFillColor.g = tintColor.g;
590             locTextFillColor.b = tintColor.b;
591             this._setColorsString();
592             this._needUpdateTexture = true;
593         }
594     },
595 
596 	_getFillStyle: function () {
597 		return this._textFillColor;
598 	},
599 
600     //set the text definition for this label
601     _updateWithTextDefinition:function(textDefinition, mustUpdateTexture){
602         if(textDefinition.fontDimensions){
603             this._dimensions.width = textDefinition.boundingWidth;
604             this._dimensions.height = textDefinition.boundingHeight;
605         } else {
606             this._dimensions.width = 0;
607             this._dimensions.height = 0;
608         }
609 
610         this._hAlignment  = textDefinition.textAlign;
611         this._vAlignment  = textDefinition.verticalAlign;
612 
613         this._fontName   = textDefinition.fontName;
614         this._fontSize   = textDefinition.fontSize || 12;
615         this._fontStyleStr = this._fontSize + "px '" + this._fontName + "'";
616         this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(this._fontName,this._fontSize);
617 
618         // shadow
619         if ( textDefinition.shadowEnabled)
620             this.enableShadow(textDefinition.shadowOffsetX,
621 	                          textDefinition.shadowOffsetY,
622 	                          textDefinition.shadowOpacity,
623 	                          textDefinition.shadowBlur);
624 
625         // stroke
626         if ( textDefinition.strokeEnabled )
627             this.enableStroke(textDefinition.strokeStyle, textDefinition.lineWidth);
628 
629         // fill color
630         this.setFontFillColor(textDefinition.fillStyle);
631 
632 	    if (mustUpdateTexture)
633 	        this._updateTexture();
634     },
635 
636     _prepareTextDefinition:function(adjustForResolution){
637         var texDef = new cc.FontDefinition();
638 
639         if (adjustForResolution){
640             //texDef.fontSize = (cc._renderType === cc._RENDER_TYPE_CANVAS) ? this._fontSize : this._fontSize * cc.CONTENT_SCALE_FACTOR();
641             texDef.fontSize = this._fontSize;
642             texDef.boundingWidth = cc.CONTENT_SCALE_FACTOR() * this._dimensions.width;
643 	        texDef.boundingHeight = cc.CONTENT_SCALE_FACTOR() * this._dimensions.height;
644         } else {
645             texDef.fontSize = this._fontSize;
646 	        texDef.boundingWidth = this._dimensions.width;
647 	        texDef.boundingHeight = this._dimensions.height;
648         }
649 
650         texDef.fontName       =  this._fontName;
651         texDef.textAlign =  this._hAlignment;
652         texDef.verticalAlign =  this._vAlignment;
653 
654         // stroke
655         if ( this._strokeEnabled ){
656             texDef.strokeEnabled = true;
657             var locStrokeColor = this._strokeColor;
658             texDef.strokeStyle   = cc.color(locStrokeColor.r, locStrokeColor.g, locStrokeColor.b);
659             texDef.lineWidth = this._strokeSize;
660         }else
661             texDef.strokeEnabled = false;
662 
663         // shadow
664         if ( this._shadowEnabled ){
665             texDef.shadowEnabled = true;
666             texDef.shadowBlur = this._shadowBlur;
667             texDef.shadowOpacity = this._shadowOpacity;
668 
669             texDef.shadowOffsetX = (adjustForResolution ? cc.CONTENT_SCALE_FACTOR() : 1) * this._shadowOffset.x;
670 	        texDef.shadowOffsetY = (adjustForResolution ? cc.CONTENT_SCALE_FACTOR() : 1) * this._shadowOffset.y;
671         } else
672             texDef._shadowEnabled = false;
673 
674         // text tint
675         var locTextFillColor = this._textFillColor;
676         texDef.fillStyle = cc.color(locTextFillColor.r, locTextFillColor.g, locTextFillColor.b);
677         return texDef;
678     },
679 
680     _fontClientHeight:18,
681     /**
682      * changes the string to render
683      * @warning Changing the string is as expensive as creating a new cc.LabelTTF. To obtain better performance use cc.LabelAtlas
684      * @param {String} text text for the label
685      */
686     setString:function (text) {
687         text = String(text);
688         if (this._originalText != text) {
689             this._originalText = text + "";
690 
691             this._updateString();
692 
693             // Force update
694             this._needUpdateTexture = true;
695         }
696     },
697     _updateString: function() {
698         this._string = this._originalText;
699     },
700     /**
701      * set Horizontal Alignment of cc.LabelTTF
702      * @param {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT} alignment Horizontal Alignment
703      */
704     setHorizontalAlignment:function (alignment) {
705         if (alignment !== this._hAlignment) {
706             this._hAlignment = alignment;
707 
708             // Force update
709             this._needUpdateTexture = true;
710         }
711     },
712 
713     /**
714      * set Vertical Alignment of cc.LabelTTF
715      * @param {cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM} verticalAlignment
716      */
717     setVerticalAlignment:function (verticalAlignment) {
718         if (verticalAlignment != this._vAlignment) {
719             this._vAlignment = verticalAlignment;
720 
721             // Force update
722             this._needUpdateTexture = true;
723         }
724     },
725 
726     /**
727      * set Dimensions of cc.LabelTTF
728      * @param {cc.Size} dim
729      */
730     setDimensions:function (dim) {
731         if (dim.width != this._dimensions.width || dim.height != this._dimensions.height) {
732             this._dimensions = dim;
733             this._updateString();
734             // Force udpate
735             this._needUpdateTexture = true;
736         }
737     },
738 
739 	_getBoundingWidth: function () {
740 		return this._dimensions.width;
741 	},
742 	_setBoundingWidth: function (width) {
743 		if (width != this._dimensions.width) {
744 			this._dimensions.width = width;
745 			this._updateString();
746 			// Force udpate
747 			this._needUpdateTexture = true;
748 		}
749 	},
750 
751 	_getBoundingHeight: function () {
752 		return this._dimensions.height;
753 	},
754 	_setBoundingHeight: function (height) {
755 		if (height != this._dimensions.height) {
756 			this._dimensions.height = height;
757 			this._updateString();
758 			// Force udpate
759 			this._needUpdateTexture = true;
760 		}
761 	},
762 
763     /**
764      * set font size of cc.LabelTTF
765      * @param {Number} fontSize
766      */
767     setFontSize:function (fontSize) {
768         if (this._fontSize !== fontSize) {
769             this._fontSize = fontSize;
770             this._fontStyleStr = fontSize + "px '" + this._fontName + "'";
771             this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(this._fontName, fontSize);
772             // Force update
773             this._needUpdateTexture = true;
774         }
775     },
776 
777     /**
778      * set font name of cc.LabelTTF
779      * @param {String} fontName
780      */
781     setFontName:function (fontName) {
782         if (this._fontName && this._fontName != fontName ) {
783             this._fontName = fontName;
784             this._fontStyleStr = this._fontSize + "px '" + fontName + "'";
785             this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(fontName, this._fontSize);
786             // Force update
787             this._needUpdateTexture = true;
788         }
789     },
790 
791 	_getFont: function () {
792 		return this._fontStyleStr;
793 	},
794 	_setFont: function (fontStyle) {
795 		var res = cc.LabelTTF._fontStyleRE.exec(fontStyle);
796 		if(res) {
797 			this._fontSize = parseInt(res[1]);
798 			this._fontName = res[2];
799 			this._fontStyleStr = fontStyle;
800 			this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(this._fontName, this._fontSize);
801 			// Force update
802 			this._needUpdateTexture = true;
803 		}
804 	},
805 
806     _drawTTFInCanvas: function (context) {
807         if (!context)
808             return;
809         var locStrokeShadowOffsetX = this._strokeShadowOffsetX, locStrokeShadowOffsetY = this._strokeShadowOffsetY;
810         var locContentSizeHeight = this._contentSize.height - locStrokeShadowOffsetY, locVAlignment = this._vAlignment, locHAlignment = this._hAlignment,
811             locFontHeight = this._fontClientHeight, locStrokeSize = this._strokeSize;
812 
813         context.setTransform(1, 0, 0, 1, 0 + locStrokeShadowOffsetX * 0.5 , locContentSizeHeight + locStrokeShadowOffsetY * 0.5);
814 
815         //this is fillText for canvas
816         if (context.font != this._fontStyleStr)
817             context.font = this._fontStyleStr;
818         context.fillStyle = this._fillColorStr;
819 
820         var xOffset = 0, yOffset = 0;
821         //stroke style setup
822         var locStrokeEnabled = this._strokeEnabled;
823         if (locStrokeEnabled) {
824             context.lineWidth = locStrokeSize * 2;
825             context.strokeStyle = this._strokeColorStr;
826         }
827 
828         //shadow style setup
829         if (this._shadowEnabled) {
830             var locShadowOffset = this._shadowOffset;
831             context.shadowColor = this._shadowColorStr;
832             context.shadowOffsetX = locShadowOffset.x;
833             context.shadowOffsetY = -locShadowOffset.y;
834             context.shadowBlur = this._shadowBlur;
835         }
836 
837         context.textBaseline = cc.LabelTTF._textBaseline[locVAlignment];
838         context.textAlign = cc.LabelTTF._textAlign[locHAlignment];
839 
840         var locContentWidth = this._contentSize.width - locStrokeShadowOffsetX;
841         if (locHAlignment === cc.TEXT_ALIGNMENT_RIGHT)
842             xOffset += locContentWidth;
843         else if (locHAlignment === cc.TEXT_ALIGNMENT_CENTER)
844             xOffset += locContentWidth / 2;
845         else
846             xOffset += 0;
847         if (this._isMultiLine) {
848             var locStrLen = this._strings.length;
849             if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM)
850                 yOffset = locFontHeight + locContentSizeHeight - locFontHeight * locStrLen;
851             else if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_CENTER)
852                 yOffset = locFontHeight / 2 + (locContentSizeHeight - locFontHeight * locStrLen) / 2;
853 
854             for (var i = 0; i < locStrLen; i++) {
855                 var line = this._strings[i];
856                 var tmpOffsetY = -locContentSizeHeight + (locFontHeight * i) + yOffset;
857                 if (locStrokeEnabled)
858                     context.strokeText(line, xOffset, tmpOffsetY);
859                 context.fillText(line, xOffset, tmpOffsetY);
860             }
861         } else {
862             if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM) {
863                 if (locStrokeEnabled)
864                     context.strokeText(this._string, xOffset, yOffset);
865                 context.fillText(this._string, xOffset, yOffset);
866             } else if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_TOP) {
867                 yOffset -= locContentSizeHeight ;
868                 if (locStrokeEnabled)
869                     context.strokeText(this._string, xOffset, yOffset);
870                 context.fillText(this._string, xOffset, yOffset);
871             } else {
872                 yOffset -= locContentSizeHeight * 0.5;
873                 if (locStrokeEnabled)
874                     context.strokeText(this._string, xOffset, yOffset);
875                 context.fillText(this._string, xOffset, yOffset);
876             }
877         }
878     },
879 
880     _getLabelContext:function () {
881         if (this._labelContext)
882             return this._labelContext;
883 
884         if (!this._labelCanvas) {
885             var locCanvas = document.createElement("canvas");
886             var labelTexture = new cc.Texture2D();
887             labelTexture.initWithElement(locCanvas);
888             this.texture = labelTexture;
889             this._labelCanvas = locCanvas;
890         }
891         this._labelContext = this._labelCanvas.getContext("2d");
892         return this._labelContext;
893     },
894 
895     _updateTTF: function () {
896         var locDimensionsWidth = this._dimensions.width, i, strLength;
897         var locLineWidth = this._lineWidths;
898         locLineWidth.length = 0;
899 
900         this._isMultiLine = false ;
901         this._measureConfig();
902         if (locDimensionsWidth !== 0) {
903             // Content processing
904             var text = this._string;
905             this._strings = [];
906             for (i = 0, strLength = this._string.length; i < strLength;) {
907                 // Find the index of next line
908                 var next = this._checkNextline(text.substr(i), locDimensionsWidth);
909                 var append = text.substr(i, next);
910                 this._strings.push(append);
911                 i += next;
912             }
913         } else {
914             this._strings = this._string.split('\n');
915             for (i = 0, strLength = this._strings.length; i < strLength; i++) {
916                 locLineWidth.push(this._measure(this._strings[i]));
917             }
918         }
919 
920         if (this._strings.length > 0)
921             this._isMultiLine = true;
922 
923         var locSize, locStrokeShadowOffsetX = 0, locStrokeShadowOffsetY = 0;
924         if (this._strokeEnabled)
925             locStrokeShadowOffsetX = locStrokeShadowOffsetY = this._strokeSize * 2;
926         if (this._shadowEnabled) {
927             var locOffsetSize = this._shadowOffset;
928             locStrokeShadowOffsetX += Math.abs(locOffsetSize.x) * 2;
929             locStrokeShadowOffsetY += Math.abs(locOffsetSize.y) * 2;
930         }
931 
932         //get offset for stroke and shadow
933         if (locDimensionsWidth === 0) {
934             if (this._isMultiLine)
935                 locSize = cc.size(0 | (Math.max.apply(Math, locLineWidth) + locStrokeShadowOffsetX),
936                     0 | ((this._fontClientHeight * this._strings.length) + locStrokeShadowOffsetY));
937             else
938                 locSize = cc.size(0 | (this._measure(this._string) + locStrokeShadowOffsetX), 0 | (this._fontClientHeight + locStrokeShadowOffsetY));
939         } else {
940             if (this._dimensions.height === 0) {
941                 if (this._isMultiLine)
942                     locSize = cc.size(0 | (locDimensionsWidth + locStrokeShadowOffsetX), 0 | ((this._fontClientHeight * this._strings.length) + locStrokeShadowOffsetY));
943                 else
944                     locSize = cc.size(0 | (locDimensionsWidth + locStrokeShadowOffsetX), 0 | (this._fontClientHeight + locStrokeShadowOffsetY));
945             } else {
946                 //dimension is already set, contentSize must be same as dimension
947                 locSize = cc.size(0 | (locDimensionsWidth + locStrokeShadowOffsetX), 0 | (this._dimensions.height + locStrokeShadowOffsetY));
948             }
949         }
950         this.setContentSize(locSize);
951         this._strokeShadowOffsetX = locStrokeShadowOffsetX;
952         this._strokeShadowOffsetY = locStrokeShadowOffsetY;
953 
954         // need computing _anchorPointInPoints
955         var locAP = this._anchorPoint;
956         this._anchorPointInPoints.x = (locStrokeShadowOffsetX * 0.5) + ((locSize.width - locStrokeShadowOffsetX) * locAP.x);
957         this._anchorPointInPoints.y = (locStrokeShadowOffsetY * 0.5) + ((locSize.height - locStrokeShadowOffsetY) * locAP.y);
958     },
959 
960     getContentSize:function(){
961         if(this._needUpdateTexture)
962             this._updateTTF();
963         return cc.Sprite.prototype.getContentSize.call(this);
964     },
965 
966 	_getWidth:function(){
967 		if(this._needUpdateTexture)
968 			this._updateTTF();
969 		return cc.Sprite.prototype._getWidth.call(this);
970 	},
971 	_getHeight:function(){
972 		if(this._needUpdateTexture)
973 			this._updateTTF();
974 		return cc.Sprite.prototype._getHeight.call(this);
975 	},
976 
977     _updateTexture:function () {
978         var locContext = this._getLabelContext(), locLabelCanvas = this._labelCanvas;
979         var locContentSize = this._contentSize;
980 
981         if(this._string.length === 0){
982             locLabelCanvas.width = 1;
983             locLabelCanvas.height = locContentSize.height;
984             this.setTextureRect(cc.rect(0, 0, 1, locContentSize.height));
985             return true;
986         }
987 
988         //set size for labelCanvas
989         locContext.font = this._fontStyleStr;
990         this._updateTTF();
991         var width = locContentSize.width, height = locContentSize.height;
992         var flag = locLabelCanvas.width == width && locLabelCanvas.height == height;
993         locLabelCanvas.width = width;
994         locLabelCanvas.height = height;
995         if(flag) locContext.clearRect(0, 0, width, height);
996 
997         //draw text to labelCanvas
998         this._drawTTFInCanvas(locContext);
999         this._texture.handleLoadedTexture();
1000 
1001         this.setTextureRect(cc.rect(0, 0, width, height));
1002         return true;
1003     },
1004 
1005     visit:function(ctx){
1006         if(!this._string || this._string == "")
1007             return;
1008         if(this._needUpdateTexture ){
1009             this._needUpdateTexture = false;
1010             this._updateTexture();
1011         }
1012         var context = ctx || cc._renderContext;
1013         cc.Sprite.prototype.visit.call(this,context);
1014     },
1015 
1016 	/**
1017 	 * Draw sprite to canvas
1018 	 * @function
1019 	 * @param {CanvasRenderingContext2D|WebGLRenderingContext} ctx Render context of canvas, 2d or 3d
1020 	 */
1021     draw: null,
1022 
1023     _drawForWebGL: function (ctx) {
1024         if (!this._string || this._string == "")
1025             return;
1026 
1027         var gl = ctx || cc._renderContext, locTexture = this._texture;
1028 
1029         if (locTexture && locTexture._isLoaded) {
1030             this._shaderProgram.use();
1031             this._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4();
1032 
1033             cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst);
1034             cc.glBindTexture2D(locTexture);
1035 
1036             cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POS_COLOR_TEX);
1037 
1038             gl.bindBuffer(gl.ARRAY_BUFFER, this._quadWebBuffer);
1039             if (this._quadDirty) {
1040                 gl.bufferData(gl.ARRAY_BUFFER, this._quad.arrayBuffer, gl.STATIC_DRAW);
1041                 this._quadDirty = false;
1042             }
1043             gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 24, 0);
1044             gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 24, 16);
1045             gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 24, 12);
1046             gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
1047         }
1048 
1049         if (cc.SPRITE_DEBUG_DRAW === 1) {
1050             // draw bounding box
1051             var locQuad = this._quad;
1052             var verticesG1 = [
1053                 cc.p(locQuad.tl.vertices.x, locQuad.tl.vertices.y),
1054                 cc.p(locQuad.bl.vertices.x, locQuad.bl.vertices.y),
1055                 cc.p(locQuad.br.vertices.x, locQuad.br.vertices.y),
1056                 cc.p(locQuad.tr.vertices.x, locQuad.tr.vertices.y)
1057             ];
1058             cc._drawingUtil.drawPoly(verticesG1, 4, true);
1059         } else if (cc.SPRITE_DEBUG_DRAW === 2) {
1060             // draw texture box
1061             var drawSizeG2 = this.getTextureRect()._size;
1062             var offsetPixG2X = this.offsetX, offsetPixG2Y = this.offsetY;
1063             var verticesG2 = [cc.p(offsetPixG2X, offsetPixG2Y), cc.p(offsetPixG2X + drawSizeG2.width, offsetPixG2Y),
1064                 cc.p(offsetPixG2X + drawSizeG2.width, offsetPixG2Y + drawSizeG2.height), cc.p(offsetPixG2X, offsetPixG2Y + drawSizeG2.height)];
1065             cc._drawingUtil.drawPoly(verticesG2, 4, true);
1066         } // CC_SPRITE_DEBUG_DRAW
1067         cc.g_NumberOfDraws++;
1068     },
1069 
1070     _setTextureRectForCanvas: function (rect, rotated, untrimmedSize) {
1071         this._rectRotated = rotated || false;
1072         untrimmedSize = untrimmedSize || rect;
1073 
1074         this.setContentSize(untrimmedSize);
1075         this.setVertexRect(rect);
1076 
1077         var locTextureCoordRect = this._textureRect_Canvas;
1078         locTextureCoordRect.x = rect.x;
1079         locTextureCoordRect.y = rect.y;
1080         locTextureCoordRect.width = rect.width;
1081         locTextureCoordRect.height = rect.height;
1082         locTextureCoordRect.validRect = !(locTextureCoordRect.width === 0 || locTextureCoordRect.height === 0
1083             || locTextureCoordRect.x < 0 || locTextureCoordRect.y < 0);
1084 
1085         var relativeOffset = this._unflippedOffsetPositionFromCenter;
1086         if (this._flippedX)
1087             relativeOffset.x = -relativeOffset.x;
1088         if (this._flippedY)
1089             relativeOffset.y = -relativeOffset.y;
1090         this._offsetPosition.x = relativeOffset.x + (this._contentSize.width - this._rect.width) / 2;
1091         this._offsetPosition.y = relativeOffset.y + (this._contentSize.height - this._rect.height) / 2;
1092 
1093         // rendering using batch node
1094         if (this._batchNode) {
1095             this.dirty = true;
1096         }
1097     },
1098 
1099     _setTextureCoords:function (rect) {
1100         var tex = this._batchNode ? this.textureAtlas.texture : this._texture;
1101         if (!tex)
1102             return;
1103 
1104         var atlasWidth = tex.pixelsWidth;
1105         var atlasHeight = tex.pixelsHeight;
1106 
1107         var left, right, top, bottom, tempSwap, locQuad = this._quad;
1108         if (this._rectRotated) {
1109             if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
1110                 left = (2 * rect.x + 1) / (2 * atlasWidth);
1111                 right = left + (rect.height * 2 - 2) / (2 * atlasWidth);
1112                 top = (2 * rect.y + 1) / (2 * atlasHeight);
1113                 bottom = top + (rect.width * 2 - 2) / (2 * atlasHeight);
1114             } else {
1115                 left = rect.x / atlasWidth;
1116                 right = (rect.x + rect.height) / atlasWidth;
1117                 top = rect.y / atlasHeight;
1118                 bottom = (rect.y + rect.width) / atlasHeight;
1119             }// CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
1120 
1121             if (this._flippedX) {
1122                 tempSwap = top;
1123                 top = bottom;
1124                 bottom = tempSwap;
1125             }
1126 
1127             if (this._flippedY) {
1128                 tempSwap = left;
1129                 left = right;
1130                 right = tempSwap;
1131             }
1132 
1133             locQuad.bl.texCoords.u = left;
1134             locQuad.bl.texCoords.v = top;
1135             locQuad.br.texCoords.u = left;
1136             locQuad.br.texCoords.v = bottom;
1137             locQuad.tl.texCoords.u = right;
1138             locQuad.tl.texCoords.v = top;
1139             locQuad.tr.texCoords.u = right;
1140             locQuad.tr.texCoords.v = bottom;
1141         } else {
1142             if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
1143                 left = (2 * rect.x + 1) / (2 * atlasWidth);
1144                 right = left + (rect.width * 2 - 2) / (2 * atlasWidth);
1145                 top = (2 * rect.y + 1) / (2 * atlasHeight);
1146                 bottom = top + (rect.height * 2 - 2) / (2 * atlasHeight);
1147             } else {
1148                 left = rect.x / atlasWidth;
1149                 right = (rect.x + rect.width) / atlasWidth;
1150                 top = rect.y / atlasHeight;
1151                 bottom = (rect.y + rect.height) / atlasHeight;
1152             } // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
1153 
1154             if (this._flippedX) {
1155                 tempSwap = left;
1156                 left = right;
1157                 right = tempSwap;
1158             }
1159 
1160             if (this._flippedY) {
1161                 tempSwap = top;
1162                 top = bottom;
1163                 bottom = tempSwap;
1164             }
1165 
1166             locQuad.bl.texCoords.u = left;
1167             locQuad.bl.texCoords.v = bottom;
1168             locQuad.br.texCoords.u = right;
1169             locQuad.br.texCoords.v = bottom;
1170             locQuad.tl.texCoords.u = left;
1171             locQuad.tl.texCoords.v = top;
1172             locQuad.tr.texCoords.u = right;
1173             locQuad.tr.texCoords.v = top;
1174         }
1175         this._quadDirty = true;
1176     }
1177 });
1178 
1179 window._p = cc.LabelTTF.prototype;
1180 if (cc._renderType === cc._RENDER_TYPE_WEBGL) {
1181 	_p.setColor = cc.Sprite.prototype.setColor;
1182     _p._setColorsString = _p._setColorsStringForWebGL;
1183     _p.updateDisplayedColor = cc.Sprite.prototype.updateDisplayedColor;
1184     _p.setOpacity = cc.Sprite.prototype.setOpacity;
1185     _p.updateDisplayedOpacity = cc.Sprite.prototype.updateDisplayedOpacity;
1186     _p.initWithStringAndTextDefinition = _p._initWithStringAndTextDefinitionForWebGL;
1187     _p.setFontFillColor = _p._setFontFillColorForWebGL;
1188     _p.draw = _p._drawForWebGL;
1189     _p.setTextureRect = cc.Sprite.prototype._setTextureRectForWebGL;
1190 } else {
1191     _p.setColor = _p._setColorForCanvas;
1192     _p._setColorsString = _p._setColorsStringForCanvas;
1193     _p.updateDisplayedColor = _p._updateDisplayedColorForCanvas;
1194     _p.setOpacity = _p._setOpacityForCanvas;
1195     _p.updateDisplayedOpacity = _p._updateDisplayedOpacityForCanvas;
1196     _p.initWithStringAndTextDefinition = _p._initWithStringAndTextDefinitionForCanvas;
1197     _p.setFontFillColor = _p._setFontFillColorForCanvas;
1198     _p.draw = cc.Sprite.prototype.draw;
1199     _p.setTextureRect = _p._setTextureRectForCanvas;
1200 }
1201 
1202 // Override properties
1203 cc.defineGetterSetter(_p, "color", _p.getColor, _p.setColor);
1204 cc.defineGetterSetter(_p, "opacity", _p.getOpacity, _p.setOpacity);
1205 
1206 // Extended properties
1207 /** @expose */
1208 _p.string;
1209 cc.defineGetterSetter(_p, "string", _p.getString, _p.setString);
1210 /** @expose */
1211 _p.textAlign;
1212 cc.defineGetterSetter(_p, "textAlign", _p.getHorizontalAlignment, _p.setHorizontalAlignment);
1213 /** @expose */
1214 _p.verticalAlign;
1215 cc.defineGetterSetter(_p, "verticalAlign", _p.getVerticalAlignment, _p.setVerticalAlignment);
1216 /** @expose */
1217 _p.fontSize;
1218 cc.defineGetterSetter(_p, "fontSize", _p.getFontSize, _p.setFontSize);
1219 /** @expose */
1220 _p.fontName;
1221 cc.defineGetterSetter(_p, "fontName", _p.getFontName, _p.setFontName);
1222 /** @expose */
1223 _p.font;
1224 cc.defineGetterSetter(_p, "font", _p._getFont, _p._setFont);
1225 /** @expose */
1226 _p.boundingSize;
1227 //cc.defineGetterSetter(_p, "boundingSize", _p.getDimensions, _p.setDimensions);
1228 /** @expose */
1229 _p.boundingWidth;
1230 cc.defineGetterSetter(_p, "boundingWidth", _p._getBoundingWidth, _p._setBoundingWidth);
1231 /** @expose */
1232 _p.boundingHeight;
1233 cc.defineGetterSetter(_p, "boundingHeight", _p._getBoundingHeight, _p._setBoundingHeight);
1234 /** @expose */
1235 _p.fillStyle;
1236 cc.defineGetterSetter(_p, "fillStyle", _p._getFillStyle, _p.setFontFillColor);
1237 /** @expose */
1238 _p.strokeStyle;
1239 cc.defineGetterSetter(_p, "strokeStyle", _p._getStrokeStyle, _p._setStrokeStyle);
1240 /** @expose */
1241 _p.lineWidth;
1242 cc.defineGetterSetter(_p, "lineWidth", _p._getLineWidth, _p._setLineWidth);
1243 /** @expose */
1244 _p.shadowOffset;
1245 //cc.defineGetterSetter(_p, "shadowOffset", _p._getShadowOffset, _p._setShadowOffset);
1246 /** @expose */
1247 _p.shadowOffsetX;
1248 cc.defineGetterSetter(_p, "shadowOffsetX", _p._getShadowOffsetX, _p._setShadowOffsetX);
1249 /** @expose */
1250 _p.shadowOffsetY;
1251 cc.defineGetterSetter(_p, "shadowOffsetY", _p._getShadowOffsetY, _p._setShadowOffsetY);
1252 /** @expose */
1253 _p.shadowOpacity;
1254 cc.defineGetterSetter(_p, "shadowOpacity", _p._getShadowOpacity, _p._setShadowOpacity);
1255 /** @expose */
1256 _p.shadowBlur;
1257 cc.defineGetterSetter(_p, "shadowBlur", _p._getShadowBlur, _p._setShadowBlur);
1258 
1259 delete window._p;
1260 
1261 cc.LabelTTF._textAlign = ["left", "center", "right"];
1262 
1263 cc.LabelTTF._textBaseline = ["top", "middle", "bottom"];
1264 
1265 // Class static properties for measure util
1266 cc.LabelTTF._checkRegEx = /(.+?)([\s\n\r\-\/\\\:]|[\u4E00-\u9FA5]|[\uFE30-\uFFA0])/;
1267 cc.LabelTTF._reverseCheckRegEx = /(.*)([\s\n\r\-\/\\\:]|[\u4E00-\u9FA5]|[\uFE30-\uFFA0])/;
1268 cc.LabelTTF._checkEnRegEx = /[\s\-\/\\\:]/;
1269 
1270 // Only support style in this format: "18px Verdana" or "18px 'Helvetica Neue'"
1271 cc.LabelTTF._fontStyleRE = /^(\d+)px\s+['"]?([\w\s\d]+)['"]?$/;
1272 
1273 /**
1274  * creates a cc.LabelTTF from a font name, alignment, dimension and font size
1275  * @param {String} text
1276  * @param {String|cc.FontDefinition} fontName
1277  * @param {Number} fontSize
1278  * @param {cc.Size} [dimensions=cc.size(0,0)]
1279  * @param {Number} [hAlignment=]
1280  * @param {Number} [vAlignment=cc.VERTICAL_TEXT_ALIGNMENT_TOP]
1281  * @return {cc.LabelTTF|Null}
1282  * @example
1283  * // Example
1284  * 1.
1285  * var myLabel = cc.LabelTTF.create('label text',  'Times New Roman', 32, cc.size(320,32), cc.TEXT_ALIGNMENT_LEFT);
1286  * 2.
1287  * var fontDef = new cc.FontDefinition();
1288  * fontDef.fontName = "Arial";
1289  * fontDef.fontSize = "32";
1290  * var myLabel = cc.LabelTTF.create('label text',  fontDef);
1291  */
1292 cc.LabelTTF.create = function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) {
1293     var ret = new cc.LabelTTF();
1294     if (fontName && fontName instanceof cc.FontDefinition) {
1295         if (ret.initWithStringAndTextDefinition(text, fontName))
1296             return ret;
1297     }
1298     if (ret.initWithString(text, fontName, fontSize, dimensions, hAlignment, vAlignment))
1299         return ret;
1300     return null;
1301 };
1302 
1303 
1304 if(cc.USE_LA88_LABELS)
1305     cc.LabelTTF._SHADER_PROGRAM = cc.SHADER_POSITION_TEXTURECOLOR;
1306 else
1307     cc.LabelTTF._SHADER_PROGRAM = cc.SHADER_POSITION_TEXTUREA8COLOR;
1308 
1309 cc.LabelTTF.__labelHeightDiv = document.createElement("div");
1310 cc.LabelTTF.__labelHeightDiv.style.fontFamily = "Arial";
1311 cc.LabelTTF.__labelHeightDiv.style.position = "absolute";
1312 cc.LabelTTF.__labelHeightDiv.style.left = "-100px";
1313 cc.LabelTTF.__labelHeightDiv.style.top = "-100px";
1314 cc.LabelTTF.__labelHeightDiv.style.lineHeight = "normal";
1315 document.body.appendChild(cc.LabelTTF.__labelHeightDiv);
1316 
1317 cc.LabelTTF.__getFontHeightByDiv = function(fontName, fontSize){
1318     var clientHeight = cc.LabelTTF.__fontHeightCache[fontName + "." + fontSize];
1319     if (clientHeight > 0) return clientHeight;
1320     var labelDiv = cc.LabelTTF.__labelHeightDiv;
1321     labelDiv.innerHTML = "ajghl~!";
1322     labelDiv.style.fontFamily = fontName;
1323     labelDiv.style.fontSize = fontSize + "px";
1324     clientHeight = labelDiv.clientHeight ;
1325     cc.LabelTTF.__fontHeightCache[fontName + "." + fontSize] = clientHeight;
1326     labelDiv.innerHTML = "";
1327     return clientHeight;
1328 };
1329 
1330 cc.LabelTTF.__fontHeightCache = {};
1331 
1332 
1333 
1334