Skip to main content
Known Participant
January 16, 2024
Answered

Create a shape with the same size as the stroke of a text layer using the script

  • January 16, 2024
  • 3 replies
  • 2756 views

I want to create a script that can create a shape (circle, ellipse, or square) that is the same size as the text layer's stroke (e.g. 100px). Runs only on the current file.
I have combined a script to fill layer with canvas and some actions. But still have to open a new file to get the exact size. Does anyone have any better ideas?

 

 

This topic has been closed for replies.
Correct answer c.pfaffenbichler

Sorry for the late reply. For the past 2 days I've been trying to find a way to adjust the size of a custom shape to be the same as the stroke size (like with ellipses and rectangles). But it failed...


// create custom shape layer based on layer bounds including styles;
// 2024, use it at your own risk;
if (app.documents.length > 0) {
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
var layerDesc = executeActionGet(ref);
var b1 = layerDesc.getObjectValue(stringIDToTypeID("bounds"));
var b2 = layerDesc.getObjectValue(stringIDToTypeID("boundsNoEffects"));
//ellipseShapeLayer ([b1.getUnitDoubleValue(stringIDToTypeID("left")), b1.getUnitDoubleValue(stringIDToTypeID("top")), b1.getUnitDoubleValue(stringIDToTypeID("right")), b1.getUnitDoubleValue(stringIDToTypeID("bottom"))], false, 3, [0,0,0]);
// create custom shape layer;
placeCustomShape ("Ape", [0,255,255], [b1.getUnitDoubleValue(stringIDToTypeID("left")), b1.getUnitDoubleValue(stringIDToTypeID("top")), b1.getUnitDoubleValue(stringIDToTypeID("right")), b1.getUnitDoubleValue(stringIDToTypeID("bottom"))], 3, [0,0,0]);
app.preferences.rulerUnits = originalRulerUnits;
};
////// create ellipse shape layer //////
function ellipseShapeLayer (theBounds, theColor, strokeWidth, strokeColor) {
try {
// Make outer oval
var idPxl = charIDToTypeID( "#Pxl" );
var idPnt = charIDToTypeID( "#Pnt" );
var idClr = charIDToTypeID( "Clr " );
var idRd = charIDToTypeID( "Rd  " );
var idGrn = charIDToTypeID( "Grn " );
var idBl = charIDToTypeID( "Bl  " );
var idRGBC = charIDToTypeID( "RGBC" );
var idcontentLayer = stringIDToTypeID( "contentLayer" );
var idsolidColorLayer = stringIDToTypeID( "solidColorLayer" );
var idstrokeStyle = stringIDToTypeID( "strokeStyle" );
var idstrokeStyleLineAlignment = stringIDToTypeID( "strokeStyleLineAlignment" );
var idstrokeStyleLineJoinType = stringIDToTypeID( "strokeStyleLineJoinType" );
    var desc41 = new ActionDescriptor();
        var ref12 = new ActionReference();
        ref12.putClass( idcontentLayer );
    desc41.putReference( charIDToTypeID( "null" ), ref12 );
        var desc42 = new ActionDescriptor();
            var desc43 = new ActionDescriptor();
            if (theColor != false) {
                var desc44 = new ActionDescriptor();
                desc44.putDouble( idRd, theColor[0] );
                desc44.putDouble( idGrn, theColor[1] );
                desc44.putDouble( idBl, theColor[2] );
            desc43.putObject( idClr, idRGBC, desc44 );
            };
        desc42.putObject( charIDToTypeID( "Type" ), idsolidColorLayer, desc43 );
        var desc45 = new ActionDescriptor();
            desc45.putUnitDouble( charIDToTypeID( "Top " ), idPxl, theBounds[1] );
            desc45.putUnitDouble( charIDToTypeID( "Left" ), idPxl, theBounds[0] );
            desc45.putUnitDouble( charIDToTypeID( "Btom" ), idPxl, theBounds[3] );
            desc45.putUnitDouble( charIDToTypeID( "Rght" ), idPxl, theBounds[2] );
        desc42.putObject( charIDToTypeID( "Shp " ), charIDToTypeID( "Elps" ), desc45 );
            var desc46 = new ActionDescriptor();
            desc46.putInteger( stringIDToTypeID( "strokeStyleVersion" ), 2 );
            if (strokeWidth == 0) {desc46.putBoolean( stringIDToTypeID( "strokeEnabled" ), false )}
            else {desc46.putBoolean( stringIDToTypeID( "strokeEnabled" ), true )};
			if (theColor == false) {desc46.putBoolean( stringIDToTypeID( "fillEnabled" ), false )}
			else {{desc46.putBoolean( stringIDToTypeID( "fillEnabled" ), true )}};
            desc46.putUnitDouble( stringIDToTypeID( "strokeStyleLineWidth" ), idPnt, strokeWidth );
            desc46.putUnitDouble( stringIDToTypeID( "strokeStyleLineDashOffset" ), idPnt, 0.000000 );
            desc46.putDouble( stringIDToTypeID( "strokeStyleMiterLimit" ), 100.000000 );
            desc46.putEnumerated( stringIDToTypeID( "strokeStyleLineCapType" ), stringIDToTypeID( "strokeStyleButtCap" ), stringIDToTypeID( "strokeStyleButtCap" ) );
            desc46.putEnumerated( idstrokeStyleLineJoinType, idstrokeStyleLineJoinType, stringIDToTypeID( "strokeStyleMiterJoin" ) );
            desc46.putEnumerated( idstrokeStyleLineAlignment, idstrokeStyleLineAlignment, stringIDToTypeID( "strokeStyleAlignCenter" ) );//strokeStyleAlignOutside
            desc46.putBoolean( stringIDToTypeID( "strokeStyleScaleLock" ), false );
            desc46.putBoolean( stringIDToTypeID( "strokeStyleStrokeAdjust" ), false );
                var list3 = new ActionList();
            desc46.putList( stringIDToTypeID( "strokeStyleLineDashSet" ), list3 );
            desc46.putEnumerated( stringIDToTypeID( "strokeStyleBlendMode" ), charIDToTypeID( "BlnM" ), charIDToTypeID( "Nrml" ) );
            desc46.putUnitDouble( stringIDToTypeID( "strokeStyleOpacity" ), charIDToTypeID( "#Prc" ), 100.000000 );
                var desc47 = new ActionDescriptor();
                    var desc48 = new ActionDescriptor();
                    desc48.putDouble( idRd, strokeColor[0] );
                    desc48.putDouble( idGrn, strokeColor[1] );
                    desc48.putDouble( idBl, strokeColor[2] );
                desc47.putObject( idClr, idRGBC, desc48 );
            desc46.putObject( stringIDToTypeID( "strokeStyleContent" ), idsolidColorLayer, desc47 );
            desc46.putDouble( stringIDToTypeID( "strokeStyleResolution" ), 300 );
        desc42.putObject( idstrokeStyle, idstrokeStyle, desc46 );
    desc41.putObject( charIDToTypeID( "Usng" ), idcontentLayer, desc42 );
executeAction( charIDToTypeID( "Mk  " ), desc41, DialogModes.NO );
} catch (e) {alert ("fail")}
};
////// place custom shape //////
function placeCustomShape (theName, theColor, theBounds, strokeWidth, strokeColor) {
if (theColor == false) {fillOrNot = false;
theColor = [0,0,0]}
else {fillOrNot = true};
if (strokeColor == false) {strokeOrNot = false}
else {strokeOrNot = true};
var idcolor = stringIDToTypeID( "color" );
var idred = stringIDToTypeID( "red" );
var idgreen = stringIDToTypeID( "grain" );
var idblue = stringIDToTypeID( "blue" );
var idRGBColor = stringIDToTypeID( "RGBColor" );
var idsolidColorLayer = stringIDToTypeID( "solidColorLayer" );
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
var idstrokeStyle = stringIDToTypeID( "strokeStyle" );
var idcontentLayer = stringIDToTypeID( "contentLayer" );
var idmake = stringIDToTypeID( "make" );
    var desc33 = new ActionDescriptor();
    var idnull = stringIDToTypeID( "null" );
        var ref8 = new ActionReference();
        ref8.putClass( idcontentLayer );
    desc33.putReference( idnull, ref8 );
    var idusing = stringIDToTypeID( "using" );
        var desc34 = new ActionDescriptor();
        var idtype = stringIDToTypeID( "type" );
                var desc35 = new ActionDescriptor();
                var desc36 = new ActionDescriptor();
                desc36.putDouble( idred, theColor[0] );
                desc36.putDouble( idgreen, theColor[1] );
                desc36.putDouble( idblue, theColor[2] );
            desc35.putObject( idcolor, idRGBColor, desc36 );
        desc34.putObject( idtype, idsolidColorLayer, desc35 );
        var idshape = stringIDToTypeID( "shape" );
            var desc37 = new ActionDescriptor();
            desc37.putString( stringIDToTypeID( "name" ), theName );
            desc37.putInteger( stringIDToTypeID( "keyOriginType" ), 9 );
            desc37.putUnitDouble( stringIDToTypeID( "top" ), idpixelsUnit, theBounds[1] );
            desc37.putUnitDouble( stringIDToTypeID( "left" ), idpixelsUnit, theBounds[0] );
            desc37.putUnitDouble( stringIDToTypeID( "bottom" ), idpixelsUnit, theBounds[3] );
            desc37.putUnitDouble( stringIDToTypeID( "right" ), idpixelsUnit, theBounds[2] );
        desc34.putObject( idshape, stringIDToTypeID( "customShape" ), desc37 );
            var desc38 = new ActionDescriptor();
            desc38.putInteger( stringIDToTypeID( "strokeStyleVersion" ), 2 );
            desc38.putBoolean( stringIDToTypeID( "strokeEnabled" ), strokeOrNot );
            desc38.putBoolean( stringIDToTypeID( "fillEnabled" ), fillOrNot );
            desc38.putUnitDouble( stringIDToTypeID( "strokeStyleLineWidth" ), idpixelsUnit, strokeWidth );
            desc38.putUnitDouble( stringIDToTypeID( "strokeStyleLineDashOffset" ), stringIDToTypeID( "pointsUnit" ), 0.000000 );
            desc38.putDouble( stringIDToTypeID( "strokeStyleMiterLimit" ), 100.000000 );
            desc38.putEnumerated( stringIDToTypeID( "strokeStyleLineCapType" ), stringIDToTypeID( "strokeStyleLineCapType" ), stringIDToTypeID( "strokeStyleButtCap" ) );
            desc38.putEnumerated( stringIDToTypeID( "strokeStyleLineJoinType" ), stringIDToTypeID( "strokeStyleLineJoinType" ), stringIDToTypeID( "strokeStyleMiterJoin" ) );
            desc38.putEnumerated( stringIDToTypeID( "strokeStyleLineAlignment" ), stringIDToTypeID( "strokeStyleLineAlignment" ), stringIDToTypeID( "strokeStyleAlignCenter" ) );
            var idstrokeStyleScaleLock = stringIDToTypeID( "strokeStyleScaleLock" );
            desc38.putBoolean( idstrokeStyleScaleLock, false );
            desc38.putBoolean( stringIDToTypeID( "strokeStyleStrokeAdjust" ), false );
                var list5 = new ActionList();
            desc38.putList( stringIDToTypeID( "strokeStyleLineDashSet" ), list5 );
            desc38.putEnumerated( stringIDToTypeID( "strokeStyleBlendMode" ), stringIDToTypeID( "blendMode" ), stringIDToTypeID( "normal" ) );
            desc38.putUnitDouble( stringIDToTypeID( "strokeStyleOpacity" ), stringIDToTypeID( "percentUnit" ), 100.000000 );
                var desc39 = new ActionDescriptor();
                if (strokeOrNot == true) {
                    var desc40 = new ActionDescriptor();
                    desc40.putDouble( idred, strokeColor[0] );
                    desc40.putDouble( idgreen, strokeColor[1] );
                    desc40.putDouble( idblue, strokeColor[2] );
                desc39.putObject( idcolor, idRGBColor, desc40 );
                };
            desc38.putObject( stringIDToTypeID( "strokeStyleContent" ), idsolidColorLayer, desc39 );
            desc38.putDouble( stringIDToTypeID( "strokeStyleResolution" ), 300.000000 );
        desc34.putObject( idstrokeStyle, idstrokeStyle, desc38 );
    desc33.putObject( idusing, idcontentLayer, desc34 );
executeAction( idmake, desc33, DialogModes.NO );
};

