1 /**************************************************************************** 2 Copyright (c) 2008-2010 Ricardo Quesada 3 Copyright (c) 2011-2012 cocos2d-x.org 4 Copyright (c) 2013-2014 Chukong Technologies Inc. 5 6 http://www.cocos2d-x.org 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 ****************************************************************************/ 26 27 /** 28 * <p>cc.LabelTTF is a subclass of cc.TextureNode that knows how to render text labels with system font or a ttf font file<br/> 29 * All features from cc.Sprite are valid in cc.LabelTTF<br/> 30 * cc.LabelTTF objects are slow for js-binding on mobile devices.<br/> 31 * Consider using cc.LabelAtlas or cc.LabelBMFont instead.<br/> 32 * You can create a cc.LabelTTF from a font name, alignment, dimension and font size or a cc.FontDefinition object.</p> 33 * @class 34 * @extends cc.Sprite 35 * 36 * @param {String} text 37 * @param {String|cc.FontDefinition} [fontName="Arial"] 38 * @param {Number} [fontSize=16] 39 * @param {cc.Size} [dimensions=cc.size(0,0)] 40 * @param {Number} [hAlignment=cc.TEXT_ALIGNMENT_LEFT] 41 * @param {Number} [vAlignment=cc.VERTICAL_TEXT_ALIGNMENT_TOP] 42 * @example 43 * var myLabel = new cc.LabelTTF('label text', 'Times New Roman', 32, cc.size(320,32), cc.TEXT_ALIGNMENT_LEFT); 44 * 45 * var fontDef = new cc.FontDefinition(); 46 * fontDef.fontName = "Arial"; 47 * fontDef.fontSize = "32"; 48 * var myLabel = new cc.LabelTTF('label text', fontDef); 49 * 50 * @property {String} string - Content string of label 51 * @property {Number} textAlign - Horizontal Alignment of label: cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT 52 * @property {Number} verticalAlign - Vertical Alignment of label: cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM 53 * @property {Number} fontSize - Font size of label 54 * @property {String} fontName - Font name of label 55 * @property {String} font - The label font with a style string: e.g. "18px Verdana" 56 * @property {Number} boundingWidth - Width of the bounding box of label, the real content width is limited by boundingWidth 57 * @property {Number} boundingHeight - Height of the bounding box of label, the real content height is limited by boundingHeight 58 * @property {cc.Color} fillStyle - The fill color 59 * @property {cc.Color} strokeStyle - The stroke color 60 * @property {Number} lineWidth - The line width for stroke 61 * @property {Number} shadowOffsetX - The x axis offset of shadow 62 * @property {Number} shadowOffsetY - The y axis offset of shadow 63 * @property {Number} shadowOpacity - The opacity of shadow 64 * @property {Number} shadowBlur - The blur size of shadow 65 */ 66 cc.LabelTTF = cc.Sprite.extend(/** @lends cc.LabelTTF# */{ 67 _dimensions: null, 68 _hAlignment: cc.TEXT_ALIGNMENT_CENTER, 69 _vAlignment: cc.VERTICAL_TEXT_ALIGNMENT_TOP, 70 _fontName: null, 71 _fontSize: 0.0, 72 _string: "", 73 _originalText: null, 74 _onCacheCanvasMode: true, 75 76 // font shadow 77 _shadowEnabled: false, 78 _shadowOffset: null, 79 _shadowOpacity: 0, 80 _shadowBlur: 0, 81 _shadowColor: null, 82 83 // font stroke 84 _strokeEnabled: false, 85 _strokeColor: null, 86 _strokeSize: 0, 87 88 // font tint 89 _textFillColor: null, 90 91 _strokeShadowOffsetX: 0, 92 _strokeShadowOffsetY: 0, 93 _needUpdateTexture: false, 94 95 _lineWidths: null, 96 _className: "LabelTTF", 97 98 //for web 99 _fontStyle: "normal", 100 _fontWeight: "normal", 101 _lineHeight: "normal", 102 103 /** 104 * Initializes the cc.LabelTTF with a font name, alignment, dimension and font size, do not call it by yourself, 105 * you should pass the correct arguments in constructor to initialize the label. 106 * @param {String} label string 107 * @param {String} fontName 108 * @param {Number} fontSize 109 * @param {cc.Size} [dimensions=] 110 * @param {Number} [hAlignment=] 111 * @param {Number} [vAlignment=] 112 * @return {Boolean} return false on error 113 */ 114 initWithString: function (label, fontName, fontSize, dimensions, hAlignment, vAlignment) { 115 var strInfo; 116 if (label) 117 strInfo = label + ""; 118 else 119 strInfo = ""; 120 121 fontSize = fontSize || 16; 122 dimensions = dimensions || cc.size(0, 0/*fontSize*/); 123 hAlignment = hAlignment || cc.TEXT_ALIGNMENT_LEFT; 124 vAlignment = vAlignment || cc.VERTICAL_TEXT_ALIGNMENT_TOP; 125 126 this._opacityModifyRGB = false; 127 this._dimensions = cc.size(dimensions.width, dimensions.height); 128 this._fontName = fontName || "Arial"; 129 this._hAlignment = hAlignment; 130 this._vAlignment = vAlignment; 131 132 this._fontSize = fontSize; 133 this._renderCmd._setFontStyle(this._fontName, fontSize, this._fontStyle, this._fontWeight); 134 this.string = strInfo; 135 this._renderCmd._setColorsString(); 136 this._renderCmd._updateTexture(); 137 this._setUpdateTextureDirty(); 138 139 // Needed for high dpi text. 140 // In order to render it crisp, we request devicePixelRatio times the 141 // font size and scale it down 1/devicePixelRatio. 142 this._scaleX = this._scaleY = 1 / cc.view.getDevicePixelRatio(); 143 return true; 144 }, 145 146 _setUpdateTextureDirty: function () { 147 this._needUpdateTexture = true; 148 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.textDirty); 149 }, 150 151 ctor: function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) { 152 cc.Sprite.prototype.ctor.call(this); 153 154 this._dimensions = cc.size(0, 0); 155 this._hAlignment = cc.TEXT_ALIGNMENT_LEFT; 156 this._vAlignment = cc.VERTICAL_TEXT_ALIGNMENT_TOP; 157 this._opacityModifyRGB = false; 158 this._fontName = "Arial"; 159 160 this._shadowEnabled = false; 161 this._shadowOffset = cc.p(0, 0); 162 this._shadowOpacity = 0; 163 this._shadowBlur = 0; 164 165 this._strokeEnabled = false; 166 this._strokeColor = cc.color(255, 255, 255, 255); 167 this._strokeSize = 0; 168 169 this._textFillColor = cc.color(255, 255, 255, 255); 170 this._strokeShadowOffsetX = 0; 171 this._strokeShadowOffsetY = 0; 172 this._needUpdateTexture = false; 173 174 this._lineWidths = []; 175 this._renderCmd._setColorsString(); 176 this._textureLoaded = true; 177 178 if (fontName && fontName instanceof cc.FontDefinition) { 179 this.initWithStringAndTextDefinition(text, fontName); 180 } else { 181 cc.LabelTTF.prototype.initWithString.call(this, text, fontName, fontSize, dimensions, hAlignment, vAlignment); 182 } 183 }, 184 185 init: function () { 186 return this.initWithString(" ", this._fontName, this._fontSize); 187 }, 188 189 description: function () { 190 return "<cc.LabelTTF | FontName =" + this._fontName + " FontSize = " + this._fontSize.toFixed(1) + ">"; 191 }, 192 193 getLineHeight: function () { 194 return !this._lineHeight || this._lineHeight.charAt ? 195 this._renderCmd._getFontClientHeight() : 196 this._lineHeight || this._renderCmd._getFontClientHeight(); 197 }, 198 199 setLineHeight: function (lineHeight) { 200 this._lineHeight = lineHeight; 201 }, 202 203 /** 204 * Returns the text of the label 205 * @return {String} 206 */ 207 getString: function () { 208 return this._string; 209 }, 210 211 /** 212 * Returns Horizontal Alignment of cc.LabelTTF 213 * @return {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT} 214 */ 215 getHorizontalAlignment: function () { 216 return this._hAlignment; 217 }, 218 219 /** 220 * Returns Vertical Alignment of cc.LabelTTF 221 * @return {cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM} 222 */ 223 getVerticalAlignment: function () { 224 return this._vAlignment; 225 }, 226 227 /** 228 * 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. 229 * @see cc.LabelTTF#setDimensions, cc.LabelTTF#boundingWidth and cc.LabelTTF#boundingHeight 230 * @return {cc.Size} 231 */ 232 getDimensions: function () { 233 return cc.size(this._dimensions); 234 }, 235 236 /** 237 * Returns font size of cc.LabelTTF 238 * @return {Number} 239 */ 240 getFontSize: function () { 241 return this._fontSize; 242 }, 243 244 /** 245 * Returns font name of cc.LabelTTF 246 * @return {String} 247 */ 248 getFontName: function () { 249 return this._fontName; 250 }, 251 252 /** 253 * 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. 254 * @param {String} text 255 * @param {cc.FontDefinition} textDefinition 256 * @return {Boolean} 257 */ 258 initWithStringAndTextDefinition: function (text, textDefinition) { 259 // prepare everything needed to render the label 260 this._updateWithTextDefinition(textDefinition, false); 261 // set the string 262 this.string = text; 263 return true; 264 }, 265 266 /** 267 * Sets the text definition used by this label 268 * @param {cc.FontDefinition} theDefinition 269 */ 270 setTextDefinition: function (theDefinition) { 271 if (theDefinition) 272 this._updateWithTextDefinition(theDefinition, true); 273 }, 274 275 /** 276 * Extract the text definition used by this label 277 * @return {cc.FontDefinition} 278 */ 279 getTextDefinition: function () { 280 return this._prepareTextDefinition(false); 281 }, 282 283 /** 284 * Enable or disable shadow for the label 285 * @param {cc.Color | Number} a Color or The x axis offset of the shadow 286 * @param {cc.Size | Number} b Size or The y axis offset of the shadow 287 * @param {Number} c The blur size of the shadow or The opacity of the shadow (0 to 1) 288 * @param {null | Number} d Null or The blur size of the shadow 289 * @example 290 * old: 291 * labelttf.enableShadow(shadowOffsetX, shadowOffsetY, shadowOpacity, shadowBlur); 292 * new: 293 * labelttf.enableShadow(shadowColor, offset, blurRadius); 294 */ 295 enableShadow: function (a, b, c, d) { 296 if (a.r != null && a.g != null && a.b != null && a.a != null) { 297 this._enableShadow(a, b, c); 298 } else { 299 this._enableShadowNoneColor(a, b, c, d); 300 } 301 }, 302 303 _enableShadowNoneColor: function (shadowOffsetX, shadowOffsetY, shadowOpacity, shadowBlur) { 304 shadowOpacity = shadowOpacity || 0.5; 305 if (false === this._shadowEnabled) 306 this._shadowEnabled = true; 307 308 var locShadowOffset = this._shadowOffset; 309 if (locShadowOffset && (locShadowOffset.x !== shadowOffsetX) || (locShadowOffset._y !== shadowOffsetY)) { 310 locShadowOffset.x = shadowOffsetX; 311 locShadowOffset.y = shadowOffsetY; 312 } 313 314 if (this._shadowOpacity !== shadowOpacity) { 315 this._shadowOpacity = shadowOpacity; 316 } 317 this._renderCmd._setColorsString(); 318 319 if (this._shadowBlur !== shadowBlur) 320 this._shadowBlur = shadowBlur; 321 this._setUpdateTextureDirty(); 322 }, 323 324 _enableShadow: function (shadowColor, offset, blurRadius) { 325 if (!this._shadowColor) { 326 this._shadowColor = cc.color(255, 255, 255, 128); 327 } 328 this._shadowColor.r = shadowColor.r; 329 this._shadowColor.g = shadowColor.g; 330 this._shadowColor.b = shadowColor.b; 331 332 var x, y, a, b; 333 x = offset.width || offset.x || 0; 334 y = offset.height || offset.y || 0; 335 a = (shadowColor.a != null) ? (shadowColor.a / 255) : 0.5; 336 b = blurRadius; 337 338 this._enableShadowNoneColor(x, y, a, b); 339 }, 340 341 _getShadowOffsetX: function () { 342 return this._shadowOffset.x; 343 }, 344 _setShadowOffsetX: function (x) { 345 if (false === this._shadowEnabled) 346 this._shadowEnabled = true; 347 348 if (this._shadowOffset.x !== x) { 349 this._shadowOffset.x = x; 350 this._setUpdateTextureDirty(); 351 } 352 }, 353 354 _getShadowOffsetY: function () { 355 return this._shadowOffset._y; 356 }, 357 _setShadowOffsetY: function (y) { 358 if (false === this._shadowEnabled) 359 this._shadowEnabled = true; 360 361 if (this._shadowOffset._y !== y) { 362 this._shadowOffset._y = y; 363 this._setUpdateTextureDirty(); 364 } 365 }, 366 367 _getShadowOffset: function () { 368 return cc.p(this._shadowOffset.x, this._shadowOffset.y); 369 }, 370 _setShadowOffset: function (offset) { 371 if (false === this._shadowEnabled) 372 this._shadowEnabled = true; 373 374 if (this._shadowOffset.x !== offset.x || this._shadowOffset.y !== offset.y) { 375 this._shadowOffset.x = offset.x; 376 this._shadowOffset.y = offset.y; 377 this._setUpdateTextureDirty(); 378 } 379 }, 380 381 _getShadowOpacity: function () { 382 return this._shadowOpacity; 383 }, 384 _setShadowOpacity: function (shadowOpacity) { 385 if (false === this._shadowEnabled) 386 this._shadowEnabled = true; 387 388 if (this._shadowOpacity !== shadowOpacity) { 389 this._shadowOpacity = shadowOpacity; 390 this._renderCmd._setColorsString(); 391 this._setUpdateTextureDirty(); 392 } 393 }, 394 395 _getShadowBlur: function () { 396 return this._shadowBlur; 397 }, 398 _setShadowBlur: function (shadowBlur) { 399 if (false === this._shadowEnabled) 400 this._shadowEnabled = true; 401 402 if (this._shadowBlur !== shadowBlur) { 403 this._shadowBlur = shadowBlur; 404 this._setUpdateTextureDirty(); 405 } 406 }, 407 408 /** 409 * Disable shadow rendering 410 */ 411 disableShadow: function () { 412 if (this._shadowEnabled) { 413 this._shadowEnabled = false; 414 this._setUpdateTextureDirty(); 415 } 416 }, 417 418 /** 419 * Enable label stroke with stroke parameters 420 * @param {cc.Color} strokeColor The color of stroke 421 * @param {Number} strokeSize The size of stroke 422 */ 423 enableStroke: function (strokeColor, strokeSize) { 424 if (this._strokeEnabled === false) 425 this._strokeEnabled = true; 426 427 var locStrokeColor = this._strokeColor; 428 if ((locStrokeColor.r !== strokeColor.r) || (locStrokeColor.g !== strokeColor.g) || (locStrokeColor.b !== strokeColor.b)) { 429 locStrokeColor.r = strokeColor.r; 430 locStrokeColor.g = strokeColor.g; 431 locStrokeColor.b = strokeColor.b; 432 this._renderCmd._setColorsString(); 433 } 434 435 if (this._strokeSize !== strokeSize) 436 this._strokeSize = strokeSize || 0; 437 this._setUpdateTextureDirty(); 438 }, 439 440 _getStrokeStyle: function () { 441 return this._strokeColor; 442 }, 443 _setStrokeStyle: function (strokeStyle) { 444 if (this._strokeEnabled === false) 445 this._strokeEnabled = true; 446 447 var locStrokeColor = this._strokeColor; 448 if ((locStrokeColor.r !== strokeStyle.r) || (locStrokeColor.g !== strokeStyle.g) || (locStrokeColor.b !== strokeStyle.b)) { 449 locStrokeColor.r = strokeStyle.r; 450 locStrokeColor.g = strokeStyle.g; 451 locStrokeColor.b = strokeStyle.b; 452 this._renderCmd._setColorsString(); 453 this._setUpdateTextureDirty(); 454 } 455 }, 456 457 _getLineWidth: function () { 458 return this._strokeSize; 459 }, 460 _setLineWidth: function (lineWidth) { 461 if (this._strokeEnabled === false) 462 this._strokeEnabled = true; 463 if (this._strokeSize !== lineWidth) { 464 this._strokeSize = lineWidth || 0; 465 this._setUpdateTextureDirty(); 466 } 467 }, 468 469 /** 470 * Disable label stroke 471 */ 472 disableStroke: function () { 473 if (this._strokeEnabled) { 474 this._strokeEnabled = false; 475 this._setUpdateTextureDirty(); 476 } 477 }, 478 479 /** 480 * Sets the text fill color 481 * @function 482 * @param {cc.Color} fillColor The fill color of the label 483 */ 484 setFontFillColor: function (fillColor) { 485 var locTextFillColor = this._textFillColor; 486 if (locTextFillColor.r !== fillColor.r || locTextFillColor.g !== fillColor.g || locTextFillColor.b !== fillColor.b) { 487 locTextFillColor.r = fillColor.r; 488 locTextFillColor.g = fillColor.g; 489 locTextFillColor.b = fillColor.b; 490 this._renderCmd._setColorsString(); 491 this._needUpdateTexture = true; 492 } 493 }, 494 495 _getFillStyle: function () { 496 return this._textFillColor; 497 }, 498 499 //set the text definition for this label 500 _updateWithTextDefinition: function (textDefinition, mustUpdateTexture) { 501 if (textDefinition.fontDimensions) { 502 this._dimensions.width = textDefinition.boundingWidth; 503 this._dimensions.height = textDefinition.boundingHeight; 504 } else { 505 this._dimensions.width = 0; 506 this._dimensions.height = 0; 507 } 508 509 this._hAlignment = textDefinition.textAlign; 510 this._vAlignment = textDefinition.verticalAlign; 511 512 this._fontName = textDefinition.fontName; 513 this._fontSize = textDefinition.fontSize || 12; 514 515 if(textDefinition.lineHeight) 516 this._lineHeight = textDefinition.lineHeight 517 else 518 this._lineHeight = this._fontSize; 519 520 this._renderCmd._setFontStyle(textDefinition); 521 522 523 // shadow 524 if (textDefinition.shadowEnabled) 525 this.enableShadow(textDefinition.shadowOffsetX, 526 textDefinition.shadowOffsetY, 527 textDefinition.shadowOpacity, 528 textDefinition.shadowBlur); 529 530 // stroke 531 if (textDefinition.strokeEnabled) 532 this.enableStroke(textDefinition.strokeStyle, textDefinition.lineWidth); 533 534 // fill color 535 this.setFontFillColor(textDefinition.fillStyle); 536 537 if (mustUpdateTexture) 538 this._renderCmd._updateTexture(); 539 var flags = cc.Node._dirtyFlags; 540 this._renderCmd.setDirtyFlag(flags.colorDirty|flags.opacityDirty|flags.textDirty); 541 }, 542 543 _prepareTextDefinition: function (adjustForResolution) { 544 var texDef = new cc.FontDefinition(); 545 546 if (adjustForResolution) { 547 texDef.fontSize = this._fontSize; 548 texDef.boundingWidth = cc.contentScaleFactor() * this._dimensions.width; 549 texDef.boundingHeight = cc.contentScaleFactor() * this._dimensions.height; 550 } else { 551 texDef.fontSize = this._fontSize; 552 texDef.boundingWidth = this._dimensions.width; 553 texDef.boundingHeight = this._dimensions.height; 554 } 555 556 texDef.fontName = this._fontName; 557 texDef.textAlign = this._hAlignment; 558 texDef.verticalAlign = this._vAlignment; 559 560 // stroke 561 if (this._strokeEnabled) { 562 texDef.strokeEnabled = true; 563 var locStrokeColor = this._strokeColor; 564 texDef.strokeStyle = cc.color(locStrokeColor.r, locStrokeColor.g, locStrokeColor.b); 565 texDef.lineWidth = this._strokeSize; 566 } else 567 texDef.strokeEnabled = false; 568 569 // shadow 570 if (this._shadowEnabled) { 571 texDef.shadowEnabled = true; 572 texDef.shadowBlur = this._shadowBlur; 573 texDef.shadowOpacity = this._shadowOpacity; 574 575 texDef.shadowOffsetX = (adjustForResolution ? cc.contentScaleFactor() : 1) * this._shadowOffset.x; 576 texDef.shadowOffsetY = (adjustForResolution ? cc.contentScaleFactor() : 1) * this._shadowOffset.y; 577 } else 578 texDef._shadowEnabled = false; 579 580 // text tint 581 var locTextFillColor = this._textFillColor; 582 texDef.fillStyle = cc.color(locTextFillColor.r, locTextFillColor.g, locTextFillColor.b); 583 return texDef; 584 }, 585 586 /* 587 * BEGIN SCALE METHODS 588 * 589 * In order to make the value of scaleX and scaleY consistent across 590 * screens, we provide patched versions that return the same values as if 591 * the screen was not HiDPI. 592 */ 593 594 /** 595 * Returns the scale factor of the node. 596 * @warning: Assertion will fail when _scaleX != _scaleY. 597 * @function 598 * @return {Number} The scale factor 599 */ 600 getScale: function () { 601 if (this._scaleX !== this._scaleY) 602 cc.log(cc._LogInfos.Node_getScale); 603 return this._scaleX * cc.view.getDevicePixelRatio(); 604 }, 605 606 /** 607 * Sets the scale factor of the node. 1.0 is the default scale factor. This function can modify the X and Y scale at the same time. 608 * @function 609 * @param {Number} scale or scaleX value 610 * @param {Number} [scaleY=] 611 */ 612 setScale: function (scale, scaleY) { 613 this._scaleX = scale / cc.view.getDevicePixelRatio(); 614 this._scaleY = ((scaleY || scaleY === 0) ? scaleY : scale) / 615 cc.view.getDevicePixelRatio(); 616 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty); 617 }, 618 619 /** 620 * Returns the scale factor on X axis of this node 621 * @function 622 * @return {Number} The scale factor on X axis. 623 */ 624 getScaleX: function () { 625 return this._scaleX * cc.view.getDevicePixelRatio(); 626 }, 627 628 /** 629 * <p> 630 * Changes the scale factor on X axis of this node <br/> 631 * The default value is 1.0 if you haven't changed it before 632 * </p> 633 * @function 634 * @param {Number} newScaleX The scale factor on X axis. 635 */ 636 setScaleX: function (newScaleX) { 637 this._scaleX = newScaleX / cc.view.getDevicePixelRatio(); 638 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty); 639 }, 640 641 /** 642 * Returns the scale factor on Y axis of this node 643 * @function 644 * @return {Number} The scale factor on Y axis. 645 */ 646 getScaleY: function () { 647 return this._scaleY * cc.view.getDevicePixelRatio(); 648 }, 649 650 /** 651 * <p> 652 * Changes the scale factor on Y axis of this node <br/> 653 * The Default value is 1.0 if you haven't changed it before. 654 * </p> 655 * @function 656 * @param {Number} newScaleY The scale factor on Y axis. 657 */ 658 setScaleY: function (newScaleY) { 659 this._scaleY = newScaleY / cc.view.getDevicePixelRatio(); 660 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty); 661 }, 662 663 /* 664 * END SCALE METHODS 665 */ 666 667 /** 668 * Changes the text content of the label 669 * @warning Changing the string is as expensive as creating a new cc.LabelTTF. To obtain better performance use cc.LabelAtlas 670 * @param {String} text Text content for the label 671 */ 672 setString: function (text) { 673 text = String(text); 674 if (this._originalText !== text) { 675 this._originalText = text + ""; 676 677 this._updateString(); 678 679 // Force update 680 this._setUpdateTextureDirty(); 681 this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty); 682 } 683 }, 684 _updateString: function () { 685 if ((!this._string || this._string === "") && this._string !== this._originalText) 686 cc.renderer.childrenOrderDirty = true; 687 this._string = this._originalText; 688 }, 689 690 /** 691 * Sets Horizontal Alignment of cc.LabelTTF 692 * @param {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT} alignment Horizontal Alignment 693 */ 694 setHorizontalAlignment: function (alignment) { 695 if (alignment !== this._hAlignment) { 696 this._hAlignment = alignment; 697 // Force update 698 this._setUpdateTextureDirty(); 699 } 700 }, 701 702 /** 703 * Sets Vertical Alignment of cc.LabelTTF 704 * @param {cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM} verticalAlignment 705 */ 706 setVerticalAlignment: function (verticalAlignment) { 707 if (verticalAlignment !== this._vAlignment) { 708 this._vAlignment = verticalAlignment; 709 710 // Force update 711 this._setUpdateTextureDirty(); 712 } 713 }, 714 715 /** 716 * 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. 717 * @param {cc.Size|Number} dim dimensions or width of dimensions 718 * @param {Number} [height] height of dimensions 719 */ 720 setDimensions: function (dim, height) { 721 var width; 722 if (height === undefined) { 723 width = dim.width; 724 height = dim.height; 725 } else 726 width = dim; 727 728 if (width !== this._dimensions.width || height !== this._dimensions.height) { 729 this._dimensions.width = width; 730 this._dimensions.height = height; 731 this._updateString(); 732 // Force update 733 this._setUpdateTextureDirty(); 734 } 735 }, 736 737 _getBoundingWidth: function () { 738 return this._dimensions.width; 739 }, 740 _setBoundingWidth: function (width) { 741 if (width !== this._dimensions.width) { 742 this._dimensions.width = width; 743 this._updateString(); 744 // Force update 745 this._setUpdateTextureDirty(); 746 } 747 }, 748 749 _getBoundingHeight: function () { 750 return this._dimensions.height; 751 }, 752 _setBoundingHeight: function (height) { 753 if (height !== this._dimensions.height) { 754 this._dimensions.height = height; 755 this._updateString(); 756 // Force update 757 this._setUpdateTextureDirty(); 758 } 759 }, 760 761 /** 762 * Sets font size of cc.LabelTTF 763 * @param {Number} fontSize 764 */ 765 setFontSize: function (fontSize) { 766 if (this._fontSize !== fontSize) { 767 this._fontSize = fontSize; 768 this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight); 769 // Force update 770 this._setUpdateTextureDirty(); 771 } 772 }, 773 774 /** 775 * Sets font name of cc.LabelTTF 776 * @param {String} fontName 777 */ 778 setFontName: function (fontName) { 779 if (this._fontName && this._fontName !== fontName) { 780 this._fontName = fontName; 781 this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight); 782 // Force update 783 this._setUpdateTextureDirty(); 784 } 785 }, 786 787 _getFont: function () { 788 return this._renderCmd._getFontStyle(); 789 }, 790 _setFont: function (fontStyle) { 791 var res = cc.LabelTTF._fontStyleRE.exec(fontStyle); 792 if (res) { 793 this._fontSize = parseInt(res[1]); 794 this._fontName = res[2]; 795 this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight); 796 797 // Force update 798 this._setUpdateTextureDirty(); 799 } 800 }, 801 802 /** 803 * 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. 804 * @returns {cc.Size} The content size 805 */ 806 getContentSize: function () { 807 if (this._needUpdateTexture) 808 this._renderCmd._updateTTF(); 809 return cc.size(this._contentSize); 810 }, 811 812 _getWidth: function () { 813 if (this._needUpdateTexture) 814 this._renderCmd._updateTTF(); 815 return this._contentSize.width; 816 }, 817 _getHeight: function () { 818 if (this._needUpdateTexture) 819 this._renderCmd._updateTTF(); 820 return this._contentSize.height; 821 }, 822 823 setTextureRect: function (rect, rotated, untrimmedSize) { 824 //set needConvert to false 825 cc.Sprite.prototype.setTextureRect.call(this, rect, rotated, untrimmedSize, false); 826 }, 827 828 /** 829 * set Target to draw on 830 * @param boolean onCanvas 831 */ 832 setDrawMode: function (onCacheMode) { 833 this._onCacheCanvasMode = onCacheMode; 834 }, 835 836 _createRenderCmd: function () { 837 if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) 838 return new cc.LabelTTF.WebGLRenderCmd(this); 839 else if (this._onCacheCanvasMode) 840 return new cc.LabelTTF.CacheCanvasRenderCmd(this); 841 else 842 return new cc.LabelTTF.CanvasRenderCmd(this); 843 }, 844 845 //For web only 846 _setFontStyle: function(fontStyle){ 847 if (this._fontStyle !== fontStyle) { 848 this._fontStyle = fontStyle; 849 this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight); 850 this._setUpdateTextureDirty(); 851 } 852 }, 853 854 _getFontStyle: function(){ 855 return this._fontStyle; 856 }, 857 858 _setFontWeight: function(fontWeight){ 859 if (this._fontWeight !== fontWeight) { 860 this._fontWeight = fontWeight; 861 this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight); 862 this._setUpdateTextureDirty(); 863 } 864 }, 865 866 _getFontWeight: function(){ 867 return this._fontWeight; 868 } 869 }); 870 871 cc.assert(cc.isFunction(cc._tmp.PrototypeLabelTTF), cc._LogInfos.MissingFile, "LabelTTFPropertyDefine.js"); 872 cc._tmp.PrototypeLabelTTF(); 873 delete cc._tmp.PrototypeLabelTTF; 874 875 // Only support style in this format: "18px Verdana" or "18px 'Helvetica Neue'" 876 cc.LabelTTF._fontStyleRE = /^(\d+)px\s+['"]?([\w\s\d]+)['"]?$/; 877 878 /** 879 * creates a cc.LabelTTF from a font name, alignment, dimension and font size 880 * @deprecated since v3.0, please use the new construction instead 881 * @see cc.LabelTTF 882 * @static 883 * @param {String} text 884 * @param {String|cc.FontDefinition} [fontName="Arial"] 885 * @param {Number} [fontSize=16] 886 * @param {cc.Size} [dimensions=cc.size(0,0)] 887 * @param {Number} [hAlignment=cc.TEXT_ALIGNMENT_LEFT] 888 * @param {Number} [vAlignment=cc.VERTICAL_TEXT_ALIGNMENT_TOP] 889 * @return {cc.LabelTTF|Null} 890 */ 891 cc.LabelTTF.create = function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) { 892 return new cc.LabelTTF(text, fontName, fontSize, dimensions, hAlignment, vAlignment); 893 }; 894 895 /** 896 * @deprecated since v3.0, please use the new construction instead 897 * @function 898 * @static 899 */ 900 cc.LabelTTF.createWithFontDefinition = cc.LabelTTF.create; 901 902 cc.LabelTTF.__labelHeightDiv = document.createElement("div"); 903 cc.LabelTTF.__labelHeightDiv.style.fontFamily = "Arial"; 904 cc.LabelTTF.__labelHeightDiv.style.position = "absolute"; 905 cc.LabelTTF.__labelHeightDiv.style.left = "-100px"; 906 cc.LabelTTF.__labelHeightDiv.style.top = "-100px"; 907 cc.LabelTTF.__labelHeightDiv.style.lineHeight = "normal"; 908 909 document.body ? 910 document.body.appendChild(cc.LabelTTF.__labelHeightDiv) : 911 window.addEventListener('load', function () { 912 this.removeEventListener('load', arguments.callee, false); 913 document.body.appendChild(cc.LabelTTF.__labelHeightDiv); 914 }, false); 915 916 /** 917 * Returns the height of text with an specified font family and font size, in 918 * device independent pixels. 919 * 920 * @param {string|cc.FontDefinition} fontName 921 * @param {number} fontSize 922 * @returns {number} 923 * @private 924 */ 925 cc.LabelTTF.__getFontHeightByDiv = function (fontName, fontSize) { 926 var clientHeight, labelDiv = cc.LabelTTF.__labelHeightDiv; 927 if(fontName instanceof cc.FontDefinition){ 928 /** @type cc.FontDefinition */ 929 var fontDef = fontName; 930 clientHeight = cc.LabelTTF.__fontHeightCache[fontDef._getCanvasFontStr()]; 931 if (clientHeight > 0) return clientHeight; 932 labelDiv.innerHTML = "ajghl~!"; 933 labelDiv.style.fontFamily = fontDef.fontName; 934 labelDiv.style.fontSize = fontDef.fontSize + "px"; 935 labelDiv.style.fontStyle = fontDef.fontStyle; 936 labelDiv.style.fontWeight = fontDef.fontWeight; 937 938 clientHeight = labelDiv.clientHeight; 939 cc.LabelTTF.__fontHeightCache[fontDef._getCanvasFontStr()] = clientHeight; 940 labelDiv.innerHTML = ""; 941 } 942 else { 943 //Default 944 clientHeight = cc.LabelTTF.__fontHeightCache[fontName + "." + fontSize]; 945 if (clientHeight > 0) return clientHeight; 946 labelDiv.innerHTML = "ajghl~!"; 947 labelDiv.style.fontFamily = fontName; 948 labelDiv.style.fontSize = fontSize + "px"; 949 clientHeight = labelDiv.clientHeight; 950 cc.LabelTTF.__fontHeightCache[fontName + "." + fontSize] = clientHeight; 951 labelDiv.innerHTML = ""; 952 } 953 return clientHeight; 954 955 }; 956 957 cc.LabelTTF.__fontHeightCache = {}; 958