femkeblanco
Guide
femkeblanco
Guide
Activity
‎Nov 19, 2023
03:20 AM
Thanks @Kurt Gold . The line can be deleted if it's causing an error.
... View more
‎Nov 19, 2023
03:13 AM
2 Upvotes
Below is a simple script for a grid of random symbols. It's a slow running script, so I've limited the number of symbols to 1000. Remove the limit by deleting line 2. Randomly distributed spacing may be achieved with a more complex script. (200 * 200 mm artboard.) var limit;
limit = Math.sqrt(1000);
var size = 12; // font (cell) size
var doc = app.activeDocument;
var num_x = doc.width / size;
var num_y = doc.height / size;
if (limit && num_x > limit) num_x = limit;
if (limit && num_y > limit) num_y = limit;
var x = size;
for (var i = 0; i < num_x - 1; i++) {
var y = - size;
for (var j = 0; j < num_y - 1; j++) {
var min = 32;
var max = 127;
var n = Math.floor(Math.random() * (max - min + 1)) + min;
var text = doc.textFrames.pointText( [x, y] );
text.contents = String.fromCharCode(n);
text.textRange.textFont = textFonts["TimesNewRomanPSMT"];
text.textRange.size = size;
text.textRange.justification = Justification.CENTER;
text.rotate(-90);
y = y - size;
}
x = x + size;
}
... View more
‎Nov 18, 2023
02:41 PM
4 Upvotes
My thinking was similar to @m1b , except I wasted my time doing the math long hand. As far as I can tell, the math is correct, any desired result depending on the tolerance (line 1). var tolerance = 1; // points
var doc = app.activeDocument;
var pathItems = doc.selection;
for (var i = 0; i < pathItems.length; i++) {
main(pathItems[i])
}
function main(pathItem) {
var points = pathItem.pathPoints;
var P0 = points[0].anchor;
var P1 = points[0].rightDirection;
var P2 = points[1].leftDirection;
var P3 = points[1].anchor;
// handles, i.e. distances between (1) P0 and P1 and (2) P2 and P3
var handle1 = Math.sqrt(
(P0[0] - P1[0]) * (P0[0] - P1[0]) + (P0[1] - P1[1]) * (P0[1] - P1[1])
);
var handle2 = Math.sqrt(
(P2[0] - P3[0]) * (P2[0] - P3[0]) + (P2[1] - P3[1]) * (P2[1] - P3[1])
);
// theta / 2 is angle between handle and line between anchors
var opposite1 = P1[1] - P0[1];
var adjacent1 = P1[0] - P0[0];
var angle1 = Math.atan2(opposite1, adjacent1);
var opposite2 = P3[1] - P0[1];
var adjacent2 = P3[0] - P0[0];
var angle2 = Math.atan2(opposite2, adjacent2);
var theta = (angle1 - angle2) * 2;
if (opposite2 < 0) {
theta = theta * -1;
}
// radii, if arc were circular
var alpha = 4 / 3 * Math.tan(theta / 4);
var R = handle1 / alpha;
// midpoint of curve
var M = [
(P0[0] + 3 * P1[0] + 3 * P2[0] + P3[0]) / 8,
(P0[1] + 3 * P1[1] + 3 * P2[1] + P3[1]) / 8
];
// midpoint of line between anchors
var Q = [(P0[0] + P3[0]) / 2, (P0[1] + P3[1]) / 2];
// centre of circle
var opposite = R * Math.sin(theta / 2);
var adjacent = R * Math.cos(theta / 2);
var dx1 = Q​[0] - P0[0];
var dy1 = Q[1] - P0[1];
var angle1 = Math.atan(dx1 / dy1​);
var angle2 = Math.PI / 2 - angle1;
var dx2 = adjacent * Math.sin(angle2);
var dy2 = adjacent * Math.cos(angle2);
var O = [Q[0] + dx2, Q[1] - dy2];
// distances between M and O
var MO = Math.sqrt(
(M[0] - O[0]) * (M[0] - O[0]) + (M[1] - O[1]) * (M[1] - O[1])
);
// true radii
R1 = Math.sqrt(
(O[0] - P0[0]) * (O[0] - P0[0]) + (O[1] - P0[1]) * (O[1] - P0[1])
);
R2 = Math.sqrt(
(O[0] - P3[0]) * (O[0] - P3[0]) + (O[1] - P3[1]) * (O[1] - P3[1])
);
if (areEqual(R1, MO) &&
areEqual(R2, MO)) {
var circle = doc.pathItems.ellipse(
O[1] + R, O[0] - R, R * 2, R * 2
);
circle.zOrder(ZOrderMethod.SENDTOBACK);
circle.strokeColor = doc.swatches["Black"].color;
circle.filled = false;
}
function areEqual(a, b) {
return Math.abs(a - b) < tolerance;
}
}
... View more
‎Nov 16, 2023
02:54 PM
1 Upvote
The approximation in the link is only for a "unit right" circular arc, that is to say, an arc with a radius of 1 and an angle of 90°, or a quarter circle. I presume you are dealing with arcs of unknown angles and radii, which is not as straightforward.
... View more
‎Nov 14, 2023
02:33 AM
2 Upvotes
I can't replicate the problem, possibly because I don't have Arabic enabled. Assuming it's a bug, you could just re-size. var size = layers[0].textFrames[0].textRange.size;
layers[0].textFrames[0].contents = "عنب كرز";
layers[0].textFrames[0].textRange.size = size;
... View more
‎Nov 13, 2023
02:42 AM
Copy and paste the code to a .jsx file. (You can create a .txt file and change the extension to .jsx.) Then, while your document is open in Illustrator, go to File > Scripts > Other Script (Ctrl+F12). Find the file you just created and open it; this will run the code.
... View more
‎Nov 03, 2023
12:22 PM
1 Upvote
I don't see a video or a link to one.
... View more
‎Nov 03, 2023
12:20 PM
This should output a list of words at line breaks (but not paragraph breaks). A text frame should be selected. var output = "";
var paragraphs = app.selection[0].paragraphs;
for (var i = 0; i < paragraphs.length; i++) {
var lines = paragraphs[i].lines;
for (var j = 0; j < lines.length - 1; j++) {
var index = lines[j].words.length - 1;
output += lines[j].words[index].contents + "\n";
}
}
alert(output);
... View more
‎Oct 31, 2023
01:31 PM
The script was not written with invisible and locked layers in mind. Can you share a test AI file (through a file sharing site)?
... View more
‎Oct 25, 2023
01:45 PM
I presume you want each layer saved as different PDFs and not all layers saved as the same PDFs but with different names. The script may be slow running, so test before running on a heavy document. function main() {
var folder1 = Folder.selectDialog();
var doc1 = app.activeDocument;
for (var i = 0; i < doc1.layers.length; i++) {
app.selection = null;
var layer1 = doc1.layers[i];
layer1.hasSelectedArtwork = true;
var selection = doc1.selection;
var doc2 = app.documents.add();
for (var j = 0; j < selection.length; j++) {
selection[j].duplicate(doc2, ElementPlacement.PLACEATEND);
}
var PDF1 = new PDFSaveOptions();
var name1 = layer1.name;
var file1 = new File(folder1 + "/" + name1);
doc2.saveAs(file1, PDF1);
doc2.close(SaveOptions.DONOTSAVECHANGES);
}
}
main();
... View more
‎Oct 23, 2023
04:01 PM
Regarding the first point, this is what your original script gives me. If this is what you want, and you are not getting, I would focus on debugging this. One possibility is that the script doesn't handle items >1 group deep. Could you show the hierarchy of the items in an expanded layers panel?
... View more
‎Oct 22, 2023
03:39 PM
What is the purpose of the script? Can you give the simplest example of what you are using it for?
... View more
‎Oct 22, 2023
03:37 PM
1 Upvote
I would do the first and second, skipping over any sections that may be uninteresting.
... View more
‎Oct 22, 2023
03:20 PM
1 Upvote
It used to be Lynda.com, before it was bought by LinkedIn/Microsoft in the mid 2010s.
... View more
‎Oct 22, 2023
03:11 PM
1 Upvote
I'm a fan of Deke McClelland. He wrote one of the first, if not the first, book on Illustrator in 1988. He has three courses: fundamentals, advanced and mastery. If you like and finish the first, you can move onto the other two. https://www.linkedin.com/learning/illustrator-one-on-one-fundamentals https://www.linkedin.com/learning/illustrator-one-on-one-advanced https://www.linkedin.com/learning/illustrator-one-on-one-mastery
... View more
‎Oct 22, 2023
02:47 AM
3 Upvotes
I was able to make this quickly with SVGnest, but using it will require lots of trial and error.
... View more
‎Oct 18, 2023
07:17 AM
1 Upvote
The selected Pantone/Focoltone are SpotColors that have different properties to the colors your script is accessing. The properties you are accessing are (an RGB example): swatch.color.red swatch.color.green swatch.color.blue swatch.color.typename (RGBColor) For SpotColors, you want: swatch.color.spot.color.red swatch.color.spot.color.green swatch.color.spot.color.blue swatch.color.spot.color.typename (RGBColor) swatch.color.typename (SpotColor) Add a conditional to check if a color.typename is SpotColor and, if it is, go down the above route. BTW, there's no JSON.stringify in Extendscript. How are you reading the output?
... View more
‎Oct 17, 2023
01:21 PM
Sorry to be defeatist, but this is a non-trivial packing problem that I am almost certain no one here is going to solve with a casual script.
... View more
‎Oct 16, 2023
10:08 AM
The question is unclear to me. Are you asking how to distinguish between variables from the included file and variables from the main file? If so, the answer is: not possible. Both sets of variables are added as properties to the same global object.
... View more
‎Oct 14, 2023
07:30 AM
The error implies that the script is either not saved in the right format or not being run in the right way. The script should be saved with a .jsx extension. Copy the script to a plain text file and save with a .jsx extension. I do not use a Mac, but I understand that Apple's TextEdit, by default, will save as rich text; this is not what you want; you want plain text. The script should be run from illustrator, by going through File > Scripts.
... View more
‎Oct 14, 2023
07:22 AM
Variables used in a function should be declared either before the function call or within the function. To compare colors, the components of the colors should be compared. replaceWord(/511/gim, "410");
function replaceWord(strFind, strReplace) {
var doc = app.activeDocument;
var col = new RGBColor();
col.red = 255;
col.green = 0;
col.blue = 0;
var frame, words, word;
for (var i = 0; i < doc.textFrames.length; i++) {
frame = doc.textFrames[i].textRange;
words = frame.words;
for (var j = 0; j < words.length; j++) {
word = words[j];
if (word.fillColor.red != col.red ||
word.fillColor.green != col.green ||
word.fillColor.blue != col.blue) {
new_string = word.contents.replace(strFind, strReplace)
if (new_string != word.contents) {
word.contents = new_string;
word.fillColor = col;
}
}
}
}
}
... View more
‎Oct 11, 2023
02:28 PM
1 Upvote
It's a bug. A gradient's origin, length and angle cannot be overwritten. Here's an elaborate workaround courtesy of CarlosCanto. This doubles a gradient's length (of a selected item) in the right direction: var fillcolor = app.selection[0].fillColor;
app.selection[0].filled = false;
app.selection[0].fillColor = fillcolor;
app.selection[0].fillOverprint = app.selection[0].fillOverprint;
var f = app.getScaleMatrix(200, 100); // double x
app.selection[0].transform(
f, false, false, true, false, 0, Transformation.LEFT);
... View more
‎Oct 11, 2023
10:34 AM
Your thinking is right.
... View more
‎Oct 11, 2023
10:32 AM
I can't explain this, as the script copies the text's original font and font size. What is actually changing, the font style (e.g. to bold) or the font size?
... View more
‎Oct 10, 2023
11:46 AM
Try changing this statement if (item.parent instanceof GroupItem) {
continue;
} to if (item.parent.typename == "PluginItem" ||
item.parent.typename == "GroupItem") {
continue;
}
... View more
‎Oct 10, 2023
11:14 AM
Change this line sw.name = spotName + suffix; to // if spotName has the suffix _SPOT, remove it
if (spotName.slice(-5) == "_SPOT") sw.name = spotName.slice(0, -5) + suffix
else sw.name = spotName + suffix;
... View more
‎Oct 10, 2023
01:19 AM
This should split a text frame at the beginning of a paragraph, if the color of the first character of the paragraph is the same as the first character of the first paragraph. Not extensively tested. // select 1 textFrame
var doc = app.activeDocument;
var sel = doc.selection[0];
var targetColor = sel.paragraphs[0].characters[0].fillColor;
var textFont = sel.textRange.textFont;
var size = sel.textRange.size;
var justification = sel.textRange.justification;
// divide text
var quotients = [];
var lines = 0, contents = "", colors = [];
for (var i = sel.paragraphs.length - 1; i > -1; i--) {
try {
lines = sel.paragraphs[i].lines.length + lines;
if (sel.paragraphs[i].contents == "") continue;
contents = sel.paragraphs[i].contents + "\n" + contents;
subcolors = [];
for (var j = 0; j < sel.paragraphs[i].characters.length; j++) {
subcolors.push(sel.paragraphs[i].characters[j].fillColor);
}
subcolors.push(undefined); // color corresponding to linebreak
// null crashes Illustrator
colors = subcolors.concat(colors);
if (areEqual(sel.paragraphs[i].characters[0].fillColor, targetColor)) {
var quotient = {};
quotient.lines = lines;
quotient.contents = contents;
quotient.colors = colors;
quotients.push(quotient);
lines = 0, contents = "", colors = [];
}
} catch (e) {
}
}
// re-draw textFrames
var precedingHeight = sel.geometricBounds[1];
for (var i = quotients.length - 1; i > -1; i--) {
var lines = quotients[i].lines;
var height = lines * sel.textRange.characterAttributes.leading;
var rect = doc.pathItems.rectangle(
precedingHeight, sel.geometricBounds[0], sel.width, height);
precedingHeight -= height;
var textFrame = doc.textFrames.areaText(rect);
textFrame.contents = quotients[i].contents;
textFrame.textRange.textFont = textFont;
textFrame.textRange.size = size;
textFrame.textRange.justification = justification;
for (var j = 0; j < textFrame.characters.length; j++) {
if (quotients[i].colors[j] == undefined) continue;
else textFrame.characters[j].fillColor = quotients[i].colors[j];
}
}
sel.remove();
function areEqual(o1, o2) {
for (var k in o1) {
if (o1[k] != o2[k]) return false;
}
for (var k in o2) {
if (o1[k] != o2[k]) return false;
}
return true;
}
... View more
‎Oct 09, 2023
07:32 AM
Yes, but how should the script know to make the splits at these particular places, and not any other places?
... View more
‎Oct 09, 2023
07:28 AM
I presume it's a bug. It appears that re-assigning a pathItem's height throws an "unknown scripting error" once it's a 0. This can replicated by the following: var rect = app.activeDocument.pathItems.rectangle(0, 0, 60, 60);
app.redraw();
alert("rect.height = " + rect.height);
rect.height = 0
app.redraw();
alert("rect.height = " + rect.height);
try {
rect.height = 60;
} catch (e) {
alert(e + "\nrect.height = " + rect.height + " (should be 60)");
}
... View more
‎Oct 06, 2023
08:36 AM
Can you clarify what should precipitate the split? The color of the text? A specific sentence fragment? The number of the paragraph?
... View more