7 Replies Latest reply on Sep 3, 2009 4:52 AM by Peter Kahrel

    Measurement Strings to Values

    Dave Saunders Level 4

      Am I missing a trick with this function:

       

      function getValue(theText, aDoc, horizRuler) {
           // horizRuler is a Boolean; if absent, defaults to false
           if (horizRuler === undefined) {
                horizRuler = false; // default to vertical ruler
           }
           var prop = horizRuler ? "anchorXoffset" : "anchorYoffset";
           var uValue = aDoc.anchoredObjectSettings[prop];
           try {
                aDoc.anchoredObjectSettings[prop] = theText;
           } catch(e) {
                return null; // theText has bad format
           }
           var value = aDoc.anchoredObjectSettings[prop];
           aDoc.anchoredObjectSettings[prop] = uValue;
           return value;
      }
      
      

       

      This works and avoids a lot of parsing code, but is there a much easier way that I'm just overlooking? I picked these two properties to use because they (a) relate to the document's rulers and (b) can take any positive or negative values.

       

      Dave

        • 1. Re: Measurement Strings to Values
          Bob Stucky Adobe Employee

          HI Dave,

           

          How 'bout using the UnitValue class?

           

          var v = new UnitValue( text ).as( "pt" );

           

          More rigorous:

           

          toPointValue = function( text ) {

              var v = new UnitValue( text );

              if ( v.type == "?" ) { // invalid units or format

                 return undefined;

              }

              return v.as( "pt" );

          }

           

          More Flexible:

           

          documentUnits = function( doc ) {
              if ( !doc ) {
                  doc = app.documents[0];
              }
              var mu = doc.viewPreferences.horizontalMeasurementUnits;
              switch ( mu ) {
                  case MeasurementUnits.AGATES : {
                      return "agt"; // agate == 5.5 pt
                      break;
                  }
                  case MeasurementUnits.CENTIMETERS : {
                      return "cm";
                      break;
                  }
                  case MeasurementUnits.CICEROS : {
                      return "ci";
                      break;
                  }
                  case MeasurementUnits.INCHES :
                  case MeasurementUnits.INCHES_DECIMAL : {
                      return "in";
                      break;
                  }
                  case MeasurementUnits.MILLIMETERS : {
                      return "mm";
                      break;
                  }
                  case MeasurementUnits.PICAS : {
                      return "pc"
                      break;
                  }
                  case MeasurementUnits.POINTS : {
                      return "pt";
                      break;
                  }
              }
          }

           

          toPointValue = function( text ) {

              var v = new UnitValue( text );

              if ( v.type == "?" ) { // invalid units or format

                  return undefined;

              }

              return v.as( documentUnits() );

          }

           

           

          You know I use classes whereever I can...

           

          I have a "Bounds" class that takes a geometricBounds array as an argument. The class does all kinds of handy stuff. First, all of the values (left, top, bottom, right) are stored as unit values. You can specify the units; if you don't, it takes the active document's units. Similarly, when converting back to an array, you can specify units or it will use document units.

           

          Then comes the fun stuff - set/get width, set/get height, align, intersects (boolean - if one bounds intersects with another), intersection (the bounds of the intersection), adjust (adjusts the bounds about an anchor point), getAnchor point.

           

          It also has static methods to find the document units, create a unit value, convert a text string to document units, and more.

           

          I've attached the class.

           

           

          Regards

           

          Bob

          • 2. Re: Measurement Strings to Values
            Bob Stucky Adobe Employee

            Got a nasty little error from the form when posting. I think it might have been related to attaching the file.

             

            If anyone wants the bounds class, email me: bostucky@adobe.com

             

             

            Bob

            • 3. Re: Measurement Strings to Values
              Dirk Becker  Level 4

              Dave, first let's first optimize your function:

               

              undefined used as boolean works like false, so you don't need that step of translation.

              $.writeln(undefined?"true":"false");

              -- false

               

              Another neat observation is that the || operator yields the the left or right side, rather than a boolean value.

              $.writeln(null || app.activeDocument);

              -- document

              $.writeln(47 || app.activeDocument);

              -- 47

               

              For nitpickers, I'd also store the "aDoc.anchoredObjectSettings" in a separate local. Unless there is some caching that I'm not aware of, every access on a preference thru that notation causes creation of a separate "proxy object" - the same hack that causes text operations to slow down after a while.

               

              Note that "finally" is executed even after return

               

              Then I'd name the method "parseMeasurement" or similar, "get..." usually indicates reading property access.

               

              function parseMeasurement(theText, aDoc, horizRuler) {

                  var aos = aDoc.anchoredObjectSettings;

                  var xy = horizRuler ? "anchorXoffset" : "anchorYoffset";

                  var save = aos[xy];

                  try {

                      return aos[xy] = theText;

                  } catch(e) {

                      return null; // better NaN ?

                  } finally {

                      aos[xy] = save;

                  }

              }

               

              Anyway, setting a preference will cause plenty things to happen under the hood - commands recorded for undo history, notifications to any UI widget that refers to the setting, so following Bob's UnitValue would definitely be the best improvement ...

               

              Btw, if anybody has a performance timer around, please compare the following approaches to Bob's original and post the times:

               

              documentUnits = function( doc )

              {

                  return arguments.callee[(doc||app.activeDocument). viewPreferences.horizontalMeasurementUnits];

              }

              documentUnits[MeasurementUnits.AGATES] = "agt";

              documentUnits[MeasurementUnits.CENTIMETERS ] = "cm";

              documentUnits[MeasurementUnits.CICEROS ] = "ci";

              documentUnits[MeasurementUnits.INCHES ] =

              documentUnits[MeasurementUnits.INCHES_DECIMAL ] = "in";

              documentUnits[MeasurementUnits.MILLIMETERS ] = "mm";

              documentUnits[MeasurementUnits.PICAS ] = "pc"

              documentUnits[MeasurementUnits.POINTS ] = "pt";

               

              documentUnits2 = (function()

              {

                  var lookup = {};

                  lookup[MeasurementUnits.AGATES] = "agt";

                  lookup[MeasurementUnits.CENTIMETERS ] = "cm";

                  lookup[MeasurementUnits.CICEROS ] = "ci";

                  lookup[MeasurementUnits.INCHES ] =

                  lookup[MeasurementUnits.INCHES_DECIMAL ] = "in";

                  lookup[MeasurementUnits.MILLIMETERS ] = "mm";

                  lookup[MeasurementUnits.PICAS ] = "pc"

                  lookup[MeasurementUnits.POINTS ] = "pt";

                  return function( doc )

                  {

                      return lookup[(doc||app.activeDocument).viewPreferences.horizontalMeasurementUnits];

                  }

              })();

               

              Edit: lookup = {} instead of [], because objects are the better associative arrays.

              • 4. Re: Measurement Strings to Values
                Peter Kahrel Adobe Community Professional & MVP

                Hi Dirk,

                 

                > lookup = {} instead of [], because objects are the better associative arrays.

                 

                Why is that?

                 

                Peter

                • 5. Re: Measurement Strings to Values
                  Peter Kahrel Adobe Community Professional & MVP

                  > Btw, if anybody has a performance timer around, please compare the following approaches to Bob's original and post the times.

                   

                  They're really equally fast. You need to iterate the functions to see any difference. These are the results of each function iterated 100 times:

                   

                  Bob: 0.219 - 0.234
                  Dirk 1: 0.140 - 0.188
                  Dirk 2: 0.157 - 0.188

                   

                  Peter

                  • 6. Re: Measurement Strings to Values
                    Harbs. Level 6

                    Why is that?

                     

                    Because the only reason arrays in JS work as associative arrays is 

                    because an array is just a kind of object. You can end up with all 

                    kinds of interesting bugs, etc. because of the unique qualities of 

                    arrays...

                     

                    I found a very good article on the subject quite some time ago. I 

                    don't remember where it was, but a google search turned this up which 

                    looks like it has the same basic info:

                     

                    http://andrewdupont.net/2006/05/18/javascript-associative-arrays-considered-harmful/

                     

                    Harbs

                    • 7. Re: Measurement Strings to Values
                      Peter Kahrel Adobe Community Professional & MVP

                      Thanks for that link, Harbs.

                       

                      Peter