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 };