Copy link to clipboard
Copied
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.horizontalScale = m.horizontalScale-(SASH.text*1)}
catch (e) {m.horizontalScale = m.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;
pi.select(SelectionOptions.ADD_TO);
}
var myChar=app.activeDocument.selection[0].characters;
for (a=0;a<myChar.length;a++){
myChar.horizontalScale = (myChar.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!!
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 examp
...Copy link to clipboard
Copied
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()
; 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;
for(
a.unshift(-9999), dz=t.index, x=a
; z-- ;
x===(t=a
) || ((resolve(__(s,dz+z,dz+a.length-1)) =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.
@+
Marc
Copy link to clipboard
Copied
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!