3 replies

Participant
January 21, 2024

To create a script that automatically creates a shape (circle, ellipse, or square) with the same size as the text layer's stroke in Photoshop and runs only on the current file, you can use the following JavaScript code. This script assumes that the text layer with the stroke is selected.

javascriptCopy code
// Ensure we have an active document if (app.activeDocument) { var textLayer = app.activeDocument.activeLayer; // Check if the active layer is a text layer if (textLayer.kind == LayerKind.TEXT) { // Get the size of the text layer's stroke var strokeSize = textLayer.textItem.strokeWidth; // Create a new shape layer (circle, ellipse, or square) var shapeLayer = createShapeLayer(strokeSize); // Select the new shape layer shapeLayer.selected = true; } else { alert("Please select a text layer with a stroke."); } } else { alert("Open a document before running this script."); } // Function to create a shape layer with the specified size function createShapeLayer(size) { // Create a new shape layer var shapeLayer = app.activeDocument.artLayers.add(); shapeLayer.kind = LayerKind.SHAPE; shapeLayer.name = "Shape Layer"; // Set the shape color (you can customize this) var shapeColor = new SolidColor(); shapeColor.rgb.red = 255; shapeColor.rgb.green = 0; shapeColor.rgb.blue = 0; // Create a new ellipse shape path var ellipsePath = shapeLayer.pathItems.ellipse( app.activeDocument.width / 2 - size / 2, app.activeDocument.height / 2 - size / 2, size, size ); // Fill the shape with the specified color shapeLayer.fill = shapeColor; return shapeLayer; }

