15 Replies Latest reply on Aug 11, 2015 4:42 AM by Laubender

    Why is PageItem.resize() unit independent? What other methods are?

    McShaman Level 1

      I am continuing my journey through InDesign scripting units and values blues. I am currently trying to resize a PageItem and have found the following code resizes the selected PageItem in 'points' not my viewPreferences.horizontalMeasurementUnits, 'millimeters'.

       

      document.selection[0].resize( CoordinateSpaces.pasteboardCoordinates, AnchorPoint.centerAnchor, ResizeMethods.ADDING_CURRENT_DIMENSIONS_TO, [ 100, 0 ] );
      

       

      I am still trying to work out the best way to work with units and values of size. I thought all properties and methods used the documents viewPreferences unit properties when dealing with values of size… Turns out I was wrong!

       

      I am asking the experienced scripters:

       

      1. Considering all methods that manipulate, measure, compare or return values of size, what would be the ratio of methods that are unit dependent vs unit independent be? I.e. viewPreferences vs points.
      2. If Adobe were to work on making this more consistent in the future which direction do you think they would go?

       

      I ask so that I can pick a methodology that I feel will be simpler across a wider range of methods and possibly be more future proof.

        • 1. Re: Why is PageItem.resize() unit independent? What other methods are?
          Peter Kahrel Adobe Community Professional & MVP

          It is true that .resize() works in points only. As far as I know it's the only function that doesn't consider the document's measurement units.

          Whether Adobe will ever change this I don't know. But in the meantime you can convert a value into points using JavaScript's UnitValue function. For example, suppose you have a text frame selected. Then you can get the position of the frame's top in points no matter what the document's units are using the following method:

           

          top = app.selection[0].geometricBounds[0];
          topInPoints = UnitValue(top, app.documents[0].viewPreferences.horizontalMeasurementUnits).as('pt');
          

           

          It's quite a mouthful but it works.

           

          Another method could be the use the .horizontalScale and .vericalScale properties.

           

          Peter

          • 2. Re: Why is PageItem.resize() unit independent? What other methods are?
            McShaman Level 1

            Hmmm thats a bit of a shame. I was kinda hoping maybe Adobe might be moving to a unit independent system. It would make more sense. It would mean as developers you wouldn't have to constantly check the users settings and you could easily combine and compare elements that typically use different unit types. E.g. PageItem geometric bounds and stroke weights.

            • 3. Re: Why is PageItem.resize() unit independent? What other methods are?
              Peter Kahrel Adobe Community Professional & MVP

              The best way to deal with this is to set the script preferences so that everything is treated as points. That doesn't change the document's units, just the script-document interface:

               

              app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;

              • 4. Re: Why is PageItem.resize() unit independent? What other methods are?
                McShaman Level 1

                Interesting solution. I had not come across that property before. But it still relies on modifying properties outside of the scope of the target objects. If the script crashes during runtime the users environment will be left in the changed state. Which may effect other scripts that assume the MeasurmentUnits will be set to AUTO_VALUE.

                 

                Adobe should set this property to POINTS and lock it down... Or provide all values in both document.viewPreferences and unit independent.

                • 5. Re: Why is PageItem.resize() unit independent? What other methods are?
                  Peter Kahrel Adobe Community Professional & MVP

                  > the users environment will be left in the changed state.

                   

                  No, the user's environment isn't changed at all. The only thing that changes is the scripting environment, and if you use a custom engine, the scope of the unit value that you set is restricted to that engine.

                  • 6. Re: Why is PageItem.resize() unit independent? What other methods are?
                    Marc Autret Level 4

                    Hi guys,

                     

                    In fact, all methods that explicitly deal with coordinate spaces and transformations expect dimensions and/or locations in points: resolve(), transform(), resize(), reframe().

                     

                    There is just an exception for locations, provided that:

                    (1) coordinates are passed using the ruler system syntax;

                    (2) the param consideringRulerUnits is set to true.

                    In such case your x and y are interpreted with respect to user units and custom zero-point.

                     

                    What seems to me embarrassing is the fact that the ruler system is involved in many DOM object properties—PageItem.geometricBounds, PathPoint.anchor, and so on—while this is the most unsafe and volatile coordinate system in InDesign. Actual data are stored using coordinate spaces and transformation matrices (all in points units) as shown in IDML exports.

                     

                    There is no problem in finding locations or computing sizes relative to a target coordinate space, but inversely it might be very fastidious to translate coordinate space data into the ruler system when the DOM API requires those ruler-related coordinates. A solution is to create your own transformation matrix. An example is shown at the end of the article Indiscripts :: Drawing Sine Waves in InDesign (see boxToRulerMatrix.)

                     

                    Hope that helps.

                     

                    @+

                    Marc

                    • 7. Re: Why is PageItem.resize() unit independent? What other methods are?
                      McShaman Level 1

                      Hi Marc,

                       

                      I am interested in the boxToRulerMatix method. The syntax for arguments for transform(), resolve(), resize(), etc has always confused me. I have tried to stick it out but still stuck on some concepts I think. Have made a new post with my questions if you wouldn't mind responding.

                       

                      Thanks.

                      • 8. Re: Why is PageItem.resize() unit independent? What other methods are?
                        Laubender Adobe Community Professional & MVP

                        There is just an exception for locations, provided that:

                        (1) coordinates are passed using the ruler system syntax;

                        (2) the param consideringRulerUnits is set to true.

                        In such case your x and y are interpreted with respect to user units and custom zero-point.

                         

                        Hi Marc,

                        and it seems consideringRulerUnits is coming with a condition :

                        Adobe InDesign CS6 (8.0) Object Model JS: PageItem

                         

                        Let me quote the description text for consideringRulerUnits according to DOM documentation:

                        "This parameter has no effect unless the reference point is specified relative to a page. (Optional) (default: false)"

                         

                        I'm not exactly sure what this condition is all about.
                        Does that mean, that setting consideringRulerUnits to true is only working, if the coordinate space of the in parameter or maybe the from parameter of transform() is set to CoordinateSpaces.PAGE_COORDINATES ? I'm a little bit confused what reference point the documentation is talking about.

                         

                        Uwe

                        • 9. Re: Why is PageItem.resize() unit independent? What other methods are?
                          Marc Autret Level 4

                          Hi Uwe,

                           

                          > Does that mean, that setting consideringRulerUnits to true is only working, if the coordinate space of the in parameter

                          > or maybe the from parameter of transform() is set to CoordinateSpaces.PAGE_COORDINATES ?

                           

                          Not at all—but the official doc is very confusing on this point.

                           

                          The consideringRulerUnits option has only to do with the syntax of a location. In the transform() method, this location is the origin during the transformation (that is, the from parameter.) And in the resolve() method, this is of course the location parameter. The in parameter of transform() refers to the targeted bounding box, keeping in mind that the concept of bounding box is space-dependent. (I think I've already posted something on that subject.)

                           

                          Now, what is the location syntax that complies with consideringRulerUnits==true? That's the RULER SPACE syntax. (Two other formats are available, BOUNDS SPACE and COORDINATE SPACE, I won't discuss them here.)

                           

                          To my knowledge the RULER SPACE syntax has two possible forms:

                           

                          1. [ [X,Y], pgIndex ]

                          where [X,Y] is a location relative to the ruler origin (zero point) of the spread or page-ruler-space associated to the client object.

                          This depends on both the Zero Point location and the RulerPerPage vs. RulerPerSpread vs. RulerOnSpine option.

                          Then (X,Y) will be interpreted in ruler units if consideringRulerUnits==TRUE.

                          pgIndex is the page index in the parent spread if RulerPerPage is ON, otherwise the value of pageIndex has no effect although it is required (use 0).

                          Note: if RulerPerPage is ON, pgIndex may actually be set to 1+maxIndex

                          Note: if RulerOnSpine is ON, the Zero Point has a fixed location.

                           

                          2. [ [X,Y], pgAtLocation ]

                          where [X,Y] is a location relative to the ruler origin (zero point) of the spread or page-ruler-space associated to pgAtLocation.

                          In that scheme pgAtLocation is a location specified in the BOUNDS SPACE format (anchor point enum or anchor point relative coordinates, including BoundingBoxLimits if needed, etc.)

                           

                          I know that's a bit complicated. What is important to notice is, the RULER SPACE syntax does require a page to be specified (pgIndex in form 1, pgAtLocation in form 2), and this is the only format that gives sense to consideringRulerUnits. That's why the doc says, “This parameter has no effect unless the reference point is specified relative to a page.”

                           

                          Hope that helps.

                          @+

                          Marc

                          • 10. Re: Why is PageItem.resize() unit independent? What other methods are?
                            Laubender Adobe Community Professional & MVP

                            Thank you, Marc!
                            Hmm… I'll be back with some code examples after musing about your explanations.

                            I'm really eager to understand this important argument consideringRulerUnits.

                             

                            Uwe

                            • 11. Re: Why is PageItem.resize() unit independent? What other methods are?
                              Jump_Over Level 5

                              Hi Marc,

                               

                              Thanks a lot for your lights in this winding tunnel

                               

                              Jarek

                              • 12. Re: Why is PageItem.resize() unit independent? What other methods are?
                                Marc Autret Level 4

                                Hi Uwe and Jarek,

                                 

                                For the sake of precision I should add that the terms 'RULER SPACE' and 'BOUNDS SPACE' are mine—although there is a trace of these idioms in SDK's hpp headers. But it would be more correct to speak of RULER (resp. BOUNDS) SYSTEMS, since they are not actual coordinate spaces in strict InDesign terms.

                                 

                                As for consideringRulerUnits, the best example I can provide so far is in my boxToRulerMatrix() function at Indiscripts :: Drawing Sine Waves in InDesign

                                 

                                Study the following portion of the code, ref being a Page instance:

                                 

                                // ...
                                
                                   // Ruler origin --> CS_BOARD (trans)
                                   // ---
                                  ro = ref.resolve([[0,0], AP_TOP_LEFT], CS_BOARD, true)[0];
                                
                                   // Ruler (u,v) --> CS_BOARD (scaling)
                                   // ---
                                  rs = ref.resolve([[1,1], AP_TOP_LEFT], CS_BOARD, true)[0];
                                
                                
                                // ...
                                
                                
                                

                                 

                                The variables ro and rs are computed via the RULER SPACE syntax based on the scheme [ [X,Y], pgAtLocation ], where pgAtLocation is the top left anchor point of the page bounding box seen in its inner space (in short, the actual top-left corner of the page). Contrary to what one might think at first glance, the unique purpose of this argument is to specify a page, that is, the page which contains the anchor point in question, that is, the page ref itself! (The top left corner of a page always belongs to that page, right?) This seems incredibly odd to make such a detour, provided that ref is precisely the client object of the resolve method we are invoking. But the RULER SPACE syntax requires that we provide a page!

                                 

                                Note that I could have used the form [ [X,Y], pgIndex ] as well, since the pgIndex is 0 (zero) in the particular context of my routine—ref being the 1st page of the target spread. But the code I use is more generic in that it doesn't assume that ref index is known. In summary, the pattern:

                                 

                                myPage.resolve( [ [X,Y], AnchorPoint.TOP_LEFT_ANCHOR ], coordSpace, true)[0]


                                allows to resolve the [X,Y] coordinates relative to myPage itself and with respect to the current units and zero point, into any coordSpace. This is the best way I can see to safely extract this information. Furthermore, that pattern still works in RulerPerSpread or RulerOnSpine modes, because as long as a page is specified consideringRulerUnits is taken into account by the location resolver


                                Now, what about these [0,0] and [1,1] coordinate pairs in ro and rs? This is the best part:


                                • Since we are using the RULER SPACE syntax, [0,0] indicates the zero point location (the ruler origin). Hence, ro resolves that location, in points, into the destination space (i.e. the pasteboard coordinate space, in my example).


                                • For the same reason [1,1] indicates the location [1 hu,1 vu] in the ruler system, where hu (resp. vu) refers to the current horizontal (resp. vertical) unit(s). So rs resolves that location, in points, into the destination space.


                                Finally, ro and rs allow to compute both a translation and a scaling vector that will contribute in revert-mapping coordinates from the bounding box system into the current ruler system. (The whole routine performs additional matrix calculations through the inner coordinate space, but this stuff is not related to the RULER SPACE syntax.)


                                The boxToRulerMatrix() function provides a bridge between intuitive bbox coordinates (0..1 ranges along x- and y-axes) and the highly non-intuitive and unstable ruler system, which is unfortunately required in PathPoint specifications and other similar DOM commands. The method I suggest is intended to support any transformation state of the target, any ruler or zero point customization, any unusual context. I don't think I'd have reached my goal by other means…

                                 

                                @+

                                Marc

                                • 13. Re: Why is PageItem.resize() unit independent? What other methods are?
                                  Laubender Adobe Community Professional & MVP

                                  Hi Marc,

                                  I want to approach myself slowly for using consideringRulerUnits set to true, using the ruler units rather than points, step by step.

                                  Baby steps, so to say.

                                   

                                  I don't know, if this is the right first step, but:

                                  All I like to do is moving (translating) a simple rectangle by 20 units of the ruler units along the x-axis and along the y-axis.

                                  I know, that I can achieve this by using the move() method very easily, but this should not be my point here.

                                   

                                  Instead I want to use the transform() method of this rectangle.

                                   

                                  My code is trying this, but in vain. The rectangle is moving, but only in points, not in millimeters (the measurement unit I set for horizontalMeasurementUnits of the document's ViewPreferences).

                                  Maybe you could guide me through what I'm doing wrong. Here is my code:

                                   

                                  /**
                                  * @@@BUILDINFO@@@ NaiveApproach-3-Translation-x-y-ConsideringRulerUnits.jsx !Version! Tue Aug 11 2015 09:55:11 GMT+0200
                                  */
                                  
                                  //DESCRIPTION:USING consideringRulerUnits; so translation values should be according to the vertical and horizontal ruler units
                                  
                                  
                                  // RESULT: STILL transform() IS USING POINTS
                                  
                                  // Setting a unique file name for my InDesign file
                                  // relative to the position of the script in use:
                                  
                                  var myScriptFile = File($.fileName);
                                  var myScriptPath = myScriptFile.path;
                                  var myScriptName = myScriptFile.name;
                                  
                                  var myInddFile = File( myScriptPath +"/"+ myScriptName.replace(/\.jsx$/,"") +"_"+ Date.now() +".indd" );
                                  
                                  var myDocument = app.documents.add();
                                  myDocument.save(myInddFile);
                                  
                                  //Adding a rectangle to page 1
                                  
                                  //If this rectangle is a square depends on the ruler units
                                  //Are there different MeasurementUnits for horizontalMeasurementUnits and verticalMeasurementUnits
                                  //the rectangle is *not* square-like
                                  
                                  //I want a square:
                                  
                                  myDocument.viewPreferences.properties =
                                  {
                                     
                                      rulerOrigin : RulerOrigin.SPINE_ORIGIN , // Ruler on spine
                                     
                                      horizontalMeasurementUnits : MeasurementUnits.MILLIMETERS ,
                                      verticalMeasurementUnits : MeasurementUnits.MILLIMETERS
                                     
                                  };
                                  
                                  //Adding a rectangle to the first page of the document
                                  //100 x 100 mm at position [10,10]
                                  //fillColor is "Yellow"
                                  
                                  var myRectangle = myDocument.rectangles.add
                                  (
                                      {
                                          geometricBounds : [10,10,110,110] ,
                                          fillColor : "Yellow"
                                      }
                                  );
                                  
                                  $.writeln("BEFORE TRANSFORM | myRectangle.parent"+"\t"+myRectangle.parent);
                                  $.writeln("BEFORE TRANSFORM | myRectangle.geometricBounds"+"\t"+myRectangle.geometricBounds);
                                  
                                  // Getting the index of the page the rectangle is sitting on:
                                  // I know this is overcomplicated, but I want it a bit more generic.
                                  
                                  myRectanglePageIndex = myRectangle.parentPage.documentOffset;
                                  
                                  // The value for translating the object in x-direction:
                                  var x = 20;
                                  // The value for translating the object in y-direction:
                                  var y = 20;
                                  
                                  // Maybe a naive approach:
                                  // Defining horizontalTranslation and verticalTranslation with a new transformation matrix
                                  
                                  var myTransformationMatrix = app.transformationMatrices.add
                                  (
                                  
                                      undefined, // horizontalScaleFactor
                                      undefined, // verticalScaleFactor
                                      undefined, // clockwiseShearAngle
                                      undefined, // counterclockwiseRotationAngle
                                     
                                      x , // horizontalTranslation
                                      y , // verticalTranslation
                                     
                                      undefined, // matrixValues
                                      undefined, // matrixMapping
                                      undefined // withProperties
                                  
                                  );
                                         
                                  //Now using this matrix with method transform() on the rectangle:
                                  
                                  myRectangle.transform
                                  (
                                      // in (NOT OPTIONAL)
                                      // The coordinate space to use
                                      // [In this case the coordinate space of the spread]
                                     
                                      // Can I do wrong here?
                                      // I just want to translate the object
                                     
                                      CoordinateSpaces.PARENT_COORDINATES,
                                     
                                      // from (NOT OPTIONAL)
                                      // there lies the culprit, I guess
                                      // transform() may not recongnize, that this should be page related
                                      // Why?
                                     
                                      [
                                         
                                          [0,0] , // the zero point
                                          myRectanglePageIndex // the index of the page the rectangle was added to
                                         
                                          //Alternatively tested, but same result:
                                          //AnchorPoint.CENTER_ANCHOR
                                         
                                      ] ,
                                     
                                     
                                      myTransformationMatrix , // withMatrix
                                     
                                      undefined , // replacingCurrent
                                  
                                     
                                      true // consideringRulerUnits
                                      // It seems, that consideringRulerUnits has no effect here
                                      // horizontal translation is still made in points
                                     
                                  );
                                  
                                  
                                  $.writeln("AFTER TRANSFORM | myRectangle.geometricBounds"+"\t"+myRectangle.geometricBounds);
                                  
                                  myDocument.save(myInddFile);
                                  

                                   

                                  Thank you very much for your patience, Marc.

                                   

                                  Uwe

                                  • 14. Re: Why is PageItem.resize() unit independent? What other methods are?
                                    Marc Autret Level 4

                                    Hi Uwe,

                                     

                                    I guess you didn't notice my very first point: “The consideringRulerUnits option has only to do with the syntax of a location.”

                                     

                                    The attributes of a transformation matrix are always given and interpreted in points!

                                     

                                    What your code does, in summary, is

                                     

                                    myRectangle.transform( coordSpace, [ [0,0], pgIndex ], [1,0,0,1,x,y], undefined, true );

                                     

                                    where (x,y) are still POINTS attributes no matter the consideringRulerUnits flag.

                                     

                                    All you can say is that the origin of that transformation—origin which has no effect here, since this is just a translation!—is the ruler zero point, as you're using the RULER SPACE syntax for that location.

                                     

                                    But there are two additional points to be mentioned:

                                    1. The pgIndex parameter expects the index of the page within its parent spread (the documentOffset property is wrong).

                                    2. In RulerSpineOrigin and RulerSpreadOrigin modes the page specification is required but has no impact since the zero point location does not depend on a given page.

                                     

                                    Now, if you really want to explore this topic in a step by step fashion, do not start with the transform() method. This is the most complex one!

                                    The right sandbox is resolve(location, space, [consideringRulerUnits]).

                                     

                                    @+

                                    Marc

                                    • 15. Re: Why is PageItem.resize() unit independent? What other methods are?
                                      Laubender Adobe Community Professional & MVP

                                      Obviously I had some misconceptions about transform().

                                       

                                      I will go study the thing from ground up.
                                      Starting with your PDF (again; it's being a while since I first read it) :

                                      Indiscripts :: Coordinate Spaces & Transformations in InDesign — Chap.1-2

                                       

                                      Thanks a lot, Marc!

                                       

                                      Uwe