Last active
March 12, 2024 13:24
-
-
Save creold/c6fbad64b836d3d610b0f1c19996e42a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Make highlighting rectangle based on size of TextFrame | |
Discussion: https://community.adobe.com/t5/illustrator-discussions/script-make-rectangle-based-on-size-of-object-on-layer/td-p/13383600 | |
Author: Sergey Osokin, email: [email protected] | |
Check my other scripts: https://github.com/creold | |
Donate (optional): | |
If you find this script helpful, you can buy me a coffee | |
- via Buymeacoffee: https://www.buymeacoffee.com/aiscripts | |
- via Donatty https://donatty.com/sergosokin | |
- via DonatePay https://new.donatepay.ru/en/@osokin | |
- via YooMoney https://yoomoney.ru/to/410011149615582 | |
*/ | |
//@target illustrator | |
app.preferences.setBooleanPreference('ShowExternalJSXWarning', false); // Fix drag and drop a .jsx file | |
function main() { | |
if (!documents.length) return; | |
if (!selection.length || selection[0].typename !== 'TextFrame') return; | |
polyfills(); | |
var ratioW = 0.5 // Width scale | |
var ratioH = 0.5 // Height scale | |
var isXHeight = false; | |
var color = new RGBColor(); | |
color.red = 255; | |
color.green = 235; | |
color.blue = 0; | |
var inp = prompt('Enter parameters:\nwidth scale ratio (decimal),\nheight: x-height (x) or cap height (c)', ratioW + ',' + ratioH + 'c', 'Highlight Text'); | |
if (!inp.length || inp !== null) { | |
inp = inp.split(','); | |
if (!isNaN(inp[0])) ratioW = parseFloat(inp[0]); | |
if (/x/i.test(inp[1]) == 'x') isXHeight = true; | |
else if (/c/i.test(inp[1]) == 'x') isXHeight = false; | |
if (!isNaN(parseFloat(inp[1]))) ratioH = parseFloat(inp[1]); | |
} | |
var tfs = getTextFrames(selection); | |
var rects = []; | |
tfs.forEach(function (e) { | |
if (e.lines.length > 1) { | |
var lines = divide(e.layer, e); | |
lines.forEach(function (l) { | |
rects = rects.concat(drawHighlightRect(l, color, ratioW, ratioH, isXHeight, e)); | |
}); | |
// Remove line-breaking TextFrame | |
for (var i = lines.length - 1; i >= 0; i--) { | |
lines[i].remove(); | |
} | |
} else { | |
rects.push(drawHighlightRect(e, color, ratioW, ratioH, isXHeight)); | |
} | |
}); | |
if (rects.length) selection = rects; | |
} | |
// Setup JavaScript Polyfills | |
function polyfills() { | |
Array.prototype.forEach = function (callback, startPos, inc) { | |
startPos = startPos || 0; | |
inc = inc || 1; | |
for (var i = startPos; i < this.length; i += inc) | |
callback(this[i], i, this); | |
}; | |
} | |
// Get TextFrames array from collection | |
function getTextFrames(coll) { | |
var tfs = []; | |
for (var i = 0, len = coll.length; i < len; i++) { | |
if (/text/i.test(coll[i].typename)) tfs.push(coll[i]); // coll[i].kind == TextType.POINTTEXT | |
else if (/group/i.test(coll[i].typename)) tfs = tfs.concat(getTextFrames(coll[i].pageItems)); | |
} | |
return tfs; | |
} | |
function drawHighlightRect(tf, color, ratioW, ratioH, isX, dest) { | |
if (arguments.length == 4 || !dest) dest = tf; | |
selection = null; | |
tf.selected = true; | |
var coords = getCoords(tf, ratioW, isX); | |
var rect = tf.layer.pathItems.rectangle(coords.t - (0.5 * (1 - ratioH) * coords.h), coords.l, coords.w * ratioW, ratioH * coords.h); | |
rect.fillColor = color; | |
rect.stroked = false; | |
rect.move(dest, ElementPlacement.PLACEAFTER); | |
return rect; | |
} | |
function getCoords(obj, ratioW, isX) { | |
var dup = obj.duplicate().createOutline(); | |
var bnds = dup.geometricBounds; | |
var w = dup.width; | |
dup.remove(); | |
var left = bnds[0] + w * 0.5 * (1 - ratioW); | |
dup = obj.duplicate(); | |
dup.contents = isX ? 'x' : 'X'; | |
dup.createOutline(); | |
var h = selection[0].height; | |
var top = selection[0].geometricBounds[1]; | |
selection[0].remove(); | |
return { 't': top, 'l': left, 'w': w, 'h': h }; | |
} | |
// https://community.adobe.com/t5/illustrator-discussions/break-text-area-into-text-lines/m-p/5258096 | |
function divide(relObj, item) { | |
//getObject justification and leading | |
var justification = item.textRange.justification; | |
var vSpacing = item.textRange.leading; | |
var tfTop = item.top; | |
var tfLeft = item.left; | |
var newTF; | |
var out = []; | |
for (var j = 0; j < item.lines.length; j++) { | |
newTF = relObj.textFrames.add(); | |
newTF.move(item, ElementPlacement.PLACEBEFORE); | |
item.characters[0].duplicate(newTF.insertionPoints[0]); | |
newTF.contents = item.lines[j].contents; | |
newTF.top = tfTop; | |
tfTop -= vSpacing; | |
switch (justification) { | |
case (Justification.CENTER): | |
newTF.left = (tfLeft + (item.width / 2)) - (newTF.width / 2); | |
break; | |
case (Justification.RIGHT): | |
newTF.left = (tfLeft + item.width) - newTF.width; | |
break; | |
default: | |
newTF.left = item.left; | |
} | |
out.push(newTF); | |
newTF.textRange.justification = justification; | |
} | |
return out; | |
} | |
// Run script | |
try { | |
main(); | |
} catch (e) { } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Buy Pro version https://sergosokin.gumroad.com/l/hgltext