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  * 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      * creates a cc.LabelTTF from a font name, alignment, dimension and font size
 91      * Constructor of cc.LabelTTF
 92      * @param {String} text
 93      * @param {String|cc.FontDefinition} [fontName="Arial"]
 94      * @param {Number} [fontSize=16]
 95      * @param {cc.Size} [dimensions=cc.size(0,0)]
 96      * @param {Number} [hAlignment=cc.TEXT_ALIGNMENT_LEFT]
 97      * @param {Number} [vAlignment=cc.VERTICAL_TEXT_ALIGNMENT_TOP]
 98      * @example
 99      * var myLabel = new cc.LabelTTF('label text',  'Times New Roman', 32, cc.size(320,32), cc.TEXT_ALIGNMENT_LEFT);
100      *
101      * var fontDef = new cc.FontDefinition();
102      * fontDef.fontName = "Arial";
103      * fontDef.fontSize = "32";
104      * var myLabel = new cc.LabelTTF('label text',  fontDef);
105      */
106     ctor: function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) {
107         cc.Sprite.prototype.ctor.call(this);
108 
109         this._dimensions = cc.size(0, 0);
110         this._hAlignment = cc.TEXT_ALIGNMENT_LEFT;
111         this._vAlignment = cc.VERTICAL_TEXT_ALIGNMENT_TOP;
112         this._opacityModifyRGB = false;
113         this._fontStyleStr = "";
114         this._fontName = "Arial";
115         this._isMultiLine = false;
116 
117         this._shadowEnabled = false;
118         this._shadowOffset = cc.p(0, 0);
119         this._shadowOpacity = 0;
120         this._shadowBlur = 0;
121         this._shadowColorStr = "rgba(128, 128, 128, 0.5)";
122 
123         this._strokeEnabled = false;
124         this._strokeColor = cc.color(255, 255, 255, 255);
125         this._strokeSize = 0;
126         this._strokeColorStr = "";
127 
128         this._textFillColor = cc.color(255, 255, 255, 255);
129         this._fillColorStr = "rgba(255,255,255,1)";
130         this._strokeShadowOffsetX = 0;
131         this._strokeShadowOffsetY = 0;
132         this._needUpdateTexture = false;
133 
134         this._lineWidths = [];
135 
136         this._setColorsString();
137 
138         if (fontName && fontName instanceof cc.FontDefinition) {
139             this.initWithStringAndTextDefinition(text, fontName);
140         }
141         else {
142             cc.LabelTTF.prototype.initWithString.call(this, text, fontName, fontSize, dimensions, hAlignment, vAlignment);
143         }
144     },
145 
146     init: function () {
147         return this.initWithString(" ", this._fontName, this._fontSize);
148     },
149 
150     _measureConfig: function () {
151         this._getLabelContext().font = this._fontStyleStr;
152     },
153     _measure: function (text) {
154         return this._getLabelContext().measureText(text).width;
155     },
156 
157     /**
158      * Prints out a description of this class
159      * @return {String}
160      */
161     description: function () {
162         return "<cc.LabelTTF | FontName =" + this._fontName + " FontSize = " + this._fontSize.toFixed(1) + ">";
163     },
164 
165     setColor: null,
166 
167     _setColorsString: null,
168 
169     updateDisplayedColor: null,
170     setOpacity: null,
171 
172     updateDisplayedOpacity: null,
173     updateDisplayedOpacityForCanvas: function (parentOpacity) {
174         cc.Node.prototype.updateDisplayedOpacity.call(this, parentOpacity);
175         this._setColorsString();
176     },
177 
178     /**
179      * returns the text of the label
180      * @return {String}
181      */
182     getString: function () {
183         return this._string;
184     },
185 
186     /**
187      * return Horizontal Alignment of cc.LabelTTF
188      * @return {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT}
189      */
190     getHorizontalAlignment: function () {
191         return this._hAlignment;
192     },
193 
194     /**
195      * return Vertical Alignment of cc.LabelTTF
196      * @return {cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM}
197      */
198     getVerticalAlignment: function () {
199         return this._vAlignment;
200     },
201 
202     /**
203      * return Dimensions of cc.LabelTTF
204      * @return {cc.Size}
205      */
206     getDimensions: function () {
207         return cc.size(this._dimensions);
208     },
209 
210     /**
211      * return font size of cc.LabelTTF
212      * @return {Number}
213      */
214     getFontSize: function () {
215         return this._fontSize;
216     },
217 
218     /**
219      * return font name of cc.LabelTTF
220      * @return {String}
221      */
222     getFontName: function () {
223         return this._fontName;
224     },
225 
226     /**
227      * initializes the cc.LabelTTF with a font name, alignment, dimension and font size
228      * @param {String} label string
229      * @param {String} fontName
230      * @param {Number} fontSize
231      * @param {cc.Size} [dimensions=]
232      * @param {Number} [hAlignment=]
233      * @param {Number} [vAlignment=]
234      * @return {Boolean} return false on error
235      */
236     initWithString: function (label, fontName, fontSize, dimensions, hAlignment, vAlignment) {
237         var strInfo;
238         if (label)
239             strInfo = label + "";
240         else
241             strInfo = "";
242 
243         fontSize = fontSize || 16;
244         dimensions = dimensions || cc.size(0, fontSize);
245         hAlignment = hAlignment || cc.TEXT_ALIGNMENT_LEFT;
246         vAlignment = vAlignment || cc.VERTICAL_TEXT_ALIGNMENT_TOP;
247 
248         this._opacityModifyRGB = false;
249         this._dimensions = cc.size(dimensions.width, dimensions.height);
250         this._fontName = fontName || "Arial";
251         this._hAlignment = hAlignment;
252         this._vAlignment = vAlignment;
253 
254         //this._fontSize = (cc._renderType === cc._RENDER_TYPE_CANVAS) ? fontSize : fontSize * cc.contentScaleFactor();
255         this._fontSize = fontSize;
256         this._fontStyleStr = this._fontSize + "px '" + fontName + "'";
257         this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(fontName, this._fontSize);
258         this.string = strInfo;
259         this._setColorsString();
260         this._updateTexture();
261         this._needUpdateTexture = false;
262         return true;
263     },
264 
265     /**
266      * initializes the CCLabelTTF with a font name, alignment, dimension and font size
267      * @param {String} text
268      * @param {cc.FontDefinition} textDefinition
269      * @return {Boolean}
270      */
271     initWithStringAndTextDefinition: null,
272 
273     /**
274      * set the text definition used by this label
275      * @param {cc.FontDefinition} theDefinition
276      */
277     setTextDefinition: function (theDefinition) {
278         if (theDefinition)
279             this._updateWithTextDefinition(theDefinition, true);
280     },
281 
282     /**
283      * get the text definition used by this label
284      * @return {cc.FontDefinition}
285      */
286     getTextDefinition: function () {
287         return this._prepareTextDefinition(false);
288     },
289 
290     /**
291      * enable or disable shadow for the label
292      * @param {cc.Point} shadowOffset
293      * @param {Number} shadowOpacity (0 to 1)
294      * @param {Number} shadowBlur
295      */
296     enableShadow: function (shadowOffsetX, shadowOffsetY, shadowOpacity, shadowBlur) {
297         shadowOpacity = shadowOpacity || 0.5;
298         if (false === this._shadowEnabled)
299             this._shadowEnabled = true;
300 
301         var locShadowOffset = this._shadowOffset;
302         if (locShadowOffset && (locShadowOffset.x != shadowOffsetX) || (locShadowOffset._y != shadowOffsetY)) {
303             locShadowOffset.x = shadowOffsetX;
304             locShadowOffset.y = shadowOffsetY;
305         }
306 
307         if (this._shadowOpacity != shadowOpacity) {
308             this._shadowOpacity = shadowOpacity;
309         }
310         this._setColorsString();
311 
312         if (this._shadowBlur != shadowBlur)
313             this._shadowBlur = shadowBlur;
314 
315         this._needUpdateTexture = true;
316     },
317 
318     _getShadowOffsetX: function () {
319         return this._shadowOffset.x;
320     },
321     _setShadowOffsetX: function (x) {
322         if (false === this._shadowEnabled)
323             this._shadowEnabled = true;
324 
325         if (this._shadowOffset.x != x) {
326             this._shadowOffset.x = x;
327             this._needUpdateTexture = true;
328         }
329     },
330 
331     _getShadowOffsetY: function () {
332         return this._shadowOffset._y;
333     },
334     _setShadowOffsetY: function (y) {
335         if (false === this._shadowEnabled)
336             this._shadowEnabled = true;
337 
338         if (this._shadowOffset._y != y) {
339             this._shadowOffset._y = y;
340             this._needUpdateTexture = true;
341         }
342     },
343 
344     _getShadowOffset: function () {
345         return cc.p(this._shadowOffset.x, this._shadowOffset.y);
346     },
347     _setShadowOffset: function (offset) {
348         if (false === this._shadowEnabled)
349             this._shadowEnabled = true;
350 
351         if (this._shadowOffset.x != offset.x || this._shadowOffset.y != offset.y) {
352             this._shadowOffset.x = offset.x;
353             this._shadowOffset.y = offset.y;
354             this._needUpdateTexture = true;
355         }
356     },
357 
358     _getShadowOpacity: function () {
359         return this._shadowOpacity;
360     },
361     _setShadowOpacity: function (shadowOpacity) {
362         if (false === this._shadowEnabled)
363             this._shadowEnabled = true;
364 
365         if (this._shadowOpacity != shadowOpacity) {
366             this._shadowOpacity = shadowOpacity;
367             this._setColorsString();
368             this._needUpdateTexture = true;
369         }
370     },
371 
372     _getShadowBlur: function () {
373         return this._shadowBlur;
374     },
375     _setShadowBlur: function (shadowBlur) {
376         if (false === this._shadowEnabled)
377             this._shadowEnabled = true;
378 
379         if (this._shadowBlur != shadowBlur) {
380             this._shadowBlur = shadowBlur;
381             this._needUpdateTexture = true;
382         }
383     },
384 
385     /**
386      * disable shadow rendering
387      */
388     disableShadow: function () {
389         if (this._shadowEnabled) {
390             this._shadowEnabled = false;
391             this._needUpdateTexture = true;
392         }
393     },
394 
395     /**
396      * enable or disable stroke
397      * @param {cc.Color} strokeColor
398      * @param {Number} strokeSize
399      */
400     enableStroke: function (strokeColor, strokeSize) {
401         if (this._strokeEnabled === false)
402             this._strokeEnabled = true;
403 
404         var locStrokeColor = this._strokeColor;
405         if ((locStrokeColor.r !== strokeColor.r) || (locStrokeColor.g !== strokeColor.g) || (locStrokeColor.b !== strokeColor.b)) {
406             locStrokeColor.r = strokeColor.r;
407             locStrokeColor.g = strokeColor.g;
408             locStrokeColor.b = strokeColor.b;
409             this._setColorsString();
410         }
411 
412         if (this._strokeSize !== strokeSize)
413             this._strokeSize = strokeSize || 0;
414 
415         this._needUpdateTexture = true;
416     },
417 
418     _getStrokeStyle: function () {
419         return this._strokeColor;
420     },
421     _setStrokeStyle: function (strokeStyle) {
422         if (this._strokeEnabled === false)
423             this._strokeEnabled = true;
424 
425         var locStrokeColor = this._strokeColor;
426         if ((locStrokeColor.r !== strokeStyle.r) || (locStrokeColor.g !== strokeStyle.g) || (locStrokeColor.b !== strokeStyle.b)) {
427             locStrokeColor.r = strokeStyle.r;
428             locStrokeColor.g = strokeStyle.g;
429             locStrokeColor.b = strokeStyle.b;
430             this._setColorsString();
431 
432             this._needUpdateTexture = true;
433         }
434     },
435 
436     _getLineWidth: function () {
437         return this._strokeSize;
438     },
439     _setLineWidth: function (lineWidth) {
440         if (this._strokeEnabled === false)
441             this._strokeEnabled = true;
442 
443         if (this._strokeSize !== lineWidth) {
444             this._strokeSize = lineWidth || 0;
445             this._needUpdateTexture = true;
446         }
447     },
448 
449     /**
450      * disable stroke
451      */
452     disableStroke: function () {
453         if (this._strokeEnabled) {
454             this._strokeEnabled = false;
455             this._needUpdateTexture = true;
456         }
457     },
458 
459     /**
460      * set text tinting
461      * @function
462      * @param {cc.Color} tintColor
463      */
464     setFontFillColor: null,
465 
466     _getFillStyle: function () {
467         return this._textFillColor;
468     },
469 
470     //set the text definition for this label
471     _updateWithTextDefinition: function (textDefinition, mustUpdateTexture) {
472         if (textDefinition.fontDimensions) {
473             this._dimensions.width = textDefinition.boundingWidth;
474             this._dimensions.height = textDefinition.boundingHeight;
475         } else {
476             this._dimensions.width = 0;
477             this._dimensions.height = 0;
478         }
479 
480         this._hAlignment = textDefinition.textAlign;
481         this._vAlignment = textDefinition.verticalAlign;
482 
483         this._fontName = textDefinition.fontName;
484         this._fontSize = textDefinition.fontSize || 12;
485         this._fontStyleStr = this._fontSize + "px '" + this._fontName + "'";
486         this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(this._fontName, this._fontSize);
487 
488         // shadow
489         if (textDefinition.shadowEnabled)
490             this.enableShadow(textDefinition.shadowOffsetX,
491                 textDefinition.shadowOffsetY,
492                 textDefinition.shadowOpacity,
493                 textDefinition.shadowBlur);
494 
495         // stroke
496         if (textDefinition.strokeEnabled)
497             this.enableStroke(textDefinition.strokeStyle, textDefinition.lineWidth);
498 
499         // fill color
500         this.setFontFillColor(textDefinition.fillStyle);
501 
502         if (mustUpdateTexture)
503             this._updateTexture();
504     },
505 
506     _prepareTextDefinition: function (adjustForResolution) {
507         var texDef = new cc.FontDefinition();
508 
509         if (adjustForResolution) {
510             //texDef.fontSize = (cc._renderType === cc._RENDER_TYPE_CANVAS) ? this._fontSize : this._fontSize * cc.contentScaleFactor();
511             texDef.fontSize = this._fontSize;
512             texDef.boundingWidth = cc.contentScaleFactor() * this._dimensions.width;
513             texDef.boundingHeight = cc.contentScaleFactor() * this._dimensions.height;
514         } else {
515             texDef.fontSize = this._fontSize;
516             texDef.boundingWidth = this._dimensions.width;
517             texDef.boundingHeight = this._dimensions.height;
518         }
519 
520         texDef.fontName = this._fontName;
521         texDef.textAlign = this._hAlignment;
522         texDef.verticalAlign = this._vAlignment;
523 
524         // stroke
525         if (this._strokeEnabled) {
526             texDef.strokeEnabled = true;
527             var locStrokeColor = this._strokeColor;
528             texDef.strokeStyle = cc.color(locStrokeColor.r, locStrokeColor.g, locStrokeColor.b);
529             texDef.lineWidth = this._strokeSize;
530         } else
531             texDef.strokeEnabled = false;
532 
533         // shadow
534         if (this._shadowEnabled) {
535             texDef.shadowEnabled = true;
536             texDef.shadowBlur = this._shadowBlur;
537             texDef.shadowOpacity = this._shadowOpacity;
538 
539             texDef.shadowOffsetX = (adjustForResolution ? cc.contentScaleFactor() : 1) * this._shadowOffset.x;
540             texDef.shadowOffsetY = (adjustForResolution ? cc.contentScaleFactor() : 1) * this._shadowOffset.y;
541         } else
542             texDef._shadowEnabled = false;
543 
544         // text tint
545         var locTextFillColor = this._textFillColor;
546         texDef.fillStyle = cc.color(locTextFillColor.r, locTextFillColor.g, locTextFillColor.b);
547         return texDef;
548     },
549 
550     _fontClientHeight: 18,
551     /**
552      * changes the string to render
553      * @warning Changing the string is as expensive as creating a new cc.LabelTTF. To obtain better performance use cc.LabelAtlas
554      * @param {String} text text for the label
555      */
556     setString: function (text) {
557         text = String(text);
558         if (this._originalText != text) {
559             this._originalText = text + "";
560 
561             this._updateString();
562 
563             // Force update
564             this._needUpdateTexture = true;
565         }
566     },
567     _updateString: function () {
568         this._string = this._originalText;
569     },
570     /**
571      * set Horizontal Alignment of cc.LabelTTF
572      * @param {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT} alignment Horizontal Alignment
573      */
574     setHorizontalAlignment: function (alignment) {
575         if (alignment !== this._hAlignment) {
576             this._hAlignment = alignment;
577 
578             // Force update
579             this._needUpdateTexture = true;
580         }
581     },
582 
583     /**
584      * set Vertical Alignment of cc.LabelTTF
585      * @param {cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM} verticalAlignment
586      */
587     setVerticalAlignment: function (verticalAlignment) {
588         if (verticalAlignment != this._vAlignment) {
589             this._vAlignment = verticalAlignment;
590 
591             // Force update
592             this._needUpdateTexture = true;
593         }
594     },
595 
596     /**
597      * set Dimensions of cc.LabelTTF
598      * @param {cc.Size|Number} dim dimensions or width of dimensions
599      * @param {Number} [height] height of dimensions
600      */
601     setDimensions: function (dim, height) {
602         var width;
603         if(height === undefined){
604             width = dim.width;
605             height = dim.height;
606         }else
607             width = dim;
608 
609         if (width != this._dimensions.width || height != this._dimensions.height) {
610             this._dimensions.width = width;
611             this._dimensions.height = height;
612             this._updateString();
613             // Force udpate
614             this._needUpdateTexture = true;
615         }
616     },
617 
618     _getBoundingWidth: function () {
619         return this._dimensions.width;
620     },
621     _setBoundingWidth: function (width) {
622         if (width != this._dimensions.width) {
623             this._dimensions.width = width;
624             this._updateString();
625             // Force udpate
626             this._needUpdateTexture = true;
627         }
628     },
629 
630     _getBoundingHeight: function () {
631         return this._dimensions.height;
632     },
633     _setBoundingHeight: function (height) {
634         if (height != this._dimensions.height) {
635             this._dimensions.height = height;
636             this._updateString();
637             // Force udpate
638             this._needUpdateTexture = true;
639         }
640     },
641 
642     /**
643      * set font size of cc.LabelTTF
644      * @param {Number} fontSize
645      */
646     setFontSize: function (fontSize) {
647         if (this._fontSize !== fontSize) {
648             this._fontSize = fontSize;
649             this._fontStyleStr = fontSize + "px '" + this._fontName + "'";
650             this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(this._fontName, fontSize);
651             // Force update
652             this._needUpdateTexture = true;
653         }
654     },
655 
656     /**
657      * set font name of cc.LabelTTF
658      * @param {String} fontName
659      */
660     setFontName: function (fontName) {
661         if (this._fontName && this._fontName != fontName) {
662             this._fontName = fontName;
663             this._fontStyleStr = this._fontSize + "px '" + fontName + "'";
664             this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(fontName, this._fontSize);
665             // Force update
666             this._needUpdateTexture = true;
667         }
668     },
669 
670     _getFont: function () {
671         return this._fontStyleStr;
672     },
673     _setFont: function (fontStyle) {
674         var res = cc.LabelTTF._fontStyleRE.exec(fontStyle);
675         if (res) {
676             this._fontSize = parseInt(res[1]);
677             this._fontName = res[2];
678             this._fontStyleStr = fontStyle;
679             this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(this._fontName, this._fontSize);
680             // Force update
681             this._needUpdateTexture = true;
682         }
683     },
684 
685     _drawTTFInCanvas: function (context) {
686         if (!context)
687             return;
688         var locStrokeShadowOffsetX = this._strokeShadowOffsetX, locStrokeShadowOffsetY = this._strokeShadowOffsetY;
689         var locContentSizeHeight = this._contentSize.height - locStrokeShadowOffsetY, locVAlignment = this._vAlignment, locHAlignment = this._hAlignment,
690             locFontHeight = this._fontClientHeight, locStrokeSize = this._strokeSize;
691 
692         context.setTransform(1, 0, 0, 1, 0 + locStrokeShadowOffsetX * 0.5, locContentSizeHeight + locStrokeShadowOffsetY * 0.5);
693 
694         //this is fillText for canvas
695         if (context.font != this._fontStyleStr)
696             context.font = this._fontStyleStr;
697         context.fillStyle = this._fillColorStr;
698 
699         var xOffset = 0, yOffset = 0;
700         //stroke style setup
701         var locStrokeEnabled = this._strokeEnabled;
702         if (locStrokeEnabled) {
703             context.lineWidth = locStrokeSize * 2;
704             context.strokeStyle = this._strokeColorStr;
705         }
706 
707         //shadow style setup
708         if (this._shadowEnabled) {
709             var locShadowOffset = this._shadowOffset;
710             context.shadowColor = this._shadowColorStr;
711             context.shadowOffsetX = locShadowOffset.x;
712             context.shadowOffsetY = -locShadowOffset.y;
713             context.shadowBlur = this._shadowBlur;
714         }
715 
716         context.textBaseline = cc.LabelTTF._textBaseline[locVAlignment];
717         context.textAlign = cc.LabelTTF._textAlign[locHAlignment];
718 
719         var locContentWidth = this._contentSize.width - locStrokeShadowOffsetX;
720         if (locHAlignment === cc.TEXT_ALIGNMENT_RIGHT)
721             xOffset += locContentWidth;
722         else if (locHAlignment === cc.TEXT_ALIGNMENT_CENTER)
723             xOffset += locContentWidth / 2;
724         else
725             xOffset += 0;
726         if (this._isMultiLine) {
727             var locStrLen = this._strings.length;
728             if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM)
729                 yOffset = locFontHeight + locContentSizeHeight - locFontHeight * locStrLen;
730             else if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_CENTER)
731                 yOffset = locFontHeight / 2 + (locContentSizeHeight - locFontHeight * locStrLen) / 2;
732 
733             for (var i = 0; i < locStrLen; i++) {
734                 var line = this._strings[i];
735                 var tmpOffsetY = -locContentSizeHeight + (locFontHeight * i) + yOffset;
736                 if (locStrokeEnabled)
737                     context.strokeText(line, xOffset, tmpOffsetY);
738                 context.fillText(line, xOffset, tmpOffsetY);
739             }
740         } else {
741             if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM) {
742                 if (locStrokeEnabled)
743                     context.strokeText(this._string, xOffset, yOffset);
744                 context.fillText(this._string, xOffset, yOffset);
745             } else if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_TOP) {
746                 yOffset -= locContentSizeHeight;
747                 if (locStrokeEnabled)
748                     context.strokeText(this._string, xOffset, yOffset);
749                 context.fillText(this._string, xOffset, yOffset);
750             } else {
751                 yOffset -= locContentSizeHeight * 0.5;
752                 if (locStrokeEnabled)
753                     context.strokeText(this._string, xOffset, yOffset);
754                 context.fillText(this._string, xOffset, yOffset);
755             }
756         }
757     },
758 
759     _getLabelContext: function () {
760         if (this._labelContext)
761             return this._labelContext;
762 
763         if (!this._labelCanvas) {
764             var locCanvas = cc.newElement("canvas");
765             var labelTexture = new cc.Texture2D();
766             labelTexture.initWithElement(locCanvas);
767             this.texture = labelTexture;
768             this._labelCanvas = locCanvas;
769         }
770         this._labelContext = this._labelCanvas.getContext("2d");
771         return this._labelContext;
772     },
773 
774     _checkWarp: function(strArr, i, maxWidth){
775         var text = strArr[i];
776         var allWidth = this._measure(text);
777         if(allWidth > maxWidth && text.length > 1){
778 
779             var fuzzyLen = text.length * ( maxWidth / allWidth ) | 0;
780             var tmpText = text.substr(fuzzyLen);
781             var width = allWidth - this._measure(tmpText);
782             var sLine;
783             var pushNum = 0;
784 
785             //Increased while cycle maximum ceiling. default 100 time
786             var checkWhile = 0;
787 
788             //Exceeded the size
789             while(width > maxWidth && checkWhile++ < 100){
790                 fuzzyLen *= maxWidth / width;
791                 fuzzyLen = fuzzyLen | 0;
792                 tmpText = text.substr(fuzzyLen);
793                 width = allWidth - this._measure(tmpText);
794             }
795 
796             checkWhile = 0;
797 
798             //Find the truncation point
799             while(width < maxWidth && checkWhile++ < 100){
800 
801                 if(tmpText){
802                     var exec = cc.LabelTTF._wordRex.exec(tmpText);
803                     pushNum = exec ? exec[0].length : 1;
804                     sLine = tmpText;
805                 }
806 
807                 fuzzyLen = fuzzyLen + pushNum;
808 
809                 tmpText = text.substr(fuzzyLen);
810 
811                 width = allWidth - this._measure(tmpText);
812             }
813 
814             fuzzyLen -= pushNum;
815 
816             var sText = text.substr(0, fuzzyLen);
817 
818             //symbol in the first
819             if(cc.LabelTTF.wrapInspection){
820                 if(cc.LabelTTF._symbolRex.test(sLine || tmpText)){
821                     var result = cc.LabelTTF._lastWordRex.exec(sText);
822                     fuzzyLen -= result ? result[0].length : 0;
823 
824                     sLine = text.substr(fuzzyLen);
825                     sText = text.substr(0, fuzzyLen);
826                 }
827             }
828 
829             //To judge whether a English words are truncated
830             if(cc.LabelTTF._firsrEnglish.test(sLine)){
831                 var result = cc.LabelTTF._lastEnglish.exec(sText);
832                 if(result && sText !== result[0]){
833                     fuzzyLen -= result[0].length;
834                     sLine = text.substr(fuzzyLen);
835                     sText = text.substr(0, fuzzyLen);
836                 }
837             }
838 
839             strArr[i] = sLine || tmpText;
840             strArr.splice(i, 0, sText);
841         }
842     },
843 
844     _updateTTF: function () {
845         var locDimensionsWidth = this._dimensions.width, i, strLength;
846         var locLineWidth = this._lineWidths;
847         locLineWidth.length = 0;
848 
849         this._isMultiLine = false;
850         this._measureConfig();
851         if (locDimensionsWidth !== 0) {
852             // Content processing
853             this._strings = this._string.split('\n');
854 
855             for(i = 0; i < this._strings.length; i++){
856                 this._checkWarp(this._strings, i, locDimensionsWidth);
857             }
858         } else {
859             this._strings = this._string.split('\n');
860             for (i = 0, strLength = this._strings.length; i < strLength; i++) {
861                 locLineWidth.push(this._measure(this._strings[i]));
862             }
863         }
864 
865         if (this._strings.length > 0)
866             this._isMultiLine = true;
867 
868         var locSize, locStrokeShadowOffsetX = 0, locStrokeShadowOffsetY = 0;
869         if (this._strokeEnabled)
870             locStrokeShadowOffsetX = locStrokeShadowOffsetY = this._strokeSize * 2;
871         if (this._shadowEnabled) {
872             var locOffsetSize = this._shadowOffset;
873             locStrokeShadowOffsetX += Math.abs(locOffsetSize.x) * 2;
874             locStrokeShadowOffsetY += Math.abs(locOffsetSize.y) * 2;
875         }
876 
877         //get offset for stroke and shadow
878         if (locDimensionsWidth === 0) {
879             if (this._isMultiLine)
880                 locSize = cc.size(0 | (Math.max.apply(Math, locLineWidth) + locStrokeShadowOffsetX),
881                     0 | ((this._fontClientHeight * this._strings.length) + locStrokeShadowOffsetY));
882             else
883                 locSize = cc.size(0 | (this._measure(this._string) + locStrokeShadowOffsetX), 0 | (this._fontClientHeight + locStrokeShadowOffsetY));
884         } else {
885             if (this._dimensions.height === 0) {
886                 if (this._isMultiLine)
887                     locSize = cc.size(0 | (locDimensionsWidth + locStrokeShadowOffsetX), 0 | ((this._fontClientHeight * this._strings.length) + locStrokeShadowOffsetY));
888                 else
889                     locSize = cc.size(0 | (locDimensionsWidth + locStrokeShadowOffsetX), 0 | (this._fontClientHeight + locStrokeShadowOffsetY));
890             } else {
891                 //dimension is already set, contentSize must be same as dimension
892                 locSize = cc.size(0 | (locDimensionsWidth + locStrokeShadowOffsetX), 0 | (this._dimensions.height + locStrokeShadowOffsetY));
893             }
894         }
895         this.setContentSize(locSize);
896         this._strokeShadowOffsetX = locStrokeShadowOffsetX;
897         this._strokeShadowOffsetY = locStrokeShadowOffsetY;
898 
899         // need computing _anchorPointInPoints
900         var locAP = this._anchorPoint;
901         this._anchorPointInPoints.x = (locStrokeShadowOffsetX * 0.5) + ((locSize.width - locStrokeShadowOffsetX) * locAP.x);
902         this._anchorPointInPoints.y = (locStrokeShadowOffsetY * 0.5) + ((locSize.height - locStrokeShadowOffsetY) * locAP.y);
903     },
904 
905     getContentSize: function () {
906         if (this._needUpdateTexture)
907             this._updateTTF();
908         return cc.Sprite.prototype.getContentSize.call(this);
909     },
910 
911     _getWidth: function () {
912         if (this._needUpdateTexture)
913             this._updateTTF();
914         return cc.Sprite.prototype._getWidth.call(this);
915     },
916     _getHeight: function () {
917         if (this._needUpdateTexture)
918             this._updateTTF();
919         return cc.Sprite.prototype._getHeight.call(this);
920     },
921 
922     _updateTexture: function () {
923         var locContext = this._getLabelContext(), locLabelCanvas = this._labelCanvas;
924         var locContentSize = this._contentSize;
925 
926         if (this._string.length === 0) {
927             locLabelCanvas.width = 1;
928             locLabelCanvas.height = locContentSize.height || 1;
929             this._texture && this._texture.handleLoadedTexture();
930             this.setTextureRect(cc.rect(0, 0, 1, locContentSize.height));
931             return true;
932         }
933 
934         //set size for labelCanvas
935         locContext.font = this._fontStyleStr;
936         this._updateTTF();
937         var width = locContentSize.width, height = locContentSize.height;
938         var flag = locLabelCanvas.width == width && locLabelCanvas.height == height;
939         locLabelCanvas.width = width;
940         locLabelCanvas.height = height;
941         if (flag) locContext.clearRect(0, 0, width, height);
942 
943         //draw text to labelCanvas
944         this._drawTTFInCanvas(locContext);
945         this._texture && this._texture.handleLoadedTexture();
946 
947         this.setTextureRect(cc.rect(0, 0, width, height));
948         return true;
949     },
950 
951     visit: function (ctx) {
952         if (!this._string || this._string == "")
953             return;
954         if (this._needUpdateTexture) {
955             this._needUpdateTexture = false;
956             this._updateTexture();
957         }
958         var context = ctx || cc._renderContext;
959         cc.Sprite.prototype.visit.call(this, context);
960     },
961 
962     /**
963      * Draw sprite to canvas
964      * @function
965      * @param {CanvasRenderingContext2D|WebGLRenderingContext} ctx Render context of canvas, 2d or 3d
966      */
967     draw: null,
968 
969     _setTextureCoords: function (rect) {
970         var tex = this._batchNode ? this.textureAtlas.texture : this._texture;
971         if (!tex)
972             return;
973 
974         var atlasWidth = tex.pixelsWidth;
975         var atlasHeight = tex.pixelsHeight;
976 
977         var left, right, top, bottom, tempSwap, locQuad = this._quad;
978         if (this._rectRotated) {
979             if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
980                 left = (2 * rect.x + 1) / (2 * atlasWidth);
981                 right = left + (rect.height * 2 - 2) / (2 * atlasWidth);
982                 top = (2 * rect.y + 1) / (2 * atlasHeight);
983                 bottom = top + (rect.width * 2 - 2) / (2 * atlasHeight);
984             } else {
985                 left = rect.x / atlasWidth;
986                 right = (rect.x + rect.height) / atlasWidth;
987                 top = rect.y / atlasHeight;
988                 bottom = (rect.y + rect.width) / atlasHeight;
989             }// CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
990 
991             if (this._flippedX) {
992                 tempSwap = top;
993                 top = bottom;
994                 bottom = tempSwap;
995             }
996 
997             if (this._flippedY) {
998                 tempSwap = left;
999                 left = right;
1000                 right = tempSwap;
1001             }
1002 
1003             locQuad.bl.texCoords.u = left;
1004             locQuad.bl.texCoords.v = top;
1005             locQuad.br.texCoords.u = left;
1006             locQuad.br.texCoords.v = bottom;
1007             locQuad.tl.texCoords.u = right;
1008             locQuad.tl.texCoords.v = top;
1009             locQuad.tr.texCoords.u = right;
1010             locQuad.tr.texCoords.v = bottom;
1011         } else {
1012             if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
1013                 left = (2 * rect.x + 1) / (2 * atlasWidth);
1014                 right = left + (rect.width * 2 - 2) / (2 * atlasWidth);
1015                 top = (2 * rect.y + 1) / (2 * atlasHeight);
1016                 bottom = top + (rect.height * 2 - 2) / (2 * atlasHeight);
1017             } else {
1018                 left = rect.x / atlasWidth;
1019                 right = (rect.x + rect.width) / atlasWidth;
1020                 top = rect.y / atlasHeight;
1021                 bottom = (rect.y + rect.height) / atlasHeight;
1022             } // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
1023 
1024             if (this._flippedX) {
1025                 tempSwap = left;
1026                 left = right;
1027                 right = tempSwap;
1028             }
1029 
1030             if (this._flippedY) {
1031                 tempSwap = top;
1032                 top = bottom;
1033                 bottom = tempSwap;
1034             }
1035 
1036             locQuad.bl.texCoords.u = left;
1037             locQuad.bl.texCoords.v = bottom;
1038             locQuad.br.texCoords.u = right;
1039             locQuad.br.texCoords.v = bottom;
1040             locQuad.tl.texCoords.u = left;
1041             locQuad.tl.texCoords.v = top;
1042             locQuad.tr.texCoords.u = right;
1043             locQuad.tr.texCoords.v = top;
1044         }
1045         this._quadDirty = true;
1046     }
1047 });
1048 
1049 if (cc._renderType === cc._RENDER_TYPE_CANVAS) {
1050 
1051     var _p = cc.LabelTTF.prototype;
1052 
1053     _p.setColor = function (color3) {
1054         cc.Node.prototype.setColor.call(this, color3);
1055 
1056         this._setColorsString();
1057     };
1058 
1059     _p._setColorsString = function () {
1060         this._needUpdateTexture = true;
1061 
1062         var locDisplayColor = this._displayedColor, locDisplayedOpacity = this._displayedOpacity;
1063         var locStrokeColor = this._strokeColor, locFontFillColor = this._textFillColor;
1064 
1065         this._shadowColorStr = "rgba(" + (0 | (locDisplayColor.r * 0.5)) + "," + (0 | (locDisplayColor.g * 0.5)) + "," + (0 | (locDisplayColor.b * 0.5)) + "," + this._shadowOpacity + ")";
1066         this._fillColorStr = "rgba(" + (0 | (locDisplayColor.r / 255 * locFontFillColor.r)) + "," + (0 | (locDisplayColor.g / 255 * locFontFillColor.g)) + ","
1067             + (0 | (locDisplayColor.b / 255 * locFontFillColor.b)) + ", " + locDisplayedOpacity / 255 + ")";
1068         this._strokeColorStr = "rgba(" + (0 | (locDisplayColor.r / 255 * locStrokeColor.r)) + "," + (0 | (locDisplayColor.g / 255 * locStrokeColor.g)) + ","
1069             + (0 | (locDisplayColor.b / 255 * locStrokeColor.b)) + ", " + locDisplayedOpacity / 255 + ")";
1070     };
1071 
1072     _p.updateDisplayedColor = function (parentColor) {
1073         cc.Node.prototype.updateDisplayedColor.call(this, parentColor);
1074         this._setColorsString();
1075     };
1076 
1077     _p.setOpacity = function (opacity) {
1078         if (this._opacity === opacity)
1079             return;
1080         cc.Sprite.prototype.setOpacity.call(this, opacity);
1081         this._setColorsString();
1082         this._needUpdateTexture = true;
1083     };
1084 
1085     //TODO: _p._updateDisplayedOpacityForCanvas
1086     _p.updateDisplayedOpacity = cc.Sprite.prototype.updateDisplayedOpacity;
1087 
1088     _p.initWithStringAndTextDefinition = function (text, textDefinition) {
1089         // prepare everything needed to render the label
1090         this._updateWithTextDefinition(textDefinition, false);
1091 
1092         // set the string
1093         this.string = text;
1094 
1095         return true;
1096     };
1097 
1098     _p.setFontFillColor = function (tintColor) {
1099         var locTextFillColor = this._textFillColor;
1100         if (locTextFillColor.r != tintColor.r || locTextFillColor.g != tintColor.g || locTextFillColor.b != tintColor.b) {
1101             locTextFillColor.r = tintColor.r;
1102             locTextFillColor.g = tintColor.g;
1103             locTextFillColor.b = tintColor.b;
1104 
1105             this._setColorsString();
1106             this._needUpdateTexture = true;
1107         }
1108     };
1109 
1110     _p.draw = cc.Sprite.prototype.draw;
1111 
1112     _p.setTextureRect = function (rect, rotated, untrimmedSize) {
1113         this._rectRotated = rotated || false;
1114         untrimmedSize = untrimmedSize || rect;
1115 
1116         this.setContentSize(untrimmedSize);
1117         this.setVertexRect(rect);
1118 
1119         var locTextureCoordRect = this._textureRect_Canvas;
1120         locTextureCoordRect.x = rect.x;
1121         locTextureCoordRect.y = rect.y;
1122         locTextureCoordRect.width = rect.width;
1123         locTextureCoordRect.height = rect.height;
1124         locTextureCoordRect.validRect = !(locTextureCoordRect.width === 0 || locTextureCoordRect.height === 0
1125             || locTextureCoordRect.x < 0 || locTextureCoordRect.y < 0);
1126 
1127         var relativeOffset = this._unflippedOffsetPositionFromCenter;
1128         if (this._flippedX)
1129             relativeOffset.x = -relativeOffset.x;
1130         if (this._flippedY)
1131             relativeOffset.y = -relativeOffset.y;
1132         this._offsetPosition.x = relativeOffset.x + (this._contentSize.width - this._rect.width) / 2;
1133         this._offsetPosition.y = relativeOffset.y + (this._contentSize.height - this._rect.height) / 2;
1134 
1135         // rendering using batch node
1136         if (this._batchNode) {
1137             this.dirty = true;
1138         }
1139     };
1140     _p = null;
1141 
1142 } else {
1143     cc.assert(typeof cc._tmp.WebGLLabelTTF === "function", cc._LogInfos.MissingFile, "LabelTTFWebGL.js");
1144     cc._tmp.WebGLLabelTTF();
1145     delete cc._tmp.WebGLLabelTTF;
1146 }
1147 
1148 cc.assert(typeof cc._tmp.PrototypeLabelTTF === "function", cc._LogInfos.MissingFile, "LabelTTFPropertyDefine.js");
1149 cc._tmp.PrototypeLabelTTF();
1150 delete cc._tmp.PrototypeLabelTTF;
1151 
1152 cc.LabelTTF._textAlign = ["left", "center", "right"];
1153 
1154 cc.LabelTTF._textBaseline = ["top", "middle", "bottom"];
1155 
1156 //check the first character
1157 cc.LabelTTF.wrapInspection = true;
1158 
1159 //Support: English French German
1160 //Other as Oriental Language
1161 cc.LabelTTF._wordRex = /([a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]+|\S)/;
1162 cc.LabelTTF._symbolRex = /^[!,.:;}\]%\?>、‘“》?。,!]/;
1163 cc.LabelTTF._lastWordRex = /([a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]+|\S)$/;
1164 cc.LabelTTF._lastEnglish = /[a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]+$/;
1165 cc.LabelTTF._firsrEnglish = /^[a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]/;
1166 
1167 // Only support style in this format: "18px Verdana" or "18px 'Helvetica Neue'"
1168 cc.LabelTTF._fontStyleRE = /^(\d+)px\s+['"]?([\w\s\d]+)['"]?$/;
1169 
1170 /**
1171  * creates a cc.LabelTTF from a font name, alignment, dimension and font size
1172  * @deprecated
1173  * @param {String} text
1174  * @param {String|cc.FontDefinition} [fontName="Arial"]
1175  * @param {Number} [fontSize=16]
1176  * @param {cc.Size} [dimensions=cc.size(0,0)]
1177  * @param {Number} [hAlignment=cc.TEXT_ALIGNMENT_LEFT]
1178  * @param {Number} [vAlignment=cc.VERTICAL_TEXT_ALIGNMENT_TOP]
1179  * @return {cc.LabelTTF|Null}
1180  * @example
1181  * // Example
1182  * 1.
1183  * var myLabel = cc.LabelTTF.create('label text',  'Times New Roman', 32, cc.size(320,32), cc.TEXT_ALIGNMENT_LEFT);
1184  * 2.
1185  * var fontDef = new cc.FontDefinition();
1186  * fontDef.fontName = "Arial";
1187  * fontDef.fontSize = "32";
1188  * var myLabel = cc.LabelTTF.create('label text',  fontDef);
1189  */
1190 cc.LabelTTF.create = function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) {
1191     return new cc.LabelTTF(text, fontName, fontSize, dimensions, hAlignment, vAlignment);
1192 };
1193 
1194 /**
1195  * @deprecated
1196  * @type {Function}
1197  */
1198 cc.LabelTTF.createWithFontDefinition = cc.LabelTTF.create;
1199 
1200 if (cc.USE_LA88_LABELS)
1201     cc.LabelTTF._SHADER_PROGRAM = cc.SHADER_POSITION_TEXTURECOLOR;
1202 else
1203     cc.LabelTTF._SHADER_PROGRAM = cc.SHADER_POSITION_TEXTUREA8COLOR;
1204 
1205 cc.LabelTTF.__labelHeightDiv = cc.newElement("div");
1206 cc.LabelTTF.__labelHeightDiv.style.fontFamily = "Arial";
1207 cc.LabelTTF.__labelHeightDiv.style.position = "absolute";
1208 cc.LabelTTF.__labelHeightDiv.style.left = "-100px";
1209 cc.LabelTTF.__labelHeightDiv.style.top = "-100px";
1210 cc.LabelTTF.__labelHeightDiv.style.lineHeight = "normal";
1211 
1212 document.body ?
1213     document.body.appendChild(cc.LabelTTF.__labelHeightDiv) :
1214     cc._addEventListener(window, 'load', function () {
1215         this.removeEventListener('load', arguments.callee, false);
1216         document.body.appendChild(cc.LabelTTF.__labelHeightDiv);
1217     }, false);
1218 
1219 
1220 cc.LabelTTF.__getFontHeightByDiv = function (fontName, fontSize) {
1221     var clientHeight = cc.LabelTTF.__fontHeightCache[fontName + "." + fontSize];
1222     if (clientHeight > 0) return clientHeight;
1223     var labelDiv = cc.LabelTTF.__labelHeightDiv;
1224     labelDiv.innerHTML = "ajghl~!";
1225     labelDiv.style.fontFamily = fontName;
1226     labelDiv.style.fontSize = fontSize + "px";
1227     clientHeight = labelDiv.clientHeight;
1228     cc.LabelTTF.__fontHeightCache[fontName + "." + fontSize] = clientHeight;
1229     labelDiv.innerHTML = "";
1230     return clientHeight;
1231 };
1232 
1233 cc.LabelTTF.__fontHeightCache = {};