2 Replies Latest reply on Apr 22, 2017 11:36 AM by goldgoldgold

    Change horizontal Scale of characters with different horizontal Scale


      I'm still pretty new in writing scripts.

      and I am trying to write a script that changes the horizontal Scale of the characters in the paragraph where the mouse pointer is located.

      So basically I wrote a script like this:


      var SASH="0.75"

          function myscript(){

        var m = app.activeDocument.selection[0].paragraphs.everyItem().getElements();

          for (a=0;a<m.length;a++){         

                try {m[a].horizontalScale = m[a].horizontalScale-(SASH.text*1)}

                   catch (e) {m[a].horizontalScale = m[a].horizontalScale-(SASH.text*1)}



      Basically it works, but the problem is that if there are characters in a paragraph that have a different horizontal Scale than the rest of the paragraph, the script gives everyone the same horizontal Scale and does not change them relatively.


      So I tried another way:


      var SASH="0.75"

      function myscript(){

        if(app.documents.length && app.selection.length && app.selection[0].hasOwnProperty("baseline")){

          var mySel = app.selection[0],

              p = mySel.paragraphs,

              pMax, pi, p0, ip;

          for(var i = 0; i < p.length; i++)

              pi = p[i];




      var myChar=app.activeDocument.selection[0].characters;

          for (a=0;a<myChar.length;a++){

          myChar[a].horizontalScale = (myChar[a].horizontalScale*1)-(SASH.text*1)};




      It works. But the problem is: 1) It is very, very, very slow. 2) As you probably noticed, I had to make the script select the entire paragraph where the mouse cursor was, and only then could I use that selection. It seems to me just the wrong way.

      I would be very happy if anyone here could help me solve the problem.
      Thank you!!

        • 1. Re: Change horizontal Scale of characters with different horizontal Scale
          Marc Autret Level 4

          Hi gold³


          First, a crucial rule you need to know (as it will dramatically simplify your life in the future) is:

          your script does not have to SELECT things before processing.


          I don't understand what the syntax SASH.text refers to in your code, but I will suppose at a more abstract level that:

          (a) You have some constant operation to achieve on target characters (by constant operation, I mean… function),

          (b) This operation regards a specific character property (in your example, horizontalScale).


          For example, you want to reduce or increase the value by the same amount, or apply to it some constant multiplier, etc.


          The interesting problem behind your question is, how can we optimize such process when the targets are sequential characters having, unfortunately, non-uniform scales applied. In the worst case, all scales would be distinct, and then each character would require an individual treatment. But in practice, I can't imagine all those horizontal scales randomly distributed—unless it's experimental poetry! So you likely have ranges of identical attributes in your source text. (At least, that's what I will assume, otherwise there is little hope of improving.)


          As the key idea is to reduce DOM access as much as possible, a good algorithm should try to handle the largest character ranges it can find, and from then it can operate range-by-range rather than char-by-char. That's the solution I suggest below.


          // YOUR SETTINGS
          // ---
          const KEY_PROP = 'horizontalScale';
          const CHANGE_VALUE = function(x){ return x + 0.75 };
          (function(/*fct*/f,/*str*/k,  t,a,z,dz,s,x)
          // ---------------------------
          // Range-optimized change of a character property.
          // (Covers all paragraphs containing the selection.)
              const __ = $.global.localize;
              // Selection check.
              // ---
              if( !(t=app.selection||[]).length ) return;
              if( !((t=t[0]).hasOwnProperty('paragraphs')) ) return;
              if( !(t=t.paragraphs).count() ) return;
              // Retrieve all values in an array.
              // ---
              a = t.everyItem().characters.everyItem()[k];
              if( !(z=a.length) ) return;
              // First paragraph.
              // ---
              t = t[0];
              // Range specifier pattern.
              // ---
              s = __(
                  "(%1[%%1] to %1[%%2])",
                  t.parentStory.toSpecifier() + "/insertion-point"
              // Quick Loop
              // ---
              app.scriptPreferences.enableRedraw = false;
                  a.unshift(-9999), dz=t.index, x=a[z] ;
                  z-- ;
                  x===(t=a[z]) || ((resolve(__(s,dz+z,dz+a.length-1))[k]=f(x)), (a.length=1+z), (x=t))
              app.scriptPreferences.enableRedraw = true;
          })(CHANGE_VALUE, KEY_PROP);


          The code may seem a bit cryptic (because it's a kind of abstraction from the original question), but I hope it may still help you.




          • 2. Re: Change horizontal Scale of characters with different horizontal Scale
            goldgoldgold Level 1

            Thank you! It just does the job in an excellent way!
            And I learned more correctly to approach the problem. Also for that thank you very much!