9 Replies Latest reply on Dec 1, 2010 6:50 AM by WordRad

    Various text width methods for TextField simply DO NOT WORK (what's up with that, Adobe)

    WordRad Level 1

      This is beyond ridiculous.  They're not working in Flex 4 either.

       

      The ONLY method for determining the width correctly for text in a textfield is as follows:

       

      Create a subclass of mx.controls.Text so that its protected property textField can be accessed.

      For that textField property, call textfield.getCharBoundaries(..) for each character in the text you want to measure and add them up.

      That is the ONLY method that determines the width for some text in a TextField.  (NOTE: this concerns large font text - say 50pts or higher.)

       

      There are a myriad number of other methods for ostensibly determining text width, but none of them work.  They are all returning the same value, but its substantially less than the correct value returned by the method outlined above.

       

      For example if you call  Text.textField.getUITextFormat.measureHTMLText (or measureText)  they both return the same value but that value is WRONG.

      The same is true for any standalone TextField or UITextfield (i.e. one not part of an MX:Text object).

       

      Also,  TextField.getLineMetrics(...).width is returning this same errouneous value.  If I just had domr idea what this value is its returning I could adjust for it, but that value is not varying in any straightforward way from the correct value when you change the font size.

       

      Also, just calling getCharBoundaries of a stand alone TextField or UITextField also returns erroneous values.  It has to be the textfield property of an Mx.Controls.Text object for getCharBoundaries to work  correctly  That method outlined above using getCharBoundaries is the only way to determine the correct width.

       

      My problem occured when I wanted to change an Mx.controls.Text object into a straight UITextField, at which point I could no longer correctly determine text width.

       

      Its so baffling and confounding that virtually no one has encountered this.  Or maybe they have, and have constructed some convoluted erroneous rationalization to account for it not working (along the lines of, "Maybe I'm the stupid one, and Adobe really does know what they're doing...")

       

      I did encounter a thread from a couple of years ago on Actionscript.Org, where someone also posted that these text width methods simply do not work.  There was one response from someone else confirming this, but no subsequent resolution provided.

       

      So what is going on???  Do any competent Adobe employees, actually monitor this forum?  I didn't see any point in putting this in the bug tracker for Flex, because I won't care if this is resolved a year from now.

        • 1. Re: Various text width methods for TextField simply DO NOT WORK (what's up with that, Adobe)
          Flex harUI Adobe Employee

          If you want someone to look into it, post a test case.

           

          TextField definitely has some idiosyncracies, especially with device fonts.

          You have to size the TextField to compensate for the gutter, and the

          concatenatedMatrix affects the reported widths.

          • 2. Re: Various text width methods for TextField simply DO NOT WORK (what's up with that, Adobe)
            WordRad Level 1

            OK I'll come up with a test case.  Just to clarify one thing,  if getCharBoundaries is called from the textField property of an MX:Text object, it returns what I would call the total cell width of the text, which is what I want.  However getCharBoundaries returns something entirely different if called from a stand alone TextField or UITextField.  It's like 25% less but the error varies non-linearly based on font-size.  So my point is, its not as if I'm misinterpreting what getCharBOundaries is returning, its returning 2 entirely different things based on the context.  But I'll come up with a test case here in a bit.

             

            edit:

            But I would prefer to use something other than getCharBoundaries anyway, as it apparently works by processing the actual display, and throws exceptions for stand alone UITextfields if the text is outside the visible region (And oddly MX:Text.textField.getCharBoundaries does not throw exceptions for this.)

             

            But as I say, measureText, measureHTMLText -all of those are returning some mystery value.  Only MX:Text.textField.getCharBoundaries is returning a correct value.  But I'll come up with a test case.

            • 3. Re: Various text width methods for TextField simply DO NOT WORK (what's up with that, Adobe)
              WordRad Level 1

              The test case I came up with computed  text widths correctly.  My standard program still isn't, though no explanation as the test case captures the essence of it.

               

              As I said the test case works, but here  it is anyway:

               

              untitled.PNG

               

               

              <?xml version="1.0" encoding="UTF-8"?>
              <mx:Application
                xmlns:mx="http://www.adobe.com/2006/mxml
                xmlns:mc="my_components.*"
                xmlns:custom="swf_address.*"
                layout="absolute"
                initialize="{Init()}"
                backgroundColor="#00B0C0"
              >


                <mx:Style>         
               
                  @font-face {
                    src:url("arthur__.ttf");
                    fontFamily: font0;
                  }     
                   
                </mx:Style> 
                     
                <mx:Script><![CDATA[ 
               
                  import my_components.TextWR;
                  import mx.controls.SWFLoader;
                  import mx.core.UITextField;
                  import mx.core.IUITextField;
                     
                  private var txt1:TextWR;

                  //private var txt0:TextWR;
                  private var txt0:UITextField;
                 
                  private var fnt_ldr:SWFLoader;  

                  private function Init(event:Event=null):void {

                    fnt_ldr = new SWFLoader();
                    fnt_ldr.addEventListener(Event.COMPLETE, regfont);
                    fnt_ldr.source = "tribeca.swf"
                    fnt_ldr.load();   
                 
                  }

                  private function regfont(event:Event):void {
                    Font.registerFont(SWFLoader(event.target).content['wrFont']);
                    Init2();
                  }
                 
                  private function Init2(event:Event=null):void {

                    var s:String =
                      "<font face=\"Tribeca\" size=\"50\"><br>0123456789  Testing 1 2 3...</font>";
                   
                    txt1 = new TextWR();
                    txt1.percentWidth=100;
                    txt1.percentHeight=100;
                    txt1.setStyle("fontGridFitType","subpixel");
                    txt1.setStyle("fontFamily","font0");

                    txt1.htmlText = s;
                    addChild(txt1);

                    //txt0 = new TextWR;
                    txt0 = new UITextField();
                    txt0.percentWidth=100;
                    txt0.percentHeight=100;
                    txt0.setStyle("fontGridFitType","subpixel");
                    txt0.setStyle("fontFamily","font0");
                    txt0.multiline=true;

                    txt0.htmlText = s;             
                    addChild(txt0);

                    var timer_if:Timer = new Timer(3000,1);
                    timer_if.addEventListener(TimerEvent.TIMER,TxtInit);
                    timer_if.start(); 

                  }
                           

                  private function TxtInit(event:Event):void {
                   
                    var r:Rectangle = txt1.ui_txtfld().getCharBoundaries(1);
                   
                    //var txt0_ui:IUITextField = txt0.ui_txtfld();
                    var txt0_ui:IUITextField = txt0;
                   
                    var w:Number = 0;
                    //for (var n:int=1; n<=10; n++)
                    //  w += txt0_ui.getCharBoundaries(n).width;
                    w = txt0_ui.getUITextFormat().measureHTMLText("<font face=\"Tribeca\" size=\"50\">0123456789</font>").width;       
                            
                    txt1.graphics.beginFill(0);
                    txt1.graphics.drawRect(r.left,r.top-7,w,4);
                    txt1.graphics.endFill();

                    removeChild(txt0);     
                   
                  }


                ]]></mx:Script>  

                 
              </mx:Application>

              • 4. Re: Various text width methods for TextField simply DO NOT WORK (what's up with that, Adobe)
                WordRad Level 1

                OK, I've solved my problem.  I apologize for the rant against Adobe but

                then again I might not have solved this otherwise.

                 

                The problem was rather obscure and almost certainly not relevant to others, but here it is:

                 

                I was trying to find the text width of a prefix that contains some characters in a special nonstandard utility font I created with very nonstandard attributes.  Mx:Text.textfield.getCharBoundaries had no problem with it, but every other width method did, evidently.   Of course, Mx.Text.textField is not actually a TextField or a UITextField,  but rather an  IUITextField, meaning it just implements the interface. Evidently its implementation may have nothing in common with the implementation of TextField and UITextField which are both directly related.

                 

                As far as this nonstandard font, I had not had any problem with it in the past, so failed to identify it as the culprit. Its character widths are identical to another font's, so that solved my problem.

                • 5. Re: Various text width methods for TextField simply DO NOT WORK (what's up with that, Adobe)
                  Flex harUI Adobe Employee

                  A TextField that isn't on the display list may return unexpected values

                  because the concatenatedMatrix is the identity matrix and may not reflect

                  how you are actually going to render the text.

                   

                  A TextField on the display list may also return unexpected values depending

                  on whether multiline and wordwrap are set and what the width of the

                  TextField is.  And then the concatenatedMatrix is considered.  And then a

                  font is chosen that may not exactly match the requested font size.  But it

                  should render the same as it measured.

                  • 6. Re: Various text width methods for TextField simply DO NOT WORK (what's up with that, Adobe)
                    WordRad Level 1

                    I have to give an update here, because in my last post I said the problem was this strange font I contrived, but it wasn't the problem after all.

                     

                    The problem was that this particular font of mine wasn't an installed  font on my system, and many of the text width methods in Flex only work evidently if the font is already installed on the user's system.  But it was an embedded font in my Flex application, (even though not a local system font). 

                     

                    So the moral is, even if a font is embedded in your Flex App, it may be misformatted on a user's machine if they didn't already have it installed independently on their own machine, because things like measureHTMLText, measureText,  getLineMetrics and TextField.getcharBoundaries assume the font is actually a system font on the users own machine and don't work correctly otherwise.  This is clearly a bug, not that I think it will ever be fixed by Adobe, regardless of whether its posted to their bug tracking system.

                    • 7. Re: Various text width methods for TextField simply DO NOT WORK (what's up with that, Adobe)
                      WordRad Level 1

                      I need to add an update.  The problem, contrary to what I said in my last post was not this unusual font I was using. Rather, it was that this font  was not installed as a system font on my machine, (even though it was an embedded font in my Flex App.)  measureText, measureHTMLText, TextField.getCharBoundaries do not work unless a font is actually installed on an end-user's machine - it makes no difference if the font is embedded in your Flex application.  Clearly a bug. Anyway, I did find a work around someone posted that appears to be working - involves creating an invisible TextField and then using TextWidth, with the Textfield only containing the text you want to measure, and setting AutoSize to "left"  But you probably have to hold your mouth right as well, although it does appear to be working thus far.

                      • 8. Re: Various text width methods for TextField simply DO NOT WORK (what's up with that, Adobe)
                        WordRad Level 1

                        OK I have to correct this issue as best I can as I learn about it.  Textfield.textWidth

                        will not work regardless.  Its like the other methods such as measureText and measureHTMLText, returning some mystery value.

                         

                        Textfield.width has to be used -  that is returning the actual width of the text if you do the following:

                         

                              var txt0Aux:UITextField = new UITextField();
                              txt0aux.visible=false;
                              txt0aux.autoSize="left";
                              txt0aux.defaultTextFormat = tf_b;
                              txt0aux.text = b_str;

                          

                        txt0aux.width is now actually the width of the text and can reliably be used. txt0aux.textWidth is who knows what.

                        • 9. Re: Various text width methods for TextField simply DO NOT WORK (what's up with that, Adobe)
                          WordRad Level 1

                          Another overlooked issue:

                           

                          Textfield.embedFonts has to be set to true. I just did that and now TextField. textWidth is computed correctly.

                           

                          But textWidth, measureHTMLText, etc shouldn't just return som default unexplained value , if its tryingto measure a  System Font that isn't there. And there wasn't any other indication that it couldn't find the embedded font.