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