1 /** 2 * The Render Engine 3 * VectorText 4 * 5 * @fileoverview A simple text renderer which draws text using lines. It has a 6 * limited character set. 7 * 8 * @author: Brett Fattori (brettf@renderengine.com) 9 * @author: $Author: bfattori $ 10 * @version: $Revision: 1555 $ 11 * 12 * Copyright (c) 2011 Brett Fattori (brettf@renderengine.com) 13 * 14 * Permission is hereby granted, free of charge, to any person obtaining a copy 15 * of this software and associated documentation files (the "Software"), to deal 16 * in the Software without restriction, including without limitation the rights 17 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 * copies of the Software, and to permit persons to whom the Software is 19 * furnished to do so, subject to the following conditions: 20 * 21 * The above copyright notice and this permission notice shall be included in 22 * all copies or substantial portions of the Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 30 * THE SOFTWARE. 31 * 32 */ 33 34 // The class this file defines and its required classes 35 R.Engine.define({ 36 "class":"R.text.VectorText", 37 "requires":[ 38 "R.math.Point2D", 39 "R.math.Rectangle2D", 40 "R.text.AbstractTextRenderer" 41 ] 42 }); 43 44 /** 45 * @class A text renderer which draws text with simple vectors. This type of text 46 * renderer is only supported by the {@link R.rendercontexts.CanvasContext CanvasContext}. 47 * For an {@link R.rendercontexts.HTMLElementContext HTMLElementContext} 48 * or a derivative, use the {@link R.text.ContextText} renderer. 49 * 50 * @constructor 51 * @param componentName {String} The name of the text component 52 * @param priority {Number} The priority of the component 53 * @extends R.text.AbstractTextRenderer 54 */ 55 R.text.VectorText = function () { 56 return R.text.AbstractTextRenderer.extend(/** @scope R.text.VectorText.prototype */{ 57 58 rText:null, 59 spacing:0, 60 61 /** @private */ 62 constructor:function (componentName, priority) { 63 this.base(componentName, priority); 64 this.rText = []; 65 this.setTextWeight(1.5); 66 }, 67 68 /** 69 * Release the text renderer back into the pool for reuse 70 */ 71 release:function () { 72 this.base(); 73 this.rText = null; 74 this.spacing = 0; 75 this.setTextWeight(1.5); 76 }, 77 78 /** 79 * Calculate the bounding box for the text and set it on the host object. 80 * @private 81 */ 82 calculateBoundingBox:function () { 83 var x1 = R.lang.Math2.MAX_INT; 84 var x2 = -R.lang.Math2.MAX_INT; 85 var y1 = R.lang.Math2.MAX_INT; 86 var y2 = -R.lang.Math2.MAX_INT; 87 for (var p = 0; p < this.rText.length; p++) { 88 var pt = this.rText[p]; 89 90 if (pt != null) { 91 if (pt.x < x1) { 92 x1 = pt.x; 93 } 94 if (pt.x > x2) { 95 x2 = pt.x; 96 } 97 if (pt.y < y1) { 98 y1 = pt.y; 99 } 100 if (pt.y > y2) { 101 y2 = pt.y; 102 } 103 } 104 } 105 106 this.getGameObject().getBoundingBox().set(0, 0, ((Math.abs(x1) + x2) * this.getSize()) + 2, ((Math.abs(y1) + y2) * this.getSize()) + 2); 107 this.setTextAlignment(this.getTextAlignment()); 108 }, 109 110 /** 111 * Set the scaling of the text 112 * @param size {Number} 113 */ 114 setSize:function (size) { 115 this.base(size); 116 this.calculateBoundingBox(); 117 }, 118 119 /** 120 * Set the text alignment 121 * @param align {Number} 122 */ 123 setTextAlignment:function (align) { 124 this.base(align); 125 126 // Adjust the origin, based on the alignment 127 var b = this.getGameObject().getBoundingBox(); 128 var c = b.getCenter(); 129 var o = R.math.Point2D.create(0, 0); 130 if (align === R.text.AbstractTextRenderer.ALIGN_RIGHT) { 131 o.set(c.x + b.getHalfWidth(), 0); 132 } 133 else if (align === R.text.AbstractTextRenderer.ALIGN_LEFT) { 134 o.set(c.x - b.getHalfWidth(), 0); 135 } 136 else { 137 o.set(c.x, 0); 138 } 139 140 this.getGameObject().setOrigin(o); 141 }, 142 143 /** 144 * Set the text to render. 145 * 146 * @param text {String} The text to vectorize 147 */ 148 setText:function (text) { 149 // We only have uppercase letters 150 text = String(text).toUpperCase(); 151 this.base(text); 152 153 if (this.rText.length > 0) { 154 for (var r in this.rText) { 155 if (this.rText[r]) 156 this.rText[r].destroy(); 157 } 158 } 159 160 this.rText = []; 161 var spacing = 11.5; 162 163 // Replace special chars 164 text = text.replace(/©/g, "a").replace(/®/g, "b"); 165 166 var lCount = text.length; 167 var letter = 0; 168 var kern = R.math.Point2D.create(spacing, 0); 169 var lineHeight = this.getSize() * 5; 170 var y = 0; 171 172 // Vectorize the text 173 var pc = R.math.Point2D.create(0, y); 174 while (lCount-- > 0) { 175 var ltr = []; 176 var chr = text.charCodeAt(letter); 177 if (chr == 10) { 178 // Support multi-line text 179 y += (this.getSize() * 10) + this.getLineSpacing(); 180 pc.set(0, y); 181 } 182 else { 183 var glyph = R.text.VectorText.chars[chr - 32]; 184 if (glyph.length == 0) { 185 pc.add(kern); 186 } 187 else { 188 189 for (var p = 0; p < glyph.length; p++) { 190 if (glyph[p] != null) { 191 this.rText.push(R.math.Point2D.create(glyph[p]).add(pc)); 192 } 193 else { 194 this.rText.push(null); 195 } 196 } 197 this.rText.push(null); 198 pc.add(kern); 199 } 200 } 201 letter += 1; 202 } 203 pc.destroy(); 204 kern.destroy(); 205 this.calculateBoundingBox(); 206 }, 207 208 /** 209 * @private 210 */ 211 execute:function (renderContext, time, dt) { 212 213 if (this.rText.length == 0) { 214 return; 215 } 216 217 renderContext.pushTransform(); 218 var o = R.math.Point2D.create(this.getGameObject().getOrigin()); 219 o.neg(); 220 renderContext.setPosition(o); 221 o.destroy(); 222 renderContext.setScale(this.getSize()); 223 // Set the stroke and fill styles 224 if (this.getColor() != null) { 225 renderContext.setLineStyle(this.getColor()); 226 } 227 228 renderContext.setLineWidth(this.getTextWeight()); 229 renderContext.drawPolyline(this.rText); 230 renderContext.popTransform(); 231 } 232 233 234 }, /** @scope R.text.VectorText.prototype */ { 235 236 /** 237 * Get the class name of this object 238 * @return {String} The string "R.text.VectorText" 239 */ 240 getClassName:function () { 241 return "R.text.VectorText"; 242 }, 243 244 /** 245 * @private 246 */ 247 chars:null, 248 249 /** 250 * @private 251 */ 252 _precalc:function () { 253 R.text.VectorText.chars = []; 254 var lb = function (glyph) { 255 var x1 = R.lang.Math2.MAX_INT; 256 var x2 = -R.lang.Math2.MAX_INT; 257 var y1 = R.lang.Math2.MAX_INT; 258 var y2 = -R.lang.Math2.MAX_INT; 259 for (var p = 0; p < glyph.length; p++) { 260 var pt = glyph[p]; 261 262 if (pt != null) { 263 if (pt.x < x1) { 264 x1 = pt.x; 265 } 266 if (pt.x > x2) { 267 x2 = pt.x; 268 } 269 if (pt.y < y1) { 270 y1 = pt.y; 271 } 272 if (pt.y > y2) { 273 y2 = pt.y; 274 } 275 } 276 } 277 278 // Get the center of the bounding box and move all of the points so none are negative 279 var b = R.math.Rectangle2D.create(0, 0, Math.abs(x1) + x2, Math.abs(y1) + y2); 280 var hP = R.math.Point2D.create(b.getHalfWidth() + 1, b.getHalfHeight() + 1); 281 for (p in glyph) { 282 if (glyph[p]) { 283 glyph[p].add(hP); 284 } 285 } 286 }; 287 288 // Convert the character set into adjusted points 289 for (var c in R.text.VectorText.charSet) { 290 var chr = R.text.VectorText.charSet[c], newChr = []; 291 292 // Convert to points 293 for (var p in chr) { 294 if (chr[p]) { 295 newChr.push(R.math.Point2D.create(chr[p][0], chr[p][1])); 296 } 297 else { 298 newChr.push(null); 299 } 300 } 301 302 // Adjust the origin of each point to zero 303 lb(newChr); 304 R.text.VectorText.chars.push(newChr); 305 } 306 }, 307 308 /** 309 * @private 310 */ 311 resolved:function () { 312 R.text.VectorText._precalc(); 313 }, 314 315 /** 316 * The character set 317 * @private 318 */ 319 charSet:[ 320 [], 321 // Space 322 [ 323 [0, -5], 324 [0, 3.5], 325 null, 326 [0, 4.5], 327 [-0.5, 4.75], 328 [0, 5], 329 [0.5, 4.75], 330 [0, 4.5] 331 ], 332 // ! 333 [ 334 [-1, -4], 335 [-2, -4], 336 [-2, -5], 337 [-1, -5], 338 [-1, -4], 339 [-2, -2], 340 null, 341 [2, -4], 342 [1, -4], 343 [1, -5], 344 [2, -5], 345 [2, -4], 346 [1, -2] 347 ], 348 // " 349 [ 350 [-1, -3], 351 [-1, 3], 352 null, 353 [1, -3], 354 [1, 3], 355 null, 356 [-3, -1], 357 [3, -1], 358 null, 359 [-3, 1], 360 [3, 1] 361 ], 362 // # 363 [ 364 [5, -4], 365 [-3, -4], 366 [-5, -3], 367 [-3, 0], 368 [3, 0], 369 [5, 3], 370 [3, 4], 371 [-5, 4], 372 null, 373 [0, -5], 374 [0, 5] 375 ], 376 // $ 377 [ 378 [-3, -3], 379 [-1, -3], 380 [-1, -1], 381 [-3, -1], 382 [-3, -3], 383 null, 384 [2, 2], 385 [4, 2], 386 [4, 4], 387 [2, 4], 388 [2, 2], 389 null, 390 [3, -4], 391 [-3, 4] 392 ], 393 // % 394 [ 395 [3, 5], 396 [0, -1], 397 [-1, -3], 398 [0, -4], 399 [1, -3], 400 [0, -1], 401 [-2, 1], 402 [-2, 3], 403 [-1, 4], 404 [1, 4], 405 [3, 1] 406 ], 407 // & 408 [ 409 [-1, -4], 410 [-2, -4], 411 [-2, -5], 412 [-1, -5], 413 [-1, -4], 414 [-2, -2] 415 ], 416 // ' 417 [ 418 [1, -5], 419 [-1, -3], 420 [-1, 3], 421 [1, 5] 422 ], 423 // ( 424 [ 425 [-1, -5], 426 [1, -3], 427 [1, 3], 428 [-1, 5] 429 ], 430 // ) 431 [ 432 [-3, -3], 433 [3, 3], 434 null, 435 [3, -3], 436 [-3, 3], 437 null, 438 [-3, 0], 439 [3, 0], 440 null, 441 [0, -3], 442 [0, 3] 443 ], 444 // * 445 [ 446 [-4, 0], 447 [4, 0], 448 null, 449 [0, -4], 450 [0, 4] 451 ], 452 // + 453 [ 454 [1, 4], 455 [0, 4], 456 [0, 3], 457 [1, 3], 458 [1, 4], 459 [0, 5] 460 ], 461 // , 462 [ 463 [-4, 1], 464 [4, 1] 465 ], 466 // - 467 [ 468 [0, 4], 469 [1, 4], 470 [1, 3], 471 [0, 3], 472 [0, 4] 473 ], 474 // . 475 [ 476 [5, -5], 477 [-5, 5] 478 ], 479 // / 480 //15 481 [ 482 [5, -5], 483 [-1, -5], 484 [-1, 5], 485 [5, 5], 486 [5, -5], 487 null, 488 [5, -5], 489 [-1, 5] 490 ], 491 // 0 492 [ 493 [1, -4], 494 [3, -5], 495 [3, 5] 496 ], 497 // 1 498 [ 499 [-5, -3], 500 [0, -5], 501 [5, -3], 502 [-5, 5], 503 [5, 5] 504 ], 505 // 2 506 [ 507 [-5, -5], 508 [5, -5], 509 [0, -1], 510 [5, 2], 511 [0, 5], 512 [-5, 3] 513 ], 514 // 3 515 [ 516 [-2, -3], 517 [-5, 0], 518 [5, 0], 519 null, 520 [5, -5], 521 [5, 5] 522 ], 523 // 4 524 [ 525 [5, -5], 526 [-5, -5], 527 [-5, 0], 528 [3, 0], 529 [5, 2], 530 [3, 5], 531 [-5, 5] 532 ], 533 // 5 534 [ 535 [-5, -5], 536 [-5, 5], 537 [5, 5], 538 [5, 0], 539 [-5, 0] 540 ], 541 // 6 542 [ 543 [-5, -5], 544 [5, -5], 545 [-2, 5] 546 ], 547 // 7 548 [ 549 [0, 0], 550 [-4, -2], 551 [0, -5], 552 [4, -2], 553 [-4, 2], 554 [0, 5], 555 [4, 2], 556 [0, 0] 557 ], 558 // 8 559 [ 560 [4, 0], 561 [-4, 0], 562 [-4, -5], 563 [4, -5], 564 [4, 0], 565 [-4, 5] 566 ], 567 // 9 568 //25 569 [ 570 [0, 1], 571 [1, 1], 572 [1, 0], 573 [0, 0], 574 [0, 1], 575 null, 576 [0, 4], 577 [1, 4], 578 [1, 3], 579 [0, 3], 580 [0, 4] 581 ], 582 // : 583 [ 584 [0, 1], 585 [1, 1], 586 [1, 0], 587 [0, 0], 588 [0, 1], 589 null, 590 [1, 4], 591 [0, 4], 592 [0, 3], 593 [1, 3], 594 [1, 4], 595 [0, 5] 596 ], 597 // ; 598 [ 599 [4, -5], 600 [-2, 0], 601 [4, 5] 602 ], 603 // < 604 [ 605 [-4, -2], 606 [4, -2], 607 null, 608 [-4, 2], 609 [4, 2] 610 ], 611 // = 612 [ 613 [-4, -5], 614 [2, 0], 615 [-4, 5] 616 ], 617 // > 618 [ 619 [-3, -3], 620 [0, -5], 621 [3, -3], 622 [0, -1], 623 [0, 2], 624 null, 625 [0, 4], 626 [1, 4], 627 [1, 3], 628 [0, 3], 629 [0, 4] 630 ], 631 // ? 632 [ 633 [3, 5], 634 [-3, 5], 635 [-5, 3], 636 [-5, -3], 637 [-3, -5], 638 [3, -5], 639 [5, -3], 640 [5, 2], 641 [3, 3], 642 [0, 3], 643 [0, 0], 644 [3, 0] 645 ], 646 // @ 647 //32 648 [ 649 [-5, 5], 650 [0, -5], 651 [5, 5], 652 [2, 2], 653 [-2, 2] 654 ], 655 // A 656 [ 657 [-4, 5], 658 [-4, -5], 659 [3, -5], 660 [5, -3], 661 [3, 0], 662 [-4, 0], 663 null, 664 [3, 0], 665 [5, 3], 666 [3, 5], 667 [-4, 5] 668 ], 669 // B 670 [ 671 [5, -3], 672 [0, -5], 673 [-5, -3], 674 [-5, 3], 675 [0, 5], 676 [5, 3] 677 ], 678 // C 679 [ 680 [-4, 5], 681 [-4, -5], 682 [2, -5], 683 [4, -3], 684 [4, 3], 685 [2, 5], 686 [-4, 5] 687 ], 688 // D 689 [ 690 [5, -5], 691 [0, -5], 692 [-3, -3], 693 [0, 0], 694 [-3, 3], 695 [0, 5], 696 [5, 5] 697 ], 698 // E 699 [ 700 [-4, 5], 701 [-4, 0], 702 [0, 0], 703 [-4, 0], 704 [-4, -5], 705 [4, -5] 706 ], 707 // F 708 [ 709 [5, -5], 710 [-4, -5], 711 [-4, 5], 712 [5, 5], 713 [5, 1], 714 [2, 1] 715 ], 716 // G 717 [ 718 [-4, 5], 719 [-4, -5], 720 null, 721 [-4, 0], 722 [4, 0], 723 null, 724 [4, -5], 725 [4, 5] 726 ], 727 // H 728 [ 729 [-3, 5], 730 [3, 5], 731 null, 732 [0, 5], 733 [0, -5], 734 null, 735 [-3, -5], 736 [3, -5] 737 ], 738 // I 739 [ 740 [3, -5], 741 [3, 3], 742 [0, 5], 743 [-3, 3] 744 ], 745 // J 746 [ 747 [-4, 5], 748 [-4, -5], 749 null, 750 [-4, 0], 751 [5, -5], 752 null, 753 [-4, 0], 754 [5, 5] 755 ], 756 // K 757 [ 758 [-4, -5], 759 [-4, 5], 760 [5, 5] 761 ], 762 // L 763 [ 764 [-4, 5], 765 [-4, -5], 766 [0, 0], 767 [5, -5], 768 [5, 5] 769 ], 770 // M 771 [ 772 [-4, 5], 773 [-4, -5], 774 [5, 5], 775 [5, -5] 776 ], 777 // N 778 [ 779 [5, -5], 780 [-2, -5], 781 [-2, 5], 782 [5, 5], 783 [5, -5] 784 ], 785 // O 786 [ 787 [-4, 5], 788 [-4, -5], 789 [3, -5], 790 [5, -3], 791 [3, 0], 792 [-4, 0] 793 ], 794 // P 795 [ 796 [-5, 0], 797 [0, -5], 798 [5, 0], 799 [0, 5], 800 [-5, 0], 801 null, 802 [3, 3], 803 [5, 5] 804 ], 805 // Q 806 [ 807 [-4, 5], 808 [-4, -5], 809 [3, -5], 810 [5, -3], 811 [3, 0], 812 [-4, 0], 813 null, 814 [3, 0], 815 [5, 5] 816 ], 817 // R 818 [ 819 [5, -5], 820 [-3, -5], 821 [-5, -3], 822 [-3, 0], 823 [3, 0], 824 [5, 3], 825 [3, 5], 826 [-5, 5] 827 ], 828 // S 829 [ 830 [-4, -5], 831 [4, -5], 832 null, 833 [0, -5], 834 [0, 5] 835 ], 836 // T 837 [ 838 [-4, -5], 839 [-4, 3], 840 [-3, 5], 841 [3, 5], 842 [5, 3], 843 [5, -5] 844 ], 845 // U 846 [ 847 [-5, -5], 848 [0, 5], 849 [5, -5] 850 ], 851 // V 852 [ 853 [-5, -5], 854 [-3, 5], 855 [0, -3], 856 [3, 5], 857 [5, -5] 858 ], 859 // W 860 [ 861 [-4, -5], 862 [5, 5], 863 null, 864 [5, -5], 865 [-4, 5] 866 ], 867 // X 868 [ 869 [-5, -5], 870 [0, -2], 871 [5, -5], 872 null, 873 [0, -2], 874 [0, 5] 875 ], 876 // Y 877 [ 878 [-4, -5], 879 [5, -5], 880 [-4, 5], 881 [5, 5] 882 ], 883 // Z 884 //58 885 [ 886 [2, -5], 887 [-1, -5], 888 [-1, 5], 889 [2, 5] 890 ], 891 // [ 892 [ 893 [-5, -5], 894 [5, 5] 895 ], 896 // \ 897 [ 898 [-2, -5], 899 [1, -5], 900 [1, 5], 901 [-2, 5] 902 ], 903 // ] 904 [ 905 [-3, 2], 906 [0, -1], 907 [3, 2] 908 ], 909 // ^ 910 [ 911 [-5, 5], 912 [5, 5] 913 ], 914 // _ 915 [ 916 [1, -4], 917 [2, -4], 918 [2, -5], 919 [1, -5], 920 [1, -4], 921 [2, -2] 922 ], 923 // ` 924 //64 925 [ 926 [5, -3], 927 [0, -5], 928 [-5, -3], 929 [-5, 3], 930 [0, 5], 931 [5, 3], 932 [5, -3], 933 null, 934 [3, -1], 935 [0, -3], 936 [-3, -1], 937 [-3, 1], 938 [0, 3], 939 [3, 1] 940 ], 941 // © 942 [ 943 [5, -3], 944 [0, -5], 945 [-5, -3], 946 [-5, 3], 947 [0, 5], 948 [5, 3], 949 [5, -3], 950 null, 951 [-3, 2], 952 [-3, -2], 953 [2, -2], 954 [3, -1], 955 [2, 0], 956 [-3, 0], 957 null, 958 [2, 0], 959 [3, 2] 960 ] 961 ] // ® 962 }); 963 964 };