Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Kerning script

Explorer ,
Jul 06, 2024 Jul 06, 2024

I'm not happy with the hanging punctuation in photoshop, but I can't work in indesign, where this feature is much more elaborate. I want to make a script with manual kerning on punctuation marks, but I can't figure out what I'm doing wrong.

function adjustPunctuationKerning() {
    var textLayer = app.activeDocument.activeLayer;
    if (textLayer.kind !== LayerKind.TEXT) {
        return; 
    }

    var textItem = textLayer.textItem;

    for (var i = 0; i < textItem.contents.length; i++) {
        var currentCharacter = textItem.contents[i];
        switch (currentCharacter) {
            case '?':
                textItem.characters[i+1].kerning = -300;
                break;
            case '!':
                textItem.characters[i+1].kerning = -100;
                break;
            case '.':
                textItem.characters[i+1].kerning = -100;
                break;
        }
    }
}

adjustPunctuationKerning();

 I don't know js well and i hope photoshop gives kerning manipulation in text layer 

enperror_0-1720260183795.png

 

TOPICS
Actions and scripting , Windows
3.6K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Jul 21, 2024 Jul 21, 2024

Screenshot 2024-07-22 at 08.05.58.pngScreenshot 2024-07-22 at 08.06.10.png

// apply properties like fonts, size, … to letters of words in selected type layer;
// kerning in this case and for all type layers in the document;
// 2024, use it at your own risk;
if (app.documents.length > 0) {
    var theRegExp = /\?/gi;
    var theTypeLayers = collectTypeLayers ();
    for (var m = 0; m < theTypeLayers.length; m++) {
	changeWordProperties (theTypeLayers[m][1], theRegExp, -500)
    }
};
//////////////////
////// change word properties //////
function changeWordProperties (
...
Translate
Adobe
Community Expert ,
Nov 29, 2024 Nov 29, 2024

The Script (from the post marked as »correct answer«) seems to insert the kerning before the question mark, as intended. 

Screenshot 2024-11-29 at 12.35.47.pngScreenshot 2024-11-29 at 12.35.53.png

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Nov 29, 2024 Nov 29, 2024

That's right, but the point doesn't change, look at the kerning before the “d”, it will be 0

enperror_0-1732882244483.png

where the kerning will be applied, it will be 0 before it

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Nov 29, 2024 Nov 29, 2024
 
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 01, 2024 Dec 01, 2024

Now I get it; if there is existing kerning (other than 0) one place before the intended kerning-change it is changed to 0. 

I don’t know why this happens, though. 

Photoshop Type Layers are kind of difficult to Script, I guess. 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 02, 2024 Dec 02, 2024

I did a test; even if I use code created with ScriptingListener.plugin that changes the kerning of two consecutive letters the first one’s is disregarded. 

So it seems likely that this is a bug in Photoshop ESTK Scripting. 

But as that is on »legacy status« as it is it doesn’t seem worth reporting as it seems unlikely to get fixed anyway. 

Edit: It does seem like a bug, but it seems one can work around it. 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 02, 2024 Dec 02, 2024

Screenshot 2024-12-02 at 13.21.26.pngScreenshot 2024-12-02 at 13.21.31.png

Please try this, it seems going backwards instead of forwards works out: 

 

 

// apply kerning before question mark;
// 2024, use it at your own risk;
if (app.documents.length > 0) {
//executeAction( stringIDToTypeID( "revert" ), undefined, DialogModes.NO );
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
var theRegExp = /\?/gi;
var theNewKerning = -500;
//////////////////
try {
var theFonts = new Array;
var theStyleRanges = new Array;
// get font of active layer;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
var theName = layerDesc.getString(stringIDToTypeID('name'));
// if not layer group collect values;
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart" && isBackground != true) {
var hasText = layerDesc.hasKey(stringIDToTypeID("textKey"));
if (hasText == true) {
var textDesc = layerDesc.getObjectValue(stringIDToTypeID('textKey'));
var theText = textDesc.getString(stringIDToTypeID('textKey'));
var paragraphRangeList = textDesc.getList(stringIDToTypeID('paragraphStyleRange'));
var kernRange = textDesc.getList(stringIDToTypeID('kerningRange'));
var rangeList = textDesc.getList(stringIDToTypeID('textStyleRange'));
// process the list;
for (var o = 0; o < rangeList.count; o++) {
var thisList = rangeList.getObjectValue(o);
var theFrom = thisList.getInteger(stringIDToTypeID('from'));
var theTo = thisList.getInteger(stringIDToTypeID('to'));
var styleDesc = thisList.getObjectValue(stringIDToTypeID('textStyle'));
var aSize = styleDesc.getUnitDoubleValue(charIDToTypeID( "Sz  " ));
// check for default font;
if (styleDesc.hasKey(stringIDToTypeID('fontPostScriptName')) == true) {var aFont = styleDesc.getString(stringIDToTypeID('fontPostScriptName'))}
else {
    var theDefault = styleDesc.getObjectValue(stringIDToTypeID('baseParentStyle'));	
    var aFont = theDefault.getString(stringIDToTypeID('fontPostScriptName'));
    };
if (styleDesc.hasKey(stringIDToTypeID('impliedFontSize')) == true) {var aFont = styleDesc.getString(stringIDToTypeID('fontPostScriptName'))}
// add to array;
theFonts.push([aFont, aSize, theFrom, theTo]);
theStyleRanges.push(thisList.getObjectValue(stringIDToTypeID('textStyle')));
}
}
};
// the change arrays;
var theColors = [[128,0,0], [128,128,0], [0,128,0],[0,128,128], [0,0,128], [128,0,128]];
var newFonts = ["MyriadPro-Regular", "MyriadPro-Bold", "Times-BoldItalic"];
var theBaselineShift = 10;
// change text;
// =======================================================
var idPxl = charIDToTypeID( "#Pxl" );
var idPnt = charIDToTypeID( "#Pnt" );
var idTxtt = charIDToTypeID( "Txtt" );
var idFrom = charIDToTypeID( "From" );
var idT = charIDToTypeID( "T   " );
var idTxtS = charIDToTypeID( "TxtS" );
var idTxLr = charIDToTypeID( "TxLr" );
var idTxt = charIDToTypeID( "Txt " );
var idsetd = charIDToTypeID( "setd" );
    var desc6 = new ActionDescriptor();
    var idnull = charIDToTypeID( "null" );
        var ref1 = new ActionReference();
        ref1.putEnumerated( idTxLr, charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt"  ));
    desc6.putReference( idnull, ref1 );
        var desc7 = new ActionDescriptor();
        desc7.putString( idTxt, theText );
            var list2 = new ActionList();
//////////////////
// define each letter individually;
var theIndex = 0;
var theRef = theStyleRanges[theIndex];
var theRef2 = theFonts[theIndex];
var theSize = theStyleRanges[theIndex].getUnitDoubleValue(charIDToTypeID( "Sz  " ));
for (var m = 0; m < theText.length; m++) {
// check for relevant style range;
        anIndex = Math.floor(Math.random() * (theColors.length))
        if (m == theRef2[3]) {
            theIndex++;
            var theRef = theStyleRanges[theIndex];
            var theRef2 = theFonts[theIndex];
            var theSize = theStyleRanges[theIndex].getUnitDoubleValue(charIDToTypeID( "Sz  " ));
            };
        var desc14 = new ActionDescriptor();
        desc14.putInteger( idFrom, m );
        desc14.putInteger( idT, m+1 );
        var theStyle = theRef;
//////////////////
/*// color;
        var desc21 = new ActionDescriptor();
        desc21.putDouble( charIDToTypeID( "Rd  " ), theColors[anIndex][0] );
        desc21.putDouble( charIDToTypeID( "Grn " ), theColors[anIndex][1]  );
        desc21.putDouble( charIDToTypeID( "Bl  " ), theColors[anIndex][2]  );
        theStyle.putObject( charIDToTypeID( "Clr " ), charIDToTypeID( "RGBC" ), desc21 );
// font;
        var aRandomFont = newFonts[Math.floor(Math.random()*newFonts.length)];
        theStyle.putString( stringIDToTypeID( "fontPostScriptName" ), aRandomFont);
// size;
        var thisSize = theSize *  (0.99 + Math.random() * 0.02);
        theStyle.putUnitDouble( charIDToTypeID( "Sz  " ), idPxl, thisSize );
        theStyle.putUnitDouble( stringIDToTypeID( "impliedFontSize" ), idPxl, thisSize );
// baseline shift:
        var thisShift = theBaselineShift * (0.5 - Math.random());
        theStyle.putUnitDouble( charIDToTypeID( "Bsln" ), idPxl, thisShift );
        theStyle.putUnitDouble( stringIDToTypeID( "impliedBaselineShift" ), idPxl, thisShift );*/
//////////////////
        desc14.putObject( stringIDToTypeID('textStyle'), stringIDToTypeID('textStyle'), theStyle);
        list2.putObject( charIDToTypeID( "Txtt" ),  desc14);
        };
// kerning range;
var list3 = new ActionList();
if (kernRange.count > 0) {
var kernIndex = kernRange.count-1;
var thisOne = kernRange.getObjectValue(kernIndex);
var theFrom = thisOne.getInteger(charIDToTypeID("From"));
var theTo = thisOne.getInteger(charIDToTypeID( "T   " ));
var theKerning = thisOne.getInteger(stringIDToTypeID("kerning"));
} else {theFrom = undefined};
for (var m = theText.length-1; m >= 0; m--) {
    if (m == theFrom) {
        var desc15 = new ActionDescriptor();
        desc15.putInteger( idFrom, m );
        desc15.putInteger( idT, m+1 );
        desc15.putInteger( charIDToTypeID( "Krng" ), theKerning);
        list3.putObject( stringIDToTypeID( "kerningRange"),  desc15);
            kernIndex--;
            if (kernIndex >= 0) {
            var thisOne = kernRange.getObjectValue(kernIndex);
            var theFrom = thisOne.getInteger(charIDToTypeID("From"));
            var theTo = thisOne.getInteger(charIDToTypeID( "T   " ));
            var theKerning = thisOne.getInteger(stringIDToTypeID("kerning"));
            }
        };
    if (theText[m].match(theRegExp) != null) {
        var desc15 = new ActionDescriptor();
        desc15.putInteger( idFrom, m-1 );
        desc15.putInteger( idT, m );
        desc15.putInteger( charIDToTypeID( "Krng" ), theNewKerning);
        list3.putObject( stringIDToTypeID( "kerningRange"),  desc15);
        };
    };
//////////////////
    desc7.putList( idTxtt, list2 );
    desc7.putList( stringIDToTypeID( "kerningRange"), list3);
//////////////////
    desc6.putObject( idT, idTxLr, desc7 );
executeAction( idsetd, desc6, DialogModes.NO );
}
catch (e) {};
app.preferences.rulerUnits = originalRulerUnits;
};

 

edited 2024-12-03

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Dec 03, 2024 Dec 03, 2024

What version of photoshop are you using? I tried to use the script, but on versions 2024 (25.12, 25.06, 25.03) I got one error 8800 and that the “revert” function is not available in the current version. I also tried on the latest version (26.1) and 2022 (23.1.0) but the error is the same. on pc

enperror_0-1733212765021.png

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 03, 2024 Dec 03, 2024
LATEST

I updated the code, please try again. 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines