Copy link to clipboard
Copied
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?
The third argument of the function Ā»ellipseShapeLayerĀ« is the Stroke Width (3 in the code I posted), feel free to change it.
I also cannot add other effects like gradients, color overlays to this dialog.
Please explain what you mean with screenshots.
// 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(strin
...
Copy link to clipboard
Copied
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;
};
};
Copy link to clipboard
Copied
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.
Copy link to clipboard
Copied
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.
Copy link to clipboard
Copied
This is the notification I received. I'm not good at using scripts because I'm not a programmer. So... it would be great if you could help me if it doesn't take too long (ą²„ļ¹ą²„)
Copy link to clipboard
Copied
// based on code by michael l hale;
// 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]);
app.preferences.rulerUnits = originalRulerUnits;
};
////// 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;
};
};
////// 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")}
};
Copy link to clipboard
Copied
Oh my gosh, thank you so much, I just have a small question. It seems that the line drawing of the image created by the script is much thicker than the drawing line created by Photoshop. I also cannot add other effects like gradients, color overlays to this dialog. Why does this happen?
Copy link to clipboard
Copied
The third argument of the function Ā»ellipseShapeLayerĀ« is the Stroke Width (3 in the code I posted), feel free to change it.
I also cannot add other effects like gradients, color overlays to this dialog.
Please explain what you mean with screenshots.
Copy link to clipboard
Copied
What I mean is that the thickness of the shape created by the script is different from the thickness of the shape created by Photoshop even though it has the same parameter of 3px. I think if I change the number in line 103 from 2 to 1 and can use action to handle the rest easily.
And I know this is excessive but can you do this with rectangles and custom shapes (with a certain name)? I don't know how to repay you guys but this script can really change my life (ć„ļæ£ Ā³ļæ£)ć„
Regarding "I also can't add other effects like gradients, color overlays to this dialog." My bad, everything still works perfectly using your code xD
Copy link to clipboard
Copied
Please post screenshots including the pertinent Panels.
I donāt understand what the problem is.
Is the ellipse offset or is the stroke width the issue?
What is the resolution of the image?
Copy link to clipboard
Copied
Copy link to clipboard
Copied
I donāt understand what the problem or the intended workflow is.
As for a Custom Shape via Script.
// place custom shape;
// 2024, use it at your own risk;
placeCustomShape ("Ape", [0,255,255], [0,0,200,334], 10, [0,0,0]);
////// place custom shape //////
function placeCustomShape (theName, theColor, theBounds, strokeWidth, strokeColor) {
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" ), true );
desc38.putBoolean( stringIDToTypeID( "fillEnabled" ), true );
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();
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 );
};
Copy link to clipboard
Copied
First at all, thank you so much for continuing to reply to me~
My work is comic typesets, so these parameters need to be accurate. But, I think the stroke-related problems will stop here because I can handle them with a little action.
As for the Custom Shape, I could combine your code with the previous code for Elipse but it doesn't work ą² āā®ą²
To explain a bit, sometimes we will work with speech bubbles that are not ellipse or rectangle shapes, the image below is an example of Custom shape.
Copy link to clipboard
Copied
What does not work out with the Script?
Please post the Script and screenshots to illustrate the error.
Copy link to clipboard
Copied
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...
Copy link to clipboard
Copied
Please donāt just talk about code you are having problems with, post it and provide a meaningful description of how it does not do what you want. (In this case please also provide the test file and the custom shape file.)
Copy link to clipboard
Copied
// 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 );
};
Copy link to clipboard
Copied
I wonder, though, why you use the Stroke on the Type Layer at all.
Couldnāt you just add/subtract the number to/from the Type Layerās original Bounds?
Copy link to clipboard
Copied
Every publisher we work with requires a "certain amount of space" between the text and the bubble border (maybe, 100px, 80px, 83px,...). So we could just define that distance with the stroke (the green stroke you saw) and started adjusting the size of the speech bubbles to fit them manually over the last year until when I get your help. So I think it's more convenient for the script to work depending on random strokes.
Copy link to clipboard
Copied
i don't know why but i can't reply anymore. Thank you so much!
Copy link to clipboard
Copied
Your script is very awesome, man! Could you make it run with all text in a group automatically?
Copy link to clipboard
Copied
Please provide a sample file.
If itās about Type Layers why only the ones in a Group (how is the Group identifyable?) and not all Type Layers in the file?
Copy link to clipboard
Copied
Edit: This Script would create Shape Layers depending on the Type Layers in the Group in which the active Layer resides (see screenshots).
// create custom shape layer based on layer bounds including styles of type layers in group;
// 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 parentID = layerDesc.getInteger(stringIDToTypeID("parentLayerID"));
// collect type layers from parent group;
if (isGroupByID(parentID) == true) {
var theLayers = collectTypeLayersInGroupOfID(parentID);
// process layers;
for (var m = 0; m < theLayers.length; m++) {
var b1 = theLayers[m][3];
var b2 = theLayers[m][4];
selectLayerByID(theLayers[m][2], false);
// 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]);
}
};
// reset;
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 );
};
////// collect layers in group of name //////
function collectTypeLayersInGroupOfID (theTargetID) {
var theLayers = new Array;
// get number of layers;
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID('property'), stringIDToTypeID('numberOfLayers'));
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
for (var m = 0; m <= theNumber; m++) {
try {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), m);
var layerDesc = executeActionGet(ref);
var theName = layerDesc.getString(stringIDToTypeID('name'));
/*var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));*/
var isTypeLayer = layerDesc.hasKey(stringIDToTypeID("textKey"));
var theParentId = layerDesc.getInteger(stringIDToTypeID('parentLayerID'));
// if type layer in group collect values;
if (isTypeLayer == true && theParentId == theTargetID) {
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
var b1 = layerDesc.getObjectValue(stringIDToTypeID("bounds"));
var b2 = layerDesc.getObjectValue(stringIDToTypeID("boundsNoEffects"));
theLayers.push([theName, theIndex, theID, b1, b2]);
};
}
catch (e) {};
};
return theLayers
};
//////
function isGroupByID (theID) {
var ref = new ActionReference();
ref.putIdentifier( charIDToTypeID("Lyr "), theID );
//ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
if (layerSet == "layerSectionStart") {return true}
else {return false}
};
// based on code by mike hale, via paul riggott;
function selectLayerByID(id,add){
add = undefined ? add = false:add
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID("Lyr "), id);
var desc = new ActionDescriptor();
desc.putReference(charIDToTypeID("null"), ref );
if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) );
desc.putBoolean( charIDToTypeID( "MkVs" ), false );
try{
executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
}catch(e){
alert(e.message);
}
};
Copy link to clipboard
Copied
this is exactly what I need! Thank you very very much!!
Copy link to clipboard
Copied
I have a video describing the process: https://drive.google.com/file/d/1t56qFBfstzOBdUlqePYwv2Zl4yUxqRIl/view?usp=sharing