This script checks if there is an active document and if the active layer is a text layer. If conditions are met, it gets the stroke size of the text layer and creates a new shape layer (ellipse, circle, or square) with the same size. Adjust the color and shape type as needed. Save this script with a .jsx extension and run it from the Photoshop Scripts menu.

 
NahidkuAuthor
Known Participant
January 21, 2024

Thank you for the script. When I run this message appears. Btw, I'm stuck with custom shape for now...

 

 

Participant
January 20, 2024

The function »ellipseShapeLayer« takes the Stroke Width as its third argument, which is set to 3 in the provided code. You can modify this value as needed.

NahidkuAuthor
Known Participant
January 21, 2024

I tried changing this parameter from 3 to 1. But the stroke became 12.5px instead of 3px.

 

c.pfaffenbichler
Community Expert
Community Expert
January 16, 2024

What »new file« gives you what »exact size«? 

Could you please post screenshots with the pertinent Panels (Toolbar, Layers, Options Bar, …) visible? 

 

If you need the bounds with and/or without the Layer Style you can get that directly. 

// based on code by michael l hale;
// 2024, use it at your own risk;
if (app.documents.length > 0) {
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
var layerDesc = executeActionGet(ref);
var b1 = layerDesc.getObjectValue(stringIDToTypeID("bounds"));
var b2 = layerDesc.getObjectValue(stringIDToTypeID("boundsNoEffects"));
checkDesc2 (b1);
checkDesc2 (b2);
};
////// based on code by michael l hale //////
function checkDesc2 (theDesc) {
var c = theDesc.count;
var str = '';
for(var i=0;i<c;i++){ //enumerate descriptor's keys
	str = str + 'Key '+i+' = '+typeIDToStringID(theDesc.getKey(i))+': '+theDesc.getType(theDesc.getKey(i))+'\n'+getValues (theDesc, i)+'\n';
	};
alert("desc\n\n"+str);
};
////// check //////
function getValues (theDesc, theNumber) {
switch (theDesc.getType(theDesc.getKey(theNumber))) {
case DescValueType.ALIASTYPE:
return theDesc.getPath(theDesc.getKey(theNumber));
break;
case DescValueType.BOOLEANTYPE:
return theDesc.getBoolean(theDesc.getKey(theNumber));
break;
case DescValueType.CLASSTYPE:
return theDesc.getClass(theDesc.getKey(theNumber));
break;
case DescValueType.DOUBLETYPE:
return theDesc.getDouble(theDesc.getKey(theNumber));
break;
case DescValueType.ENUMERATEDTYPE:
return (typeIDToStringID(theDesc.getEnumerationValue(theDesc.getKey(theNumber)))+"_"+typeIDToStringID(theDesc.getEnumerationType(theDesc.getKey(theNumber))));
break;
case DescValueType.INTEGERTYPE:
return theDesc.getInteger(theDesc.getKey(theNumber));
break;
case DescValueType.LISTTYPE:
return theDesc.getList(theDesc.getKey(theNumber));
break;
case DescValueType.OBJECTTYPE:
return (theDesc.getObjectValue(theDesc.getKey(theNumber))+"_"+typeIDToStringID(theDesc.getObjectType(theDesc.getKey(theNumber))));
break;
case DescValueType.RAWTYPE:
return theDesc.getReference(theDesc.getData(theNumber));
break;
case DescValueType.REFERENCETYPE:
return theDesc.getReference(theDesc.getKey(theNumber));
break;
case DescValueType.STRINGTYPE:
return theDesc.getString(theDesc.getKey(theNumber));
break;
case DescValueType.UNITDOUBLE:
return (theDesc.getUnitDoubleValue(theDesc.getKey(theNumber))+"_"+typeIDToStringID(theDesc.getUnitDoubleType(theDesc.getKey(theNumber))));
break;
default: 
break;
};
};

 

NahidkuAuthor
Known Participant
January 16, 2024

I will convert the stroke of the text layer to a layer -> copy it to a new document (this document will have the correct size) -> create a shape and use the script to resize it to the same size as the canvas -> copy the shape and rotate Return to the original file -> align shape and original text layer. That's what I did.

c.pfaffenbichler
Community Expert
Community Expert
January 16, 2024

Please try the code I posted with with a Layer that has a Stroke applied selected. 

You should get two alerts – one with the bounds of the Layer including the Style, one with the bounds excluding the Style.