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