Skip to main content
Participant
April 3, 2023
Question

Applying random weight values to individual characters in a variable font

  • April 3, 2023
  • 2 replies
  • 849 views

Hello!

I am trying to apply different random weight values to each character in a text frame that uses a variable font in InDesign. I've attempted to write a script to achieve this, but I'm having trouble getting it to work as intended. Here's the code I've written:

 

 

 

if (app.documents.length > 0 && app.selection.length > 0) {
var selectedItem = app.selection[0];
if (selectedItem.constructor.name === 'TextFrame') {
randomizeFontWeight(selectedItem);
} else {
alert('Please select a text frame.');
}
} else {
alert('Please open a document and select a text frame.');
}

function randomizeFontWeight(textFrame) {
var appliedFont = textFrame.parentStory.appliedFont;
var fontFamily = appliedFont.fontFamily;

if (fontFamily === 'Acumin Variable Concept') { // Replace 'Acumin Variable Concept' with the name of the variable font you want to apply.
var fontWeightRange = [100, 800];
var fontWeightList = ['Thin', 'ExtraLight', 'Light', 'Regular', 'Medium', 'SemiBold', 'Bold', 'ExtraBold', 'Black'];

for (var i = 0; i < textFrame.characters.length; i++) {
var randomWeight = Math.floor(Math.random() * (fontWeightRange[1] - fontWeightRange[0] + 1)) + fontWeightRange[0];
var randomIndex = Math.floor(Math.random() * fontWeightList.length);
var randomFontStyle = fontWeightList[randomIndex];

var myTextRange = textFrame.characters[i].textStyleRanges[0];
myTextRange.appliedFont = appliedFont;
var myTextRange = textFrame.characters[i].textStyleRanges[0]; myTextRange.applyCharacterStyle(myCharacterStyle);

var myCharacterStyle = textFrame.parentStory.characterStyles.add();
myCharacterStyle.name = "RandomFontStyle";
myCharacterStyle.fontStyle = randomFontStyle;

myTextRange.applyCharacterStyle(myCharacterStyle);
}
} else {
alert('Please select a text frame with a variable font applied.');
}
}




My goal is for each character in the selected text frame with a variable font applied to have its own unique random weight value. However, my code doesn't seem to be working properly. Can anyone suggest a solution or help me improve this script to achieve my desired result?

Thank you!

 

*I've chosen the variable font "Acumin" and included it in the code. However, it would be better if the script could apply to any variable font, rather than specifying a particular variable typeface in the code.

This topic has been closed for replies.

2 replies

m1b
Community Expert
Community Expert
April 4, 2023

Hi @Jason Pp, I had trouble with this. Specifically, setting the variable design axis seemed to crash Indesign. I didn't have time for troubleshooting the problem so instead I just added in all the variable font styles—see second script below. Maybe that will be enough?

 

But if anyone get's the first script to work without crashing, please post!

- Mark

 

// NOTE: THIS CRASHED INDESIGN 18.2.1 MACOS 13.3
function main() {

    if (app.documents.length == 0
        || app.selection.length == 0
        || !app.selection[0].hasOwnProperty('parentStory')
    ) {
        alert('Please select a text frame.');
        return;
    }

    var fontFamily = 'Acumin Variable Concept',
        fontWeightRange = [100, 900],

        doc = app.activeDocument,
        story = doc.selection[0].parentStory,
        chars = story.characters;

    story.appliedFont = fontFamily;
    story.fontStyle = 'Regular';

    for (var i = chars.length - 1; i > 2; i--) {

        var ch = chars[i];
        var randomWeight = Math.floor(Math.random() * (fontWeightRange[1] - fontWeightRange[0] + 1)) + fontWeightRange[0];

        ch.setNthDesignAxis(0, randomWeight);

    }

};

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Acumin Variable Weight');

 

function main() {

    if (app.documents.length == 0
        || app.selection.length == 0
        || !app.selection[0].hasOwnProperty('parentStory')
    ) {
        alert('Please select a text frame.');
        return;
    }

    var doc = app.activeDocument;

    var fontFamily = 'Acumin Variable Concept',

        fontStyles = [
            'Condensed Thin',
            'Condensed ExtraLight',
            'Condensed Light',
            'Condensed',
            'Condensed Medium',
            'Condensed Semibold',
            'Condensed Bold',
            'Condensed Black',
            'Condensed UltraBlack',
            'SemiCondensed Thin',
            'SemiCondensed ExtraLight',
            'SemiCondensed Light',
            'SemiCondensed',
            'SemiCondensed Medium',
            'SemiCondensed Semibold',
            'SemiCondensed Bold',
            'SemiCondensed Black',
            'SemiCondensed UltraBlack',
            'ExtraCondensed Thin',
            'ExtraCondensed ExtraLight',
            'ExtraCondensed Light',
            'ExtraCondensed',
            'ExtraCondensed Medium',
            'ExtraCondensed Semibold',
            'ExtraCondensed Bold',
            'ExtraCondensed Black',
            'ExtraCondensed UltraBlack',
            'Condensed Thin',
            'Condensed ExtraLight',
            'Condensed Light',
            'Condensed',
            'Condensed Medium',
            'Condensed Semibold',
            'Condensed Bold',
            'Condensed Black',
            'Condensed UltraBlack',
            'Thin',
            'ExtraLight',
            'Light',
            'Regular',
            'Medium',
            'Semibold',
            'Bold',
            'Black',
            'UltraBlack',
            'Wide Thin',
            'Wide ExtraLight',
            'Wide Light',
            'Wide',
            'Wide Medium',
            'Wide Semibold',
            'Wide Bold',
            'Wide Black',
            'Wide UltraBlack',
            'Wide UltraBlack Italic'
        ];

    var story = doc.selection[0].parentStory,
        chars = story.characters;

    story.appliedFont = fontFamily;
    story.fontStyle = 'Regular';

    for (var i = chars.length - 1; i > 2; i--) {

        var ch = chars[i];
        var randomFontStyle = fontStyles[Math.floor(Math.random() * fontStyles.length)];

        ch.fontStyle = randomFontStyle;

    }

};


app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Acumin Variable Font Style');

 

m1b
Community Expert
Community Expert
April 4, 2023

Also, changing the *width* axis seemed to work (see below script) but was very slow. It looks like using the "pre-baked" widths will be a lot faster.

function main() {

    if (app.documents.length == 0
        || app.selection.length == 0
        || !app.selection[0].hasOwnProperty('parentStory')
    ) {
        alert('Please select a text frame.');
        return;
    }

    var fontFamily = 'Acumin Variable Concept',
        fontWeightRange = [100, 900],
        fontWidthRange = [50, 115],

        doc = app.activeDocument,
        story = doc.selection[0].parentStory,
        chars = story.characters;

    story.appliedFont = fontFamily;
    story.fontStyle = 'Regular';

    for (var i = chars.length - 1; i > 2; i--) {

        var ch = chars[i];
        var randomWeight = Math.floor(Math.random() * (fontWeightRange[1] - fontWeightRange[0] + 1)) + fontWeightRange[0];
        var randomWidth = Math.floor(Math.random() * (fontWidthRange[1] - fontWidthRange[0] + 1)) + fontWidthRange[0];

        ch.setNthDesignAxis(1, randomWidth);

    }

};

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Acumin Variable Width');
Marc Autret
Legend
April 4, 2023

Hi @m1b 

 

That's probably a case where muting enableRedraw is required, but indeed the whole process is extremely slow.

 

This worked for me in Win10 / ID 18.1 x64:

// Assuming a textframe is selected and a variable font used.
// ---
(function(/*TextFrame*/tf,  a,i)
{
  app.doScript
  (
    '''
    app.scriptPreferences.enableRedraw = false;
    for
    (
      a=tf.parentStory.characters, i=a.length ; i-- ;
      a[i].setNthDesignAxis(0, 100 + ~~(801*Math.random()) ) // Range: 100-900
    );
    app.scriptPreferences.enableRedraw = true;
    '''
    ,
    void 0,
    void 0,
    UndoModes.FAST_ENTIRE_SCRIPT
  );

})( app.selection[0] );

 

What is highly time-consuming is the DOM command Character.setNthDesignAxis(…) called N times. On my system each call takes about 4ms (really huge!), and this remains linear across the whole story. So a 2000 character text will take 8 seconds on average to be processed. And if you don't toggle enableRedraw, there are big risks that ID won't get out of this.

 

Hope that helps.

 

Best,

Marc

brian_p_dts
Community Expert
Community Expert
April 4, 2023

Haven't tested. It'd helpful if you say how it is not working, but a couple things I see: 1) you're applyying a character style before you've created it

2) you can't have two character styles with the same name (except in different style groups)