1 /****************************************************************************
  2  Copyright (c) 2008-2010 Ricardo Quesada
  3  Copyright (c) 2011-2012 cocos2d-x.org
  4  Copyright (c) 2013-2014 Chukong Technologies 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>cc.LabelTTF is a subclass of cc.TextureNode that knows how to render text labels with system font or a ttf font file<br/>
 29  * All features from cc.Sprite are valid in cc.LabelTTF<br/>
 30  * cc.LabelTTF objects are slow for js-binding on mobile devices.<br/>
 31  * Consider using cc.LabelAtlas or cc.LabelBMFont instead.<br/>
 32  * You can create a cc.LabelTTF from a font name, alignment, dimension and font size or a cc.FontDefinition object.</p>
 33  * @class
 34  * @extends cc.Sprite
 35  *
 36  * @param {String} text
 37  * @param {String|cc.FontDefinition} [fontName="Arial"]
 38  * @param {Number} [fontSize=16]
 39  * @param {cc.Size} [dimensions=cc.size(0,0)]
 40  * @param {Number} [hAlignment=cc.TEXT_ALIGNMENT_LEFT]
 41  * @param {Number} [vAlignment=cc.VERTICAL_TEXT_ALIGNMENT_TOP]
 42  * @example
 43  * var myLabel = new cc.LabelTTF('label text',  'Times New Roman', 32, cc.size(320,32), cc.TEXT_ALIGNMENT_LEFT);
 44  *
 45  * var fontDef = new cc.FontDefinition();
 46  * fontDef.fontName = "Arial";
 47  * fontDef.fontSize = "32";
 48  * var myLabel = new cc.LabelTTF('label text',  fontDef);
 49  *
 50  * @property {String}       string          - Content string of label
 51  * @property {Number}       textAlign       - Horizontal Alignment of label: cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT
 52  * @property {Number}       verticalAlign   - Vertical Alignment of label: cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM
 53  * @property {Number}       fontSize        - Font size of label
 54  * @property {String}       fontName        - Font name of label
 55  * @property {String}       font            - The label font with a style string: e.g. "18px Verdana"
 56  * @property {Number}       boundingWidth   - Width of the bounding box of label, the real content width is limited by boundingWidth
 57  * @property {Number}       boundingHeight  - Height of the bounding box of label, the real content height is limited by boundingHeight
 58  * @property {cc.Color}     fillStyle       - The fill color
 59  * @property {cc.Color}     strokeStyle     - The stroke color
 60  * @property {Number}       lineWidth       - The line width for stroke
 61  * @property {Number}       shadowOffsetX   - The x axis offset of shadow
 62  * @property {Number}       shadowOffsetY   - The y axis offset of shadow
 63  * @property {Number}       shadowOpacity   - The opacity of shadow
 64  * @property {Number}       shadowBlur      - The blur size of shadow
 65  */
 66 cc.LabelTTF = cc.Sprite.extend(/** @lends cc.LabelTTF# */{
 67     _dimensions: null,
 68     _hAlignment: cc.TEXT_ALIGNMENT_CENTER,
 69     _vAlignment: cc.VERTICAL_TEXT_ALIGNMENT_TOP,
 70     _fontName: null,
 71     _fontSize: 0.0,
 72     _string: "",
 73     _originalText: null,
 74 
 75     // font shadow
 76     _shadowEnabled: false,
 77     _shadowOffset: null,
 78     _shadowOpacity: 0,
 79     _shadowBlur: 0,
 80     _shadowColor: null,
 81 
 82     // font stroke
 83     _strokeEnabled: false,
 84     _strokeColor: null,
 85     _strokeSize: 0,
 86 
 87     // font tint
 88     _textFillColor: null,
 89 
 90     _strokeShadowOffsetX: 0,
 91     _strokeShadowOffsetY: 0,
 92     _needUpdateTexture: false,
 93 
 94     _lineWidths: null,
 95     _className: "LabelTTF",
 96 
 97     //for web
 98     _fontStyle: "normal",
 99     _fontWeight: "normal",
100     _lineHeight: "normal",
101 
102     /**
103      * Initializes the cc.LabelTTF with a font name, alignment, dimension and font size, do not call it by yourself,
104      * you should pass the correct arguments in constructor to initialize the label.
105      * @param {String} label string
106      * @param {String} fontName
107      * @param {Number} fontSize
108      * @param {cc.Size} [dimensions=]
109      * @param {Number} [hAlignment=]
110      * @param {Number} [vAlignment=]
111      * @return {Boolean} return false on error
112      */
113     initWithString: function (label, fontName, fontSize, dimensions, hAlignment, vAlignment) {
114         var strInfo;
115         if (label)
116             strInfo = label + "";
117         else
118             strInfo = "";
119 
120         fontSize = fontSize || 16;
121         dimensions = dimensions || cc.size(0, 0/*fontSize*/);
122         hAlignment = hAlignment || cc.TEXT_ALIGNMENT_LEFT;
123         vAlignment = vAlignment || cc.VERTICAL_TEXT_ALIGNMENT_TOP;
124 
125         this._opacityModifyRGB = false;
126         this._dimensions = cc.size(dimensions.width, dimensions.height);
127         this._fontName = fontName || "Arial";
128         this._hAlignment = hAlignment;
129         this._vAlignment = vAlignment;
130 
131         this._fontSize = fontSize;
132         this._renderCmd._setFontStyle(this._fontName, fontSize, this._fontStyle, this._fontWeight);
133         this.string = strInfo;
134         this._renderCmd._setColorsString();
135         this._renderCmd._updateTexture();
136         this._setUpdateTextureDirty();
137         return true;
138     },
139 
140     _setUpdateTextureDirty: function () {
141         this._needUpdateTexture = true;
142         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.textDirty);
143     },
144 
145     ctor: function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) {
146         cc.Sprite.prototype.ctor.call(this);
147 
148         this._dimensions = cc.size(0, 0);
149         this._hAlignment = cc.TEXT_ALIGNMENT_LEFT;
150         this._vAlignment = cc.VERTICAL_TEXT_ALIGNMENT_TOP;
151         this._opacityModifyRGB = false;
152         this._fontName = "Arial";
153 
154         this._shadowEnabled = false;
155         this._shadowOffset = cc.p(0, 0);
156         this._shadowOpacity = 0;
157         this._shadowBlur = 0;
158 
159         this._strokeEnabled = false;
160         this._strokeColor = cc.color(255, 255, 255, 255);
161         this._strokeSize = 0;
162 
163         this._textFillColor = cc.color(255, 255, 255, 255);
164         this._strokeShadowOffsetX = 0;
165         this._strokeShadowOffsetY = 0;
166         this._needUpdateTexture = false;
167 
168         this._lineWidths = [];
169         this._renderCmd._setColorsString();
170         this._textureLoaded = true;
171 
172         if (fontName && fontName instanceof cc.FontDefinition) {
173             this.initWithStringAndTextDefinition(text, fontName);
174         } else {
175             cc.LabelTTF.prototype.initWithString.call(this, text, fontName, fontSize, dimensions, hAlignment, vAlignment);
176         }
177     },
178 
179     init: function () {
180         return this.initWithString(" ", this._fontName, this._fontSize);
181     },
182 
183     description: function () {
184         return "<cc.LabelTTF | FontName =" + this._fontName + " FontSize = " + this._fontSize.toFixed(1) + ">";
185     },
186 
187     getLineHeight: function () {
188         return !this._lineHeight || this._lineHeight.charAt ?
189             this._renderCmd._getFontClientHeight() :
190             this._lineHeight || this._renderCmd._getFontClientHeight();
191     },
192 
193     setLineHeight: function (lineHeight) {
194         this._lineHeight = lineHeight;
195     },
196 
197     /**
198      * Returns the text of the label
199      * @return {String}
200      */
201     getString: function () {
202         return this._string;
203     },
204 
205     /**
206      * Returns Horizontal Alignment of cc.LabelTTF
207      * @return {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT}
208      */
209     getHorizontalAlignment: function () {
210         return this._hAlignment;
211     },
212 
213     /**
214      * Returns Vertical Alignment of cc.LabelTTF
215      * @return {cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM}
216      */
217     getVerticalAlignment: function () {
218         return this._vAlignment;
219     },
220 
221     /**
222      * Returns the dimensions of cc.LabelTTF, the dimension is the maximum size of the label, set it so that label will automatically change lines when necessary.
223      * @see cc.LabelTTF#setDimensions, cc.LabelTTF#boundingWidth and cc.LabelTTF#boundingHeight
224      * @return {cc.Size}
225      */
226     getDimensions: function () {
227         return cc.size(this._dimensions);
228     },
229 
230     /**
231      * Returns font size of cc.LabelTTF
232      * @return {Number}
233      */
234     getFontSize: function () {
235         return this._fontSize;
236     },
237 
238     /**
239      * Returns font name of cc.LabelTTF
240      * @return {String}
241      */
242     getFontName: function () {
243         return this._fontName;
244     },
245 
246     /**
247      * Initializes the CCLabelTTF with a font name, alignment, dimension and font size, do not call it by yourself, you should pass the correct arguments in constructor to initialize the label.
248      * @param {String} text
249      * @param {cc.FontDefinition} textDefinition
250      * @return {Boolean}
251      */
252     initWithStringAndTextDefinition: function (text, textDefinition) {
253         // prepare everything needed to render the label
254         this._updateWithTextDefinition(textDefinition, false);
255         // set the string
256         this.string = text;
257         return true;
258     },
259 
260     /**
261      * Sets the text definition used by this label
262      * @param {cc.FontDefinition} theDefinition
263      */
264     setTextDefinition: function (theDefinition) {
265         if (theDefinition)
266             this._updateWithTextDefinition(theDefinition, true);
267     },
268 
269     /**
270      * Extract the text definition used by this label
271      * @return {cc.FontDefinition}
272      */
273     getTextDefinition: function () {
274         return this._prepareTextDefinition(false);
275     },
276 
277     /**
278      * Enable or disable shadow for the label
279      * @param {cc.Color | Number} a Color or The x axis offset of the shadow
280      * @param {cc.Size | Number} b Size or The y axis offset of the shadow
281      * @param {Number} c The blur size of the shadow or The opacity of the shadow (0 to 1)
282      * @param {null | Number} d Null or The blur size of the shadow
283      * @example
284      *   old:
285      *     labelttf.enableShadow(shadowOffsetX, shadowOffsetY, shadowOpacity, shadowBlur);
286      *   new:
287      *     labelttf.enableShadow(shadowColor, offset, blurRadius);
288      */
289     enableShadow: function (a, b, c, d) {
290         if (a.r != null && a.g != null && a.b != null && a.a != null) {
291             this._enableShadow(a, b, c);
292         } else {
293             this._enableShadowNoneColor(a, b, c, d)
294         }
295     },
296 
297     _enableShadowNoneColor: function (shadowOffsetX, shadowOffsetY, shadowOpacity, shadowBlur) {
298         shadowOpacity = shadowOpacity || 0.5;
299         if (false === this._shadowEnabled)
300             this._shadowEnabled = true;
301 
302         var locShadowOffset = this._shadowOffset;
303         if (locShadowOffset && (locShadowOffset.x !== shadowOffsetX) || (locShadowOffset._y !== shadowOffsetY)) {
304             locShadowOffset.x = shadowOffsetX;
305             locShadowOffset.y = shadowOffsetY;
306         }
307 
308         if (this._shadowOpacity !== shadowOpacity) {
309             this._shadowOpacity = shadowOpacity;
310         }
311         this._renderCmd._setColorsString();
312 
313         if (this._shadowBlur !== shadowBlur)
314             this._shadowBlur = shadowBlur;
315         this._setUpdateTextureDirty();
316     },
317 
318     _enableShadow: function (shadowColor, offset, blurRadius) {
319         if (!this._shadowColor) {
320             this._shadowColor = cc.color(255, 255, 255, 128);
321         }
322         this._shadowColor.r = shadowColor.r;
323         this._shadowColor.g = shadowColor.g;
324         this._shadowColor.b = shadowColor.b;
325 
326         var x, y, a, b;
327         x = offset.width || offset.x || 0;
328         y = offset.height || offset.y || 0;
329         a = (shadowColor.a != null) ? (shadowColor.a / 255) : 0.5;
330         b = blurRadius;
331 
332         this._enableShadowNoneColor(x, y, a, b);
333     },
334 
335     _getShadowOffsetX: function () {
336         return this._shadowOffset.x;
337     },
338     _setShadowOffsetX: function (x) {
339         if (false === this._shadowEnabled)
340             this._shadowEnabled = true;
341 
342         if (this._shadowOffset.x !== x) {
343             this._shadowOffset.x = x;
344             this._setUpdateTextureDirty();
345         }
346     },
347 
348     _getShadowOffsetY: function () {
349         return this._shadowOffset._y;
350     },
351     _setShadowOffsetY: function (y) {
352         if (false === this._shadowEnabled)
353             this._shadowEnabled = true;
354 
355         if (this._shadowOffset._y !== y) {
356             this._shadowOffset._y = y;
357             this._setUpdateTextureDirty();
358         }
359     },
360 
361     _getShadowOffset: function () {
362         return cc.p(this._shadowOffset.x, this._shadowOffset.y);
363     },
364     _setShadowOffset: function (offset) {
365         if (false === this._shadowEnabled)
366             this._shadowEnabled = true;
367 
368         if (this._shadowOffset.x !== offset.x || this._shadowOffset.y !== offset.y) {
369             this._shadowOffset.x = offset.x;
370             this._shadowOffset.y = offset.y;
371             this._setUpdateTextureDirty();
372         }
373     },
374 
375     _getShadowOpacity: function () {
376         return this._shadowOpacity;
377     },
378     _setShadowOpacity: function (shadowOpacity) {
379         if (false === this._shadowEnabled)
380             this._shadowEnabled = true;
381 
382         if (this._shadowOpacity !== shadowOpacity) {
383             this._shadowOpacity = shadowOpacity;
384             this._renderCmd._setColorsString();
385             this._setUpdateTextureDirty();
386         }
387     },
388 
389     _getShadowBlur: function () {
390         return this._shadowBlur;
391     },
392     _setShadowBlur: function (shadowBlur) {
393         if (false === this._shadowEnabled)
394             this._shadowEnabled = true;
395 
396         if (this._shadowBlur !== shadowBlur) {
397             this._shadowBlur = shadowBlur;
398             this._setUpdateTextureDirty();
399         }
400     },
401 
402     /**
403      * Disable shadow rendering
404      */
405     disableShadow: function () {
406         if (this._shadowEnabled) {
407             this._shadowEnabled = false;
408             this._setUpdateTextureDirty();
409         }
410     },
411 
412     /**
413      * Enable label stroke with stroke parameters
414      * @param {cc.Color} strokeColor The color of stroke
415      * @param {Number} strokeSize The size of stroke
416      */
417     enableStroke: function (strokeColor, strokeSize) {
418         if (this._strokeEnabled === false)
419             this._strokeEnabled = true;
420 
421         var locStrokeColor = this._strokeColor;
422         if ((locStrokeColor.r !== strokeColor.r) || (locStrokeColor.g !== strokeColor.g) || (locStrokeColor.b !== strokeColor.b)) {
423             locStrokeColor.r = strokeColor.r;
424             locStrokeColor.g = strokeColor.g;
425             locStrokeColor.b = strokeColor.b;
426             this._renderCmd._setColorsString();
427         }
428 
429         if (this._strokeSize !== strokeSize)
430             this._strokeSize = strokeSize || 0;
431         this._setUpdateTextureDirty();
432     },
433 
434     _getStrokeStyle: function () {
435         return this._strokeColor;
436     },
437     _setStrokeStyle: function (strokeStyle) {
438         if (this._strokeEnabled === false)
439             this._strokeEnabled = true;
440 
441         var locStrokeColor = this._strokeColor;
442         if ((locStrokeColor.r !== strokeStyle.r) || (locStrokeColor.g !== strokeStyle.g) || (locStrokeColor.b !== strokeStyle.b)) {
443             locStrokeColor.r = strokeStyle.r;
444             locStrokeColor.g = strokeStyle.g;
445             locStrokeColor.b = strokeStyle.b;
446             this._renderCmd._setColorsString();
447             this._setUpdateTextureDirty();
448         }
449     },
450 
451     _getLineWidth: function () {
452         return this._strokeSize;
453     },
454     _setLineWidth: function (lineWidth) {
455         if (this._strokeEnabled === false)
456             this._strokeEnabled = true;
457         if (this._strokeSize !== lineWidth) {
458             this._strokeSize = lineWidth || 0;
459             this._setUpdateTextureDirty();
460         }
461     },
462 
463     /**
464      * Disable label stroke
465      */
466     disableStroke: function () {
467         if (this._strokeEnabled) {
468             this._strokeEnabled = false;
469             this._setUpdateTextureDirty();
470         }
471     },
472 
473     /**
474      * Sets the text fill color
475      * @function
476      * @param {cc.Color} fillColor The fill color of the label
477      */
478     setFontFillColor: function (fillColor) {
479         var locTextFillColor = this._textFillColor;
480         if (locTextFillColor.r !== fillColor.r || locTextFillColor.g !== fillColor.g || locTextFillColor.b !== fillColor.b) {
481             locTextFillColor.r = fillColor.r;
482             locTextFillColor.g = fillColor.g;
483             locTextFillColor.b = fillColor.b;
484             this._renderCmd._setColorsString();
485             this._needUpdateTexture = true;
486         }
487     },
488 
489     _getFillStyle: function () {
490         return this._textFillColor;
491     },
492 
493     //set the text definition for this label
494     _updateWithTextDefinition: function (textDefinition, mustUpdateTexture) {
495         if (textDefinition.fontDimensions) {
496             this._dimensions.width = textDefinition.boundingWidth;
497             this._dimensions.height = textDefinition.boundingHeight;
498         } else {
499             this._dimensions.width = 0;
500             this._dimensions.height = 0;
501         }
502 
503         this._hAlignment = textDefinition.textAlign;
504         this._vAlignment = textDefinition.verticalAlign;
505 
506         this._fontName = textDefinition.fontName;
507         this._fontSize = textDefinition.fontSize || 12;
508 
509         if(textDefinition.lineHeight)
510             this._lineHeight = textDefinition.lineHeight
511         else
512             this._lineHeight = this._fontSize;
513 
514         this._renderCmd._setFontStyle(textDefinition);
515 
516 
517         // shadow
518         if (textDefinition.shadowEnabled)
519             this.enableShadow(textDefinition.shadowOffsetX,
520                 textDefinition.shadowOffsetY,
521                 textDefinition.shadowOpacity,
522                 textDefinition.shadowBlur);
523 
524         // stroke
525         if (textDefinition.strokeEnabled)
526             this.enableStroke(textDefinition.strokeStyle, textDefinition.lineWidth);
527 
528         // fill color
529         this.setFontFillColor(textDefinition.fillStyle);
530 
531         if (mustUpdateTexture)
532             this._renderCmd._updateTexture();
533         var flags = cc.Node._dirtyFlags;
534         this._renderCmd.setDirtyFlag(flags.colorDirty|flags.opacityDirty|flags.textDirty);
535     },
536 
537     _prepareTextDefinition: function (adjustForResolution) {
538         var texDef = new cc.FontDefinition();
539 
540         if (adjustForResolution) {
541             texDef.fontSize = this._fontSize;
542             texDef.boundingWidth = cc.contentScaleFactor() * this._dimensions.width;
543             texDef.boundingHeight = cc.contentScaleFactor() * this._dimensions.height;
544         } else {
545             texDef.fontSize = this._fontSize;
546             texDef.boundingWidth = this._dimensions.width;
547             texDef.boundingHeight = this._dimensions.height;
548         }
549 
550         texDef.fontName = this._fontName;
551         texDef.textAlign = this._hAlignment;
552         texDef.verticalAlign = this._vAlignment;
553 
554         // stroke
555         if (this._strokeEnabled) {
556             texDef.strokeEnabled = true;
557             var locStrokeColor = this._strokeColor;
558             texDef.strokeStyle = cc.color(locStrokeColor.r, locStrokeColor.g, locStrokeColor.b);
559             texDef.lineWidth = this._strokeSize;
560         } else
561             texDef.strokeEnabled = false;
562 
563         // shadow
564         if (this._shadowEnabled) {
565             texDef.shadowEnabled = true;
566             texDef.shadowBlur = this._shadowBlur;
567             texDef.shadowOpacity = this._shadowOpacity;
568 
569             texDef.shadowOffsetX = (adjustForResolution ? cc.contentScaleFactor() : 1) * this._shadowOffset.x;
570             texDef.shadowOffsetY = (adjustForResolution ? cc.contentScaleFactor() : 1) * this._shadowOffset.y;
571         } else
572             texDef._shadowEnabled = false;
573 
574         // text tint
575         var locTextFillColor = this._textFillColor;
576         texDef.fillStyle = cc.color(locTextFillColor.r, locTextFillColor.g, locTextFillColor.b);
577         return texDef;
578     },
579 
580     /**
581      * Changes the text content of the label
582      * @warning Changing the string is as expensive as creating a new cc.LabelTTF. To obtain better performance use cc.LabelAtlas
583      * @param {String} text Text content for the label
584      */
585     setString: function (text) {
586         text = String(text);
587         if (this._originalText !== text) {
588             this._originalText = text + "";
589 
590             this._updateString();
591 
592             // Force update
593             this._setUpdateTextureDirty();
594             this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
595         }
596     },
597     _updateString: function () {
598         if ((!this._string || this._string === "") && this._string !== this._originalText)
599             cc.renderer.childrenOrderDirty = true;
600         this._string = this._originalText;
601     },
602 
603     /**
604      * Sets Horizontal Alignment of cc.LabelTTF
605      * @param {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT} alignment Horizontal Alignment
606      */
607     setHorizontalAlignment: function (alignment) {
608         if (alignment !== this._hAlignment) {
609             this._hAlignment = alignment;
610             // Force update
611             this._setUpdateTextureDirty();
612         }
613     },
614 
615     /**
616      * Sets Vertical Alignment of cc.LabelTTF
617      * @param {cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM} verticalAlignment
618      */
619     setVerticalAlignment: function (verticalAlignment) {
620         if (verticalAlignment !== this._vAlignment) {
621             this._vAlignment = verticalAlignment;
622 
623             // Force update
624             this._setUpdateTextureDirty();
625         }
626     },
627 
628     /**
629      * Set Dimensions of cc.LabelTTF, the dimension is the maximum size of the label, set it so that label will automatically change lines when necessary.
630      * @param {cc.Size|Number} dim dimensions or width of dimensions
631      * @param {Number} [height] height of dimensions
632      */
633     setDimensions: function (dim, height) {
634         var width;
635         if (height === undefined) {
636             width = dim.width;
637             height = dim.height;
638         } else
639             width = dim;
640 
641         if (width !== this._dimensions.width || height !== this._dimensions.height) {
642             this._dimensions.width = width;
643             this._dimensions.height = height;
644             this._updateString();
645             // Force update
646             this._setUpdateTextureDirty();
647         }
648     },
649 
650     _getBoundingWidth: function () {
651         return this._dimensions.width;
652     },
653     _setBoundingWidth: function (width) {
654         if (width !== this._dimensions.width) {
655             this._dimensions.width = width;
656             this._updateString();
657             // Force update
658             this._setUpdateTextureDirty();
659         }
660     },
661 
662     _getBoundingHeight: function () {
663         return this._dimensions.height;
664     },
665     _setBoundingHeight: function (height) {
666         if (height !== this._dimensions.height) {
667             this._dimensions.height = height;
668             this._updateString();
669             // Force update
670             this._setUpdateTextureDirty();
671         }
672     },
673 
674     /**
675      * Sets font size of cc.LabelTTF
676      * @param {Number} fontSize
677      */
678     setFontSize: function (fontSize) {
679         if (this._fontSize !== fontSize) {
680             this._fontSize = fontSize;
681             this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight);
682             // Force update
683             this._setUpdateTextureDirty();
684         }
685     },
686 
687     /**
688      * Sets font name of cc.LabelTTF
689      * @param {String} fontName
690      */
691     setFontName: function (fontName) {
692         if (this._fontName && this._fontName !== fontName) {
693             this._fontName = fontName;
694             this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight);
695             // Force update
696             this._setUpdateTextureDirty();
697         }
698     },
699 
700     _getFont: function () {
701         return this._renderCmd._getFontStyle();
702     },
703     _setFont: function (fontStyle) {
704         var res = cc.LabelTTF._fontStyleRE.exec(fontStyle);
705         if (res) {
706             this._fontSize = parseInt(res[1]);
707             this._fontName = res[2];
708             this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight);
709 
710             // Force update
711             this._setUpdateTextureDirty();
712         }
713     },
714 
715     /**
716      * Returns the actual content size of the label, the content size is the real size that the label occupied while dimension is the outer bounding box of the label.
717      * @returns {cc.Size} The content size
718      */
719     getContentSize: function () {
720         if (this._needUpdateTexture)
721             this._renderCmd._updateTTF();
722         return cc.Sprite.prototype.getContentSize.call(this);
723     },
724 
725     _getWidth: function () {
726         if (this._needUpdateTexture)
727             this._renderCmd._updateTTF();
728         return cc.Sprite.prototype._getWidth.call(this);
729     },
730     _getHeight: function () {
731         if (this._needUpdateTexture)
732             this._renderCmd._updateTTF();
733         return cc.Sprite.prototype._getHeight.call(this);
734     },
735 
736     setTextureRect: function (rect, rotated, untrimmedSize) {
737         //set needConvert to false
738         cc.Sprite.prototype.setTextureRect.call(this, rect, rotated, untrimmedSize, false);
739     },
740 
741     _createRenderCmd: function () {
742         if (cc._renderType === cc._RENDER_TYPE_CANVAS)
743             return new cc.LabelTTF.CanvasRenderCmd(this);
744         else
745             return new cc.LabelTTF.WebGLRenderCmd(this);
746     },
747 
748     //For web only
749     _setFontStyle: function(fontStyle){
750         if (this._fontStyle !== fontStyle) {
751             this._fontStyle = fontStyle;
752             this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight);
753             this._setUpdateTextureDirty();
754         }
755     },
756 
757     _getFontStyle: function(){
758         return this._fontStyle;
759     },
760 
761     _setFontWeight: function(fontWeight){
762         if (this._fontWeight !== fontWeight) {
763             this._fontWeight = fontWeight;
764             this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight);
765             this._setUpdateTextureDirty();
766         }
767     },
768 
769     _getFontWeight: function(){
770         return this._fontWeight;
771     }
772 });
773 
774 cc.assert(cc.isFunction(cc._tmp.PrototypeLabelTTF), cc._LogInfos.MissingFile, "LabelTTFPropertyDefine.js");
775 cc._tmp.PrototypeLabelTTF();
776 delete cc._tmp.PrototypeLabelTTF;
777 
778 // Only support style in this format: "18px Verdana" or "18px 'Helvetica Neue'"
779 cc.LabelTTF._fontStyleRE = /^(\d+)px\s+['"]?([\w\s\d]+)['"]?$/;
780 
781 /**
782  * creates a cc.LabelTTF from a font name, alignment, dimension and font size
783  * @deprecated since v3.0, please use the new construction instead
784  * @see cc.LabelTTF
785  * @static
786  * @param {String} text
787  * @param {String|cc.FontDefinition} [fontName="Arial"]
788  * @param {Number} [fontSize=16]
789  * @param {cc.Size} [dimensions=cc.size(0,0)]
790  * @param {Number} [hAlignment=cc.TEXT_ALIGNMENT_LEFT]
791  * @param {Number} [vAlignment=cc.VERTICAL_TEXT_ALIGNMENT_TOP]
792  * @return {cc.LabelTTF|Null}
793  */
794 cc.LabelTTF.create = function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) {
795     return new cc.LabelTTF(text, fontName, fontSize, dimensions, hAlignment, vAlignment);
796 };
797 
798 /**
799  * @deprecated since v3.0, please use the new construction instead
800  * @function
801  * @static
802  */
803 cc.LabelTTF.createWithFontDefinition = cc.LabelTTF.create;
804 
805 if (cc.USE_LA88_LABELS)
806     cc.LabelTTF._SHADER_PROGRAM = cc.SHADER_POSITION_TEXTURECOLOR;
807 else
808     cc.LabelTTF._SHADER_PROGRAM = cc.SHADER_POSITION_TEXTUREA8COLOR;
809 
810 cc.LabelTTF.__labelHeightDiv = cc.newElement("div");
811 cc.LabelTTF.__labelHeightDiv.style.fontFamily = "Arial";
812 cc.LabelTTF.__labelHeightDiv.style.position = "absolute";
813 cc.LabelTTF.__labelHeightDiv.style.left = "-100px";
814 cc.LabelTTF.__labelHeightDiv.style.top = "-100px";
815 cc.LabelTTF.__labelHeightDiv.style.lineHeight = "normal";
816 
817 document.body ?
818     document.body.appendChild(cc.LabelTTF.__labelHeightDiv) :
819     cc._addEventListener(window, 'load', function () {
820         this.removeEventListener('load', arguments.callee, false);
821         document.body.appendChild(cc.LabelTTF.__labelHeightDiv);
822     }, false);
823 
824 cc.LabelTTF.__getFontHeightByDiv = function (fontName, fontSize) {
825 
826     if(fontName instanceof cc.FontDefinition){
827         /** @type cc.FontDefinition */
828         var fontDef = fontName;
829         var clientHeight = cc.LabelTTF.__fontHeightCache[fontDef._getCanvasFontStr()];
830         if (clientHeight > 0) return clientHeight;
831         var labelDiv = cc.LabelTTF.__labelHeightDiv;
832         labelDiv.innerHTML = "ajghl~!";
833         labelDiv.style.fontFamily = fontDef.fontName;
834         labelDiv.style.fontSize = fontDef.fontSize + "px";
835         labelDiv.style.fontStyle = fontDef.fontStyle;
836         labelDiv.style.fontWeight = fontDef.fontWeight;
837 
838         clientHeight = labelDiv.clientHeight;
839         cc.LabelTTF.__fontHeightCache[fontDef._getCanvasFontStr()] = clientHeight;
840         labelDiv.innerHTML = "";
841         return clientHeight;
842     }
843 
844     //Default
845     var clientHeight = cc.LabelTTF.__fontHeightCache[fontName + "." + fontSize];
846     if (clientHeight > 0) return clientHeight;
847     var labelDiv = cc.LabelTTF.__labelHeightDiv;
848     labelDiv.innerHTML = "ajghl~!";
849     labelDiv.style.fontFamily = fontName;
850     labelDiv.style.fontSize = fontSize + "px";
851     clientHeight = labelDiv.clientHeight;
852     cc.LabelTTF.__fontHeightCache[fontName + "." + fontSize] = clientHeight;
853     labelDiv.innerHTML = "";
854     return clientHeight;
855 
856 };
857 
858 cc.LabelTTF.__fontHeightCache = {};