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

Scattered Letters. Need help with algorithm

Guide ,
Jun 29, 2022 Jun 29, 2022

Copy link to clipboard

Copied

I have about 500 different text layers (different number of letters, different design):

2022-06-29_23-35-59.png

I need to arrange them all like this:

2022-06-29_23-36-52.png

(i.e. random resizing of letters, random rotation)

 

It's hard to do it by hand, so I'm planning to write a script. I do not need ready-made code, but it is interesting to hear any thoughts about how this can be automated ¯\_(ツ)_/¯

TOPICS
Actions and scripting

Views

911

Translate

Translate

Report

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 2 Correct answers

People's Champ , Jun 30, 2022 Jun 30, 2022

Вот исходник первого скрипта. Декодер нужен?

try {
    app.activeDocument.suspendHistory("Split Text", "ok = f()");
} catch (e) {
    alert(e);
}
if (ok) {
    alert("Done!")
}

function f() {
    try {
        try {
            activeDocument.activeLayer.textItem;
        } catch (e) {
            alert("Not a text layer");
            return false;
        }
        try {
            activeDocument.activeLayer.textItem.font;
        } catch (e) {
            alert("Yor text layer is bad.\n\nPl
...

Votes

Translate

Translate
Community Expert , Jul 09, 2022 Jul 09, 2022

Shape Layers might work out after all, because the path data collected via DOM differs from the one collected via AM and that may allow to determine which subPathItems »belong together«. 

separateLettersFromTypeLayerScr.gif

 

// create shape layer for each letter in a type layer;
// just for rgb;
// 2022, use it at your own risk;
if (app.documents.length > 0) {
var myDocument = app.activeDocument;
var theLayer = myDocument.activeLayer;
// check if active layer is type layer;
if (theLayer.kind == LayerKind.TEXT) {
    app.togglePa
...

Votes

Translate

Translate
Adobe
Community Expert ,
Jun 29, 2022 Jun 29, 2022

Copy link to clipboard

Copied

I'd be interested to see what the scripters come up with here. When you look at the letters the random size and rotation is probably the easy part. Arranging them so that they then touch with no gaps or overlaps (despite the varying shapes) might be a lot harder.

I watch with interest 🙂

Dave

Votes

Translate

Translate

Report

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
Guide ,
Jun 29, 2022 Jun 29, 2022

Copy link to clipboard

Copied

Random size and rotation look like the easiest operation when processed manually, but when working with a script, this is the most difficult part. The problem is that at the input I have more than 500 files with text layers already typed and styled. And I need to split each existing text layer into letters in such a way as to isolate each letter at the same time and keep its position in the layout (x, y)

The slight overlap of letters doesn't really bother me - just enough to make the text readable. In any case, if the letter isolation problem is solved, then we can get their exact boundaries and the overlap problem can also be solved (if necessary).

I have one solution to this problem, but it seems very cumbersome to me. I started writing it, but I hope that someone can come up with an easier way

Votes

Translate

Translate

Report

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 ,
Jun 30, 2022 Jun 30, 2022

Copy link to clipboard

Copied

Have you checked out yet if converting the Type Layer to a Shape Layer results in identifyable subPathItems for each letter or if »holes« lose reference to their original letter? 

Naturally a Shape Layer-approach would mean one would have to recolor the individual resulting Shape Layers, so not ideal. 

Votes

Translate

Translate

Report

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
Guide ,
Jun 30, 2022 Jun 30, 2022

Copy link to clipboard

Copied

I thought about this way, but it looks extremely complicated - some of the letters consist of more than one path, that is, it cannot be considered that one path segment is one letter 😞

Votes

Translate

Translate

Report

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
People's Champ ,
Jun 29, 2022 Jun 29, 2022

Copy link to clipboard

Copied

Привет.

А что значит "алгоритм"? Это значит шоб красиво было? : )

Руками как сам это делаешь?

У меня только одна мысль. Текст должен быть на пути. Скрит считывает данные текстового слоя. Меняет рэндомно точки пути  (path в textShape). Выше-ниже, право-лево, добавляет новые. Первую и последнюю может не трогать. Также произвольно меняет стиль для каждой буквы, типа цвет, размер, проч. Загоняет обновлённый дескриптор textKey обратно в слой.

 

Не проверял, но должно работать, в смысле корявить текст.

А вот насчет, чтоб смотрибельно было, это уж... )

 

Votes

Translate

Translate

Report

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
Guide ,
Jun 30, 2022 Jun 30, 2022

Copy link to clipboard

Copied

Алгоритм - это просто описание действий, которые можно повторить.
Руками копирую весь слой по количеству букв, затем в каждом слое оставляю по одной букве (при этом, естественно, позиция буквы сползает и я ее руками ставлю на место), после чего кручу-верчу.

Вариант с путями интересный.

Votes

Translate

Translate

Report

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
People's Champ ,
Jun 30, 2022 Jun 30, 2022

Copy link to clipboard

Copied

По разбивке на буквы постотри здесь https://community.adobe.com/t5/photoshop-ecosystem-discussions/split-text-into-a-single/m-p/10083604...

Только что проверил, работает.

 

Нет исходного кода. Посмотрю вечером, где-то валялся декодер jsxbin. Тогда и сам посмотрю, что я там наваял. В упор не помню. : )

 

 

Votes

Translate

Translate

Report

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
Guide ,
Jun 30, 2022 Jun 30, 2022

Copy link to clipboard

Copied

У меня он аккуратно складывает буквы в одну стопочку 🙂 Хотя пока смотрел как он работает появилась еще одна идея - после разбиения слоя на буквы я могу сделать исходный текст, например, черным и последовательно окрашивать каждую букву в белый цвет. Это позволит создать пиксельную маску, по которой можно позиционировать соответствующую букву из стопки.

Votes

Translate

Translate

Report

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
People's Champ ,
Jun 30, 2022 Jun 30, 2022

Copy link to clipboard

Copied

Для многострочных (но с одним стилем) у меня разбивает.

Там есть ниже другая, ускоренная версия. Проверь.

Votes

Translate

Translate

Report

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
Guide ,
Jun 30, 2022 Jun 30, 2022

Copy link to clipboard

Copied

Да, работает. Но при определенных условиях (под исходным текстовым слоем должен быть пиксельный слой), ему явно мешают эффекты, плюс почему-то спотыкается на середине второй строки. Но суть я понял. Спасибо!

2022-06-30_10-51-18.png

П.С. декодер есть.

Votes

Translate

Translate

Report

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
People's Champ ,
Jun 30, 2022 Jun 30, 2022

Copy link to clipboard

Copied

А ещё можно делать через маску. Делаешь копию слоя. Все буквы в черное, нужная в белое. Делаешь через калькуляцию выделение из канала (напрмер Gray) этого слоя. Вспомогательные слои не нужны. Эффекты не мешают. Выделение можно "расширить" через квикмаск и тресхолд. Накладываешь маску на копию оригинального слоя. Из плюсов - сохраняется оригинальный текст. Геморр - если обнаружится оперчатка, а текст тю-тю..

 

Votes

Translate

Translate

Report

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
Guide ,
Jun 30, 2022 Jun 30, 2022

Copy link to clipboard

Copied

Пошел по пути масок. Чтобы не было проблем с эффектами (и окружением слоя) сначала конвертирую его в смарт-объект (соответственно эффекты переношу на смарт-объект, а с текстом без оформления работаю внутри слоя), маски немного по другому сделал, но вроде работает.

Из явных проблем:

- не учитывал ситуацию с дефолтными стилями (явно будет глюк, но в данный момент с этим нет необходимости разбираться)

- в CS6 не заведется. Понятно, что можно рюшечки в виде doForcedProgress() выпилить, заменить impliedFontSize на старый добрый size, однако при попытке сделать слой белым через стили текста почему-то текст начинает изменять размер. Предполагаю, что это из-за того что часть атрибутов в дефолтном стиле висит. Забил на этот момент.


В любом случае спасибо за пример, он очень помог.

001.jpg

002.jpg

003.jpg

 

 

var app = new AM('application'),
    lr = new AM('layer'),
    scale = 30, // %, randomize size of each letter (percent of size)
    offset = 2, //%. randomize Y position of each letter, (percent of size)
    angle = 15; //deg, randomize angle of each letter (max angle)
if (app.getProperty('numberOfDocuments')) activeDocument.suspendHistory('Scattering letters', 'main()')
function main() {
    if (lr.hasProperty('textKey')) {
        lr.setVisiblity('show')
        var fx = lr.hasProperty('layerEffects');
        if (fx) lr.copyStyle();
        lr.setVisiblity('hide')
        lr.duplicateLayer(lr.getProperty('name'));
        lr.setVisiblity('show')
        if (fx) lr.clearStyle();
        lr.convertToSmartObject();
        if (fx) lr.pasteStyle();
        lr.editSmartObject();
        activeDocument.suspendHistory('Scattering letters', 'splitLetters()')
        function splitLetters() {
            var letters = lr.describeTextLayer(),
                baseLayerId = lr.getProperty('layerID');
            doForcedProgress('letter preparation', 'prepareLetters ()')
            doForcedProgress('move letters', 'moveLetters ()')
            function prepareLetters() {
                lr.randomizeSize(letters, scale);
                lr.revealAll();
                lr.splitLetters(letters);
                var IDs = [];
                for (var i = 0; i < letters.length; i++) if (letters[i].id) IDs.push(letters[i].id)
                lr.setVisiblity('hide', IDs)
            }
            function moveLetters() {
                for (var i = 0; i < letters.length; i++) {
                    updateProgress(i + 1, letters.length);
                    changeProgressText('move letter: ' + letters[i].content)
                    if (letters[i].id) {
                        lr.selectLayer([letters[i].id])
                        lr.setWhiteText(baseLayerId)
                        lr.setBlackText(baseLayerId, i)
                        lr.selectRGBChannel()
                        lr.inverseSelection()
                        lr.alignLayer()
                        lr.deselect()
                    }
                }
                for (var i = 0; i < letters.length; i++) {
                    if (letters[i].id) {
                        lr.selectLayer([letters[i].id], true)
                        var rotate = Math.random() > 0.5 ? Math.random() * angle : -Math.random() * angle,
                            bounds = lr.descToObject(lr.getProperty('bounds').value),
                            height = bounds.bottom - bounds.top,
                            shift = height * Math.random() > 0.5 ? Math.random() * offset / 100 : -Math.random() * offset / 100;
                        lr.transform(rotate, 0, shift)
                    }
                }
            }
            lr.selectLayer([baseLayerId])
            lr.removeLayer()
            lr.revealAll()
            app.closeDocument(true)
        }
    }
}
function AM(target) {
    var s2t = stringIDToTypeID,
        t2s = typeIDToStringID;
    target = target ? s2t(target) : null;
    this.getProperty = function (property, id, idxMode) {
        property = s2t(property);
        (r = new ActionReference()).putProperty(s2t('property'), property);
        id != undefined ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id)) :
            r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
        return getDescValue(executeActionGet(r), property)
    }
    this.hasProperty = function (property, id, idxMode) {
        property = s2t(property);
        (r = new ActionReference()).putProperty(s2t('property'), property);
        id ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id))
            : r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
        try { return executeActionGet(r).hasKey(property) } catch (e) { return false }
    }
    this.descToObject = function (d) {
        var o = {}
        for (var i = 0; i < d.count; i++) {
            var k = d.getKey(i)
            o[t2s(k)] = getDescValue(d, k)
        }
        return o
    }
    this.duplicateLayer = function (name) {
        (r = new ActionReference()).putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
        (d = new ActionDescriptor()).putReference(s2t('target'), r);
        d.putString(s2t('name'), name);
        executeAction(s2t('duplicate'), d, DialogModes.NO);
    }
    this.removeLayer = function (name) {
        (r = new ActionReference()).putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
        (d = new ActionDescriptor()).putReference(s2t('target'), r);
        executeAction(s2t('delete'), d, DialogModes.NO);
    }
    this.copyStyle = function () {
        executeAction(s2t('copyEffects'), undefined, DialogModes.NO);
    }
    this.pasteStyle = function () {
        executeAction(s2t('pasteEffects'), undefined, DialogModes.NO);
    }
    this.clearStyle = function () {
        (r = new ActionReference()).putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
        (d = new ActionDescriptor()).putReference(s2t('target'), r);
        executeAction(s2t('disableLayerFX'), d, DialogModes.NO);
    }
    this.setVisiblity = function (mode, IDsList) {
        var r = new ActionReference();
        if (IDsList) for (var i = 0; i < IDsList.length; i++)r.putIdentifier(s2t('layer'), IDsList[i]);
        else r.putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
        (d = new ActionDescriptor()).putReference(s2t('target'), r);
        executeAction(s2t(mode), d, DialogModes.NO);
    }
    this.convertToSmartObject = function () {
        executeAction(s2t('newPlacedLayer'), undefined, DialogModes.NO);
    }
    this.editSmartObject = function () {
        executeAction(s2t('placedLayerEditContents'), undefined, DialogModes.NO);
    }
    this.selectLayer = function (IDsList, makeVisible) {
        var r = new ActionReference()
        if (IDsList) for (var i = 0; i < IDsList.length; i++)r.putIdentifier(s2t('layer'), IDsList[i]);
        (d = new ActionDescriptor()).putReference(s2t('target'), r)
        d.putBoolean(s2t('makeVisible'), makeVisible ? makeVisible : false)
        executeAction(s2t('select'), d, DialogModes.NO)
    }
    this.describeTextLayer = function () {
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('textKey'));
        r.putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
        var textKey = executeActionGet(r).getObjectValue(p),
            tList = textKey.getList(s2t('textStyleRange')),
            styleSheet = { textStyle: [], paragraphStyle: [] },
            text = textKey.getString(s2t('textKey')),
            output = [];
        for (var i = 0; i < tList.count; i++) {
            styleSheet.textStyle.push({
                from: tList.getObjectValue(i).getInteger(s2t('from')),
                to: tList.getObjectValue(i).getInteger(s2t('to')),
                style: tList.getObjectValue(i).getObjectValue(s2t('textStyle'))
            })
        };
        for (var i = 0; i < text.length; i++) {
            output.push({
                content: text.substr(i, 1),
                textStyle: findStyle(styleSheet.textStyle, i),
            });
        };
        return output;
        function findStyle(style, idx) {
            for (var i = 0; i < style.length; i++) {
                if (idx >= style[i].from && idx < style[i].to) return copyDesc(style[i].style, new ActionDescriptor())
            }
        }
    }
    this.randomizeSize = function (letters, ratio) {
        ratio = ratio ? ratio : 0.5;
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('textKey'));
        r.putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
        var textKey = executeActionGet(r).getObjectValue(p);
        for (var i = 0; i < letters.length; i++) {
            if (!/\s/.test(letters[i].content)) {
                var impliedFontSize = letters[i].textStyle.getUnitDoubleValue(s2t('impliedFontSize'))
                letters[i].textStyle.putUnitDouble(s2t('impliedFontSize'), s2t('pointsUnit'), impliedFontSize + impliedFontSize * (Math.random() > 0.5 ? Math.random() * ratio / 100 : -Math.random() * ratio / 100));
            }
        }
        var l = new ActionList();
        for (var i = 0; i < letters.length; i++) {
            var d = new ActionDescriptor();
            d.putObject(s2t('textStyle'), s2t('textStyle'), letters[i].textStyle);
            d.putInteger(s2t('from'), i);
            d.putInteger(s2t('to'), i + 1);
            l.putObject(s2t('textStyleRange'), d)
        }
        textKey.putList(s2t('textStyleRange'), l);
        (r = new ActionReference()).putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
        (d = new ActionDescriptor()).putReference(s2t('null'), r);
        d.putObject(s2t('to'), s2t('textLayer'), textKey);
        executeAction(s2t('set'), d, DialogModes.NO);
    }
    this.revealAll = function () {
        executeAction(s2t('revealAll'), new ActionDescriptor(), DialogModes.NO);
    }
    this.splitLetters = function (letters) {
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('textKey'));
        r.putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
        var textKey = executeActionGet(r).getObjectValue(p);
        for (var i = 0; i < letters.length; i++) {
            if (!/\s/.test(letters[i].content)) {
                lr.duplicateLayer(letters[i].content)
                var d = new ActionDescriptor(),
                    l = new ActionList();
                d.putObject(s2t('textStyle'), s2t('textStyle'), letters[i].textStyle);
                d.putInteger(s2t('from'), 0);
                d.putInteger(s2t('to'), 1);
                l.putObject(s2t('textStyleRange'), d)
                textKey.putList(s2t('textStyleRange'), l);
                (r = new ActionReference()).putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
                (d = new ActionDescriptor()).putReference(s2t('null'), r);
                textKey.putString(s2t('textKey'), letters[i].content);
                d.putObject(s2t('to'), s2t('textLayer'), textKey);
                executeAction(s2t('set'), d, DialogModes.NO);
                (r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerID'));
                r.putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
                letters[i].id = executeActionGet(r).getInteger(p);
            }
        }
    }
    this.setWhiteText = function (id) {
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('textKey'));
        r.putIdentifier(s2t('layer'), id);
        var textKey = executeActionGet(r).getObjectValue(p),
            tList = textKey.getList(s2t('textStyleRange')),
            l = new ActionList();
        for (var i = 0; i < tList.count; i++) {
            var k = tList.getObjectValue(i),
                s = k.getObjectValue(s2t('textStyle'));
            var d = new ActionDescriptor();
            d.putDouble(s2t('red'), 255)
            d.putDouble(s2t('grain'), 255)
            d.putDouble(s2t('blue'), 255)
            s.putObject(s2t('color'), s2t('RGBColor'), d)
            k.putObject(s2t('textStyle'), s2t('textStyle'), s)
            l.putObject(s2t('textStyleRange'), k)
        }
        textKey.putList(s2t('textStyleRange'), l)
        var d = new ActionDescriptor();
        (r = new ActionReference()).putIdentifier(s2t('layer'), id);
        d.putReference(s2t('target'), r);
        d.putObject(s2t('to'), s2t('textLayer'), textKey);
        executeAction(s2t('set'), d, DialogModes.NO);
    }
    this.setBlackText = function (id, idx) {
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('textKey'));
        r.putIdentifier(s2t('layer'), id);
        var textKey = executeActionGet(r).getObjectValue(p),
            tList = textKey.getList(s2t('textStyleRange')),
            l = new ActionList();
        for (var i = 0; i < tList.count; i++) {
            var k = tList.getObjectValue(i),
                s = k.getObjectValue(s2t('textStyle'));
            if (idx == i) {
                var d = new ActionDescriptor();
                d.putDouble(s2t('red'), 0)
                d.putDouble(s2t('grain'), 0)
                d.putDouble(s2t('blue'), 0)
                s.putObject(s2t('color'), s2t('RGBColor'), d)
            }
            k.putObject(s2t('textStyle'), s2t('textStyle'), s)
            l.putObject(s2t('textStyleRange'), k)
        }
        textKey.putList(s2t('textStyleRange'), l)
        var d = new ActionDescriptor();
        (r = new ActionReference()).putIdentifier(s2t('layer'), id);
        d.putReference(s2t('target'), r);
        d.putObject(s2t('to'), s2t('textLayer'), textKey);
        executeAction(s2t('set'), d, DialogModes.NO);
    }
    this.selectRGBChannel = function () {
        (r = new ActionReference()).putProperty(s2t('channel'), s2t('selection'));
        (d = new ActionDescriptor()).putReference(s2t('null'), r);
        (r1 = new ActionReference()).putEnumerated(s2t('channel'), s2t('channel'), s2t('RGB'));
        d.putReference(s2t('to'), r1);
        executeAction(s2t('set'), d, DialogModes.NO);
    }
    this.inverseSelection = function () {
        executeAction(s2t('inverse'), undefined, DialogModes.NO);
    }
    this.transform = function (angle, dX, dY) {
        (r = new ActionReference()).putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
        (d = new ActionDescriptor()).putReference(s2t('target'), r);
        d.putEnumerated(s2t('freeTransformCenterState'), s2t('quadCenterState'), s2t('QCSAverage'));
        (d1 = new ActionDescriptor()).putUnitDouble(s2t('horizontal'), s2t('distanceUnit'), dX);
        d1.putUnitDouble(s2t('vertical'), s2t('distanceUnit'), dY);
        d.putObject(s2t('offset'), s2t('offset'), d1);
        d.putUnitDouble(s2t('angle'), s2t('angleUnit'), angle);
        d.putEnumerated(s2t('interfaceIconFrameDimmed'), s2t('interpolationType'), s2t('bicubic'));
        executeAction(s2t('transform'), d, DialogModes.NO);
    }
    this.alignLayer = function () {
        (r = new ActionReference()).putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
        (d = new ActionDescriptor()).putReference(s2t('target'), r);
        d.putEnumerated(s2t('using'), s2t('alignDistributeSelector'), s2t('ADSCentersH'));
        d.putBoolean(s2t('alignToCanvas'), false);
        executeAction(s2t('align'), d, DialogModes.NO);
        (r = new ActionReference()).putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
        (d = new ActionDescriptor()).putReference(s2t('target'), r);
        d.putEnumerated(s2t('using'), s2t('alignDistributeSelector'), s2t('ADSCentersV'));
        d.putBoolean(s2t('alignToCanvas'), false);
        executeAction(s2t('align'), d, DialogModes.NO);
    }
    this.deselect = function () {
        (r = new ActionReference()).putProperty(s2t('channel'), s2t('selection'));
        (d = new ActionDescriptor()).putReference(s2t('target'), r);
        d.putEnumerated(s2t('to'), s2t('ordinal'), s2t('none'));
        executeAction(s2t('set'), d, DialogModes.NO);
    }
    this.closeDocument = function (save) {
        save = save != true ? s2t('no') : s2t('yes');
        (d = new ActionDescriptor()).putEnumerated(s2t('saving'), s2t('yesNo'), save);
        executeAction(s2t('close'), d, DialogModes.NO);
    }
    function copyDesc(from, to) {
        for (var i = 0; i < from.count; i++) {
            var k = from.getKey(i);
            if (to.hasKey(k)) continue;
            switch (from.getType(k)) {
                case DescValueType.ALIASTYPE: to.putPath(k, from.getPath(k)); break;
                case DescValueType.BOOLEANTYPE: to.putBoolean(k, from.getBoolean(k)); break;
                case DescValueType.CLASSTYPE: to.putClass(k, from.getClass(k)); break;
                case DescValueType.DOUBLETYPE: to.putDouble(k, from.getDouble(k)); break;
                case DescValueType.INTEGERTYPE: to.putInteger(k, from.getInteger(k)); break;
                case DescValueType.LISTTYPE: to.putList(k, from.getList(k)); break;
                case DescValueType.RAWTYPE: to.putData(k, from.getData(k)); break;
                case DescValueType.STRINGTYPE: to.putString(k, from.getString(k)); break;
                case DescValueType.LARGEINTEGERTYPE: to.putLargeInteger(k, from.getLargeInteger(k)); break;
                case DescValueType.REFERENCETYPE: to.putReference(k, from.getReference(k)); break;
                case DescValueType.OBJECTTYPE: to.putObject(k, from.getObjectType(k), from.getObjectValue(k)); break;
                case DescValueType.ENUMERATEDTYPE: to.putEnumerated(k, from.getEnumerationType(k), from.getEnumerationValue(k)); break;
                case DescValueType.UNITDOUBLE: to.putUnitDouble(k, from.getUnitDoubleType(k), from.getUnitDoubleValue(k)); break;
            }
        }
        return to
    }
    function getDescValue(d, p) {
        switch (d.getType(p)) {
            case DescValueType.OBJECTTYPE: return { type: t2s(d.getObjectType(p)), value: d.getObjectValue(p) };
            case DescValueType.LISTTYPE: return d.getList(p);
            case DescValueType.REFERENCETYPE: return d.getReference(p);
            case DescValueType.BOOLEANTYPE: return d.getBoolean(p);
            case DescValueType.STRINGTYPE: return d.getString(p);
            case DescValueType.INTEGERTYPE: return d.getInteger(p);
            case DescValueType.LARGEINTEGERTYPE: return d.getLargeInteger(p);
            case DescValueType.DOUBLETYPE: return d.getDouble(p);
            case DescValueType.ALIASTYPE: return d.getPath(p);
            case DescValueType.CLASSTYPE: return d.getClass(p);
            case DescValueType.UNITDOUBLE: return (d.getUnitDoubleValue(p));
            case DescValueType.ENUMERATEDTYPE: return { type: t2s(d.getEnumerationType(p)), value: t2s(d.getEnumerationValue(p)) };
            default: break;
        };
    }
}

 

 

   

Votes

Translate

Translate

Report

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
People's Champ ,
Jun 30, 2022 Jun 30, 2022

Copy link to clipboard

Copied

Вот исходник первого скрипта. Декодер нужен?

try {
    app.activeDocument.suspendHistory("Split Text", "ok = f()");
} catch (e) {
    alert(e);
}
if (ok) {
    alert("Done!")
}

function f() {
    try {
        try {
            activeDocument.activeLayer.textItem;
        } catch (e) {
            alert("Not a text layer");
            return false;
        }
        try {
            activeDocument.activeLayer.textItem.font;
        } catch (e) {
            alert("Yor text layer is bad.\n\nPlease reassign font to your layer");
            return false;
        }
        app.preferences.rulerUnits = Units.CM;
        var white = new SolidColor();
        with(white.rgb) {
            red = green = blue = 255;
        }
        var black = new SolidColor();
        with(black.rgb) {
            red = green = blue = 0;
        }
        var text = activeDocument.activeLayer.textItem.contents;
        var size = activeDocument.activeLayer.textItem.size;
        try {
            color = activeDocument.activeLayer.textItem.color;
        } catch (e) {
            color = black;
            set_black_text();
        }
        var r = new ActionReference();
        r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("textKey"));
        r.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
        data = executeActionGet(r).getObjectValue(stringIDToTypeID("textKey"));
        style = executeActionGet(r).getObjectValue(stringIDToTypeID("textKey")).getList(stringIDToTypeID("textStyleRange")).getObjectValue(0).getObjectValue(stringIDToTypeID("textStyle"));
        var orig_layer = activeDocument.activeLayer;
        var layer0 = activeDocument.activeLayer.duplicate();
        activeDocument.activeLayer = layer0;
        if (app.activeDocument.activeLayer != app.activeDocument.layers[0]) {
            app.activeDocument.activeLayer.move(app.activeDocument.layers[0], ElementPlacement.PLACEBEFORE)
        }
        var white_layer = activeDocument.artLayers.add();
        activeDocument.activeLayer = white_layer;
        fill_white();
        white_layer.move(layer0, ElementPlacement.PLACEAFTER);
        if (white_layer.grouped) {
            white_layer.grouped = false
        }
        activeDocument.activeLayer = layer0;
        set_text_style(0, text.length, white);
        set_text_style(0, text.length + 1, black);
        var lll = new Array();
        for (var i = 0; i < text.length; i += 1) {
            var s = text.substr(i, 1);
            var cont = false;
            switch (s) {
                case " ":
                case "\n":
                case "\r":
                    cont = true;
                    break;
            }
            if (cont) {
                continue;
            }
            activeDocument.activeLayer = layer0;
            set_text_style(0, i, white);
            set_text_style(i, 1, black);
            set_text_style(i + 1, (text.length - i) + 1, white);
            selection_from_rgb();
            try {
                activeDocument.selection.invert();
                var x = activeDocument.selection.bounds[0].value;
                var y = activeDocument.selection.bounds[1].value;
            } catch (e) {
                continue;
            }
            activeDocument.selection.deselect();
            var layer = activeDocument.activeLayer.duplicate();
            activeDocument.activeLayer = layer;
            layer.textItem.contents = text.substr(i, 1);
            set_text_style(0, 1, color);
            move(x - layer.bounds[0].value, y - layer.bounds[1].value);
            app.activeDocument.activeLayer.move(orig_layer, ElementPlacement.PLACEBEFORE);
            lll.push(layer);
            layer.visible = false;
        }
        for (var i = 0; i < lll.length; i += 1) {
            lll[i].visible = true
        }
        white_layer.remove();
        layer0.remove();
        orig_layer.remove();
        return true;
    } catch (e) {
        alert(e);
    }
}

function set_text_style(from, color, len) {
    try {
        if (len < 1) {
            return;
        }
        var d = new ActionDescriptor();
        var r = new ActionReference();
        r.putEnumerated(stringIDToTypeID("textLayer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
        d.putReference(stringIDToTypeID("null"), r);
        var d1 = new ActionDescriptor();
        var list1 = new ActionList();
        var d2 = new ActionDescriptor();
        d2.putInteger(stringIDToTypeID("from"), from);
        d2.putInteger(stringIDToTypeID("to"), from + len);
        var d4 = new ActionDescriptor();
        d4.putDouble(stringIDToTypeID("red"), color.rgb.red);
        d4.putDouble(stringIDToTypeID("green"), color.rgb.green);
        d4.putDouble(stringIDToTypeID("blue"), color.rgb.blue);
        style.putObject(stringIDToTypeID("color"), stringIDToTypeID("RGBColor"), d4);
        d2.putObject(stringIDToTypeID("textStyle"), stringIDToTypeID("textStyle"), style);
        list1.putObject(stringIDToTypeID("textStyleRange"), d2);
        d1.putList(stringIDToTypeID("textStyleRange"), list1);
        d.putObject(stringIDToTypeID("to"), stringIDToTypeID("textLayer"), d1);
        executeAction(stringIDToTypeID("set"), d, DialogModes.NO);
    } catch (e) {
        alert(e);
        throw e
    }
}

function selection_from_rgb() {
    try {
        var d = new ActionDescriptor();
        var r = new ActionReference();
        r.putProperty(stringIDToTypeID("channel"), stringIDToTypeID("selection"));
        d.putReference(stringIDToTypeID("null"), r);
        var r = new ActionReference();
        r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("RGB"));
        d.putReference(stringIDToTypeID("to"), r);
        executeAction(stringIDToTypeID("set"), d, DialogModes.NO);
    } catch (e) {
        throw e
    }
}

function move(x, y) {
    try {
        var d1 = new ActionDescriptor();
        var ref = new ActionReference();
        ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
        d1.putReference(charIDToTypeID("null"), ref);
        var d2 = new ActionDescriptor();
        d2.putUnitDouble(charIDToTypeID("Hrzn"), charIDToTypeID("#Rlt"), (x * 72) / 2, 54);
        d2.putUnitDouble(charIDToTypeID("Vrtc"), charIDToTypeID("#Rlt"), (y * 72) / 2, 54);
        d1.putObject(charIDToTypeID("T   "), charIDToTypeID("Ofst"), d2);
        executeAction(charIDToTypeID("move"), d1, DialogModes.NO);
    } catch (e) {
        alert(e);
        throw e
    }
}

function fill_white() {
    try {
        var d = new ActionDescriptor();
        d.putEnumerated(stringIDToTypeID("using"), stringIDToTypeID("fillContents"), stringIDToTypeID("color"));
        var d1 = new ActionDescriptor();
        d1.putUnitDouble(stringIDToTypeID("hue"), stringIDToTypeID("angleUnit"), 0);
        d1.putDouble(stringIDToTypeID("saturation"), 0);
        d1.putDouble(stringIDToTypeID("brightness"), 100);
        d.putObject(stringIDToTypeID("color"), stringIDToTypeID("HSBColorClass"), d1);
        d.putUnitDouble(stringIDToTypeID("opacity"), stringIDToTypeID("percentUnit"), 100);
        d.putEnumerated(stringIDToTypeID("mode"), stringIDToTypeID("blendMode"), stringIDToTypeID("normal"));
        executeAction(stringIDToTypeID("fill"), d, DialogModes.NO);
    } catch (e) {
        throw e
    }
}

function set_black_text() {
    try {
        var d = new ActionDescriptor();
        var r = new ActionReference();
        r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("textStyle"));
        r.putEnumerated(stringIDToTypeID("textLayer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
        d.putReference(stringIDToTypeID("null"), r);
        var d1 = new ActionDescriptor();
        var d2 = new ActionDescriptor();
        d2.putDouble(stringIDToTypeID("red"), 0);
        d2.putDouble(stringIDToTypeID("green"), 0);
        d2.putDouble(stringIDToTypeID("blue"), 0);
        d1.putObject(stringIDToTypeID("color"), stringIDToTypeID("RGBColor"), d2);
        d.putObject(stringIDToTypeID("to"), stringIDToTypeID("textStyle"), d1);
        executeAction(stringIDToTypeID("set"), d, DialogModes.NO);
    } catch (e) {
        throw e
    }
}

 

Votes

Translate

Translate

Report

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
LEGEND ,
Jun 30, 2022 Jun 30, 2022

Copy link to clipboard

Copied

The biggest issue likely is figuring out the dimensions of the individual contours and then storing that in some sort of field or matrix whereby you then apply some sort of "smooth" randomization to the pre-sorted data rather than tackling each letter individually or else you'd end up with a lot of backtracking and extra iterations to correct the small errors that creep in... 

 

Mylenium

Votes

Translate

Translate

Report

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 ,
Jul 09, 2022 Jul 09, 2022

Copy link to clipboard

Copied

Shape Layers might work out after all, because the path data collected via DOM differs from the one collected via AM and that may allow to determine which subPathItems »belong together«. 

separateLettersFromTypeLayerScr.gif

 

// create shape layer for each letter in a type layer;
// just for rgb;
// 2022, use it at your own risk;
if (app.documents.length > 0) {
var myDocument = app.activeDocument;
var theLayer = myDocument.activeLayer;
// check if active layer is type layer;
if (theLayer.kind == LayerKind.TEXT) {
    app.togglePalettes();
    theLayer.visible = true;
// get the colors;
    var lettersColors = getLettersColors();
// create shape layer and collect am and dom subpathitems;
    convertToShapeLayer ();
    var theDOMPath = collectPathInfoDOM(myDocument, myDocument.pathItems[myDocument.pathItems.length-1]);
    var thePath = collectPathInfoFromDesc2012 (myDocument, myDocument.pathItems[myDocument.pathItems.length-1]);
    executeAction( charIDToTypeID("undo"), undefined, DialogModes.NO );
    theLayer.visible = false;
// process paths;
var theLayers = new Array;
var domCount = theDOMPath.length - 1;
var thisPath = new Array;
var colorsCount = lettersColors.length - 1;
for (var m = thePath.length - 1; m >= 0; m--) {
    var theCheck = true;
    var thisDOM = theDOMPath[domCount];
    var thisAM = thePath[m];
    thisPath.push(thisAM);
// compare dom and am;
    if (thisDOM.length == thisAM.length) {
        for (var n = 0; n < thisDOM.length - 2; n++) {
            if (String(thisDOM[n][0]) != String(thisAM[n][0])) {theCheck = false};
            if (String(thisDOM[n][1]) != String(thisAM[n][1])) {theCheck = false};
            if (String(thisDOM[n][2]) != String(thisAM[n][2])) {theCheck = false};
        };
    } else {theCheck = false};
// create shape layer if dom and am supathitems are identical;
    if (theCheck == true) {
        var newShape = createShapeLayer(thisPath, lettersColors[colorsCount][1][0], lettersColors[colorsCount][1][1], lettersColors[colorsCount][1][2]);
        colorsCount--;
        theLayers.push(newShape);
        var thisPath = new Array;
        domCount--
    };
};
// transform;
for (var o = 0; o < theLayers.length; o++) {
    var theScale = 100 * (Math.random()*0.4+0.8);
    layerDuplicateOffsetScaleRotate (theLayers[o], 0, 0, theScale, theScale, 15-Math.random()*30, false)
};
app.togglePalettes();
};
};
////////////////////////////////////
////////////////////////////////////
////////////////////////////////////
////// get color of letters in type layer //////
function getLettersColors () {
    var ref = new ActionReference();
    ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID('textKey'));
    ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
    var layerDesc = executeActionGet(ref);
    var textDesc = layerDesc.getObjectValue(stringIDToTypeID('textKey'));
    var theText = textDesc.getString(stringIDToTypeID("textKey"));
    var theStyleRanges = new Array;
    var theColors = new Array;
    var rangeList = textDesc.getList(stringIDToTypeID('textStyleRange'));
    for (var o = 0; o < rangeList.count; o++) {
        var thisList = rangeList.getObjectValue(o);
        var theFrom = thisList.getInteger(charIDToTypeID( "From" ));
        var theTo = thisList.getInteger(charIDToTypeID( "T   " ));
        var styleDesc = thisList.getObjectValue(stringIDToTypeID('textStyle'));
        var bl = styleDesc.getEnumerationValue(stringIDToTypeID("baseline"));
        var theColor = styleDesc.getObjectValue(stringIDToTypeID("color"));
        var theNumbers = [theColor.getUnitDoubleValue(stringIDToTypeID("red")), theColor.getUnitDoubleValue(stringIDToTypeID("grain")), theColor.getUnitDoubleValue(stringIDToTypeID("blue"))];
        theStyleRanges.push([styleDesc, theFrom, theTo]);
        if (o == 0) {theColors.push([theNumbers, theFrom, theTo])} else {
            if (theColors[theColors.length-1][1]!=theFrom && theColors[theColors.length-1][2]!=theTo) {
                theColors.push([theNumbers, theFrom, theTo])
            }
            }
        };
    //alert (theText+"\n"+theColors.join("\n"));
    var theLetterColors = new Array;
    var thisColor = theColors[0][0];
    var theCounter = 0;
    // get individual letters’s colors and ignore spaces etc.;
    for (var x = 0; x < theText.length; x++) {
        if (theColors[theCounter][2] == x) {
            theCounter++
            thisColor = theColors[theCounter][0];
        };
        if (theText[x].match(/\S/i) != null) {
            theLetterColors.push([theText[x], thisColor])
        };
    };
    return theLetterColors
};
////// collect path info from actiondescriptor, smooth added //////
function collectPathInfoFromDesc2012 (myDocument, thePath) {
    var originalRulerUnits = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.POINTS;
    // based of functions from xbytor’s stdlib;
    var ref = new ActionReference();
    for (var l = 0; l < myDocument.pathItems.length; l++) {
        var thisPath = myDocument.pathItems[l];
        if (thisPath == thePath && thisPath.kind == PathKind.WORKPATH) {
            ref.putProperty(cTID("Path"), cTID("WrPt"));
            };
        if (thisPath == thePath && thisPath.kind != PathKind.WORKPATH && thisPath.kind != PathKind.VECTORMASK) {
            ref.putIndex(cTID("Path"), l + 1);
            };
        if (thisPath == thePath && thisPath.kind == PathKind.VECTORMASK) {
            var idPath = charIDToTypeID( "Path" );
            var idPath = charIDToTypeID( "Path" );
            var idvectorMask = stringIDToTypeID( "vectorMask" );
            ref.putEnumerated( idPath, idPath, idvectorMask );
            };
        };
    var desc = app.executeActionGet(ref);
    var pname = desc.getString(cTID('PthN'));
    // create new array;
    var theArray = new Array;
    var pathComponents = desc.getObjectValue(cTID("PthC")).getList(sTID('pathComponents'));
    // for subpathitems;
    for (var m = 0; m < pathComponents.count; m++) {
        var listKey = pathComponents.getObjectValue(m).getList(sTID("subpathListKey"));
        var operation1 = pathComponents.getObjectValue(m).getEnumerationValue(sTID("shapeOperation"));
        switch (operation1) {
            case 1097098272:
            var operation = 1097098272 //cTID('Add ');
            break;
            case 1398961266:
            var operation = 1398961266 //cTID('Sbtr');
            break;
            case 1231975538:
            var operation = 1231975538 //cTID('Intr');
            break;
            default:
    //		case 1102:
            var operation = sTID('xor') //ShapeOperation.SHAPEXOR;
            break;
            };
    // for subpathitem’s count;
        for (var n = 0; n < listKey.count; n++) {
            theArray.push(new Array);
            var points = listKey.getObjectValue(n).getList(sTID('points'));
            try {var closed = listKey.getObjectValue(n).getBoolean(sTID("closedSubpath"))}
            catch (e) {var closed = false};
    // for subpathitem’s segment’s number of points;
            for (var o = 0; o < points.count; o++) {
                var anchorObj = points.getObjectValue(o).getObjectValue(sTID("anchor"));
                var anchor = [anchorObj.getUnitDoubleValue(sTID('horizontal')), anchorObj.getUnitDoubleValue(sTID('vertical'))];
                var thisPoint = [anchor];
                try {
                    var left = points.getObjectValue(o).getObjectValue(cTID("Fwd "));
                    var leftDirection = [left.getUnitDoubleValue(sTID('horizontal')), left.getUnitDoubleValue(sTID('vertical'))];
                    thisPoint.push(leftDirection)
                    }
                catch (e) {
                    thisPoint.push(anchor)
                    };
                try {
                    var right = points.getObjectValue(o).getObjectValue(cTID("Bwd "));
                    var rightDirection = [right.getUnitDoubleValue(sTID('horizontal')), right.getUnitDoubleValue(sTID('vertical'))];
                    thisPoint.push(rightDirection)
                    }
                catch (e) {
                    thisPoint.push(anchor)
                    };
                try {
                    var smoothOr = points.getObjectValue(o).getBoolean(cTID("Smoo"));
                    thisPoint.push(smoothOr)
                    }
                catch (e) {thisPoint.push(false)};
                theArray[theArray.length - 1].push(thisPoint);
                };
            theArray[theArray.length - 1].push(closed);
            theArray[theArray.length - 1].push(operation);
            };
        };
    // by xbytor, thanks to him;
    function cTID (s) { return cTID[s] || cTID[s] = app.charIDToTypeID(s); };
    function sTID (s) { return sTID[s] || sTID[s] = app.stringIDToTypeID(s); };
    // reset;
    app.preferences.rulerUnits = originalRulerUnits;
    return theArray;
    };
////// function to collect path-info as text from dom //////
function collectPathInfoDOM (myDocument, thePath) {
    var originalRulerUnits = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.POINTS;
    var theArray = [];
    for (var b = 0; b < thePath.subPathItems.length; b++) {
        theArray[b] = [];
        for (var c = 0; c < thePath.subPathItems[b].pathPoints.length; c++) {
            var pointsNumber = thePath.subPathItems[b].pathPoints.length;
            var theAnchor = thePath.subPathItems[b].pathPoints[c].anchor;
            var theLeft = thePath.subPathItems[b].pathPoints[c].leftDirection;
            var theRight = thePath.subPathItems[b].pathPoints[c].rightDirection;
            var theKind = thePath.subPathItems[b].pathPoints[c].kind;
            theArray[b][c] = [theAnchor, theLeft, theRight, theKind];
            };
        theArray[b][theArray[b].length] = String(thePath.subPathItems[b].closed);
        theArray[b][theArray[b].length] = String(thePath.subPathItems[b].operation);
        };
    app.preferences.rulerUnits = originalRulerUnits;
    return theArray
    };
////// convert type layer to shape layer //////
function convertToShapeLayer () {
try {
    var desc5 = new ActionDescriptor();
        var ref1 = new ActionReference();
        ref1.putClass( stringIDToTypeID( "contentLayer" ) );
    desc5.putReference( stringIDToTypeID( "null" ), ref1 );
        var ref2 = new ActionReference();
        ref2.putEnumerated( stringIDToTypeID( "textLayer" ), stringIDToTypeID( "ordinal" ), stringIDToTypeID( "targetEnum" ) );
    desc5.putReference( stringIDToTypeID( "using" ), ref2 );
executeAction( stringIDToTypeID( "make" ), desc5, DialogModes.NO );
} catch (e) {}
};
////// create a solid color layer //////
function createShapeLayer(theArray, theR, theG, theB) {
    var originalRulerUnits = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.POINTS;
    // thanks to xbytor;
    cTID = function(s) { return app.charIDToTypeID(s); };
    sTID = function(s) { return app.stringIDToTypeID(s); };
     
     
        var desc1 = new ActionDescriptor();
        var ref1 = new ActionReference();
        ref1.putProperty(cTID('Path'), cTID('WrPt'));
        desc1.putReference(sTID('null'), ref1);
        var list1 = new ActionList();
     
    for (var m = 0; m < theArray.length; m++) {
      var thisSubPath = theArray[m];
     
        var desc2 = new ActionDescriptor();
        desc2.putEnumerated(sTID('shapeOperation'), sTID('shapeOperation'), 1908);
//        desc2.putEnumerated(sTID('shapeOperation'), sTID('shapeOperation'), thisSubPath[thisSubPath.length - 1]);
        var list2 = new ActionList();
        var desc3 = new ActionDescriptor();
        desc3.putBoolean(cTID('Clsp'), thisSubPath[thisSubPath.length - 2]);
        var list3 = new ActionList();
     
    for (var n = 0; n < thisSubPath.length - 2; n++) {
      var thisPoint = thisSubPath[n];
     
        var desc4 = new ActionDescriptor();
        var desc5 = new ActionDescriptor();
        desc5.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[0][0]);
        desc5.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[0][1]);
        desc4.putObject(cTID('Anch'), cTID('Pnt '), desc5);
        var desc6 = new ActionDescriptor();
        desc6.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[1][0]);
        desc6.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[1][1]);
        desc4.putObject(cTID('Fwd '), cTID('Pnt '), desc6);
        var desc7 = new ActionDescriptor();
        desc7.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[2][0]);
        desc7.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[2][1]);
        desc4.putObject(cTID('Bwd '), cTID('Pnt '), desc7);
        desc4.putBoolean(cTID('Smoo'), thisPoint[3]);
        list3.putObject(cTID('Pthp'), desc4);
     
      };
     
        desc3.putList(cTID('Pts '), list3);
        list2.putObject(cTID('Sbpl'), desc3);
        desc2.putList(cTID('SbpL'), list2);
        list1.putObject(cTID('PaCm'), desc2);
      };
     
        desc1.putList(cTID('T   '), list1);
        executeAction(cTID('setd'), desc1, DialogModes.NO);
    // solid color layer;
    // =======================================================
        var desc16 = new ActionDescriptor();
            var ref4 = new ActionReference();
            ref4.putClass( stringIDToTypeID( "contentLayer" ) );
        desc16.putReference( charIDToTypeID( "null" ), ref4 );
            var desc17 = new ActionDescriptor();
                var desc18 = new ActionDescriptor();
                    var desc19 = new ActionDescriptor();
                    desc19.putDouble( charIDToTypeID( "Rd  " ), theR );
                    desc19.putDouble( charIDToTypeID( "Grn " ), theG );
                    desc19.putDouble( charIDToTypeID( "Bl  " ), theB );
                desc18.putObject( charIDToTypeID( "Clr " ), charIDToTypeID( "RGBC" ), desc19 );
            var idsolidColorLayer = stringIDToTypeID( "solidColorLayer" );
            desc17.putObject( charIDToTypeID( "Type" ), idsolidColorLayer, desc18 );
        desc16.putObject( charIDToTypeID( "Usng" ), stringIDToTypeID( "contentLayer" ), desc17 );
    executeAction( charIDToTypeID( "Mk  " ), desc16, DialogModes.NO );
    app.preferences.rulerUnits = originalRulerUnits;
//    return activeDocument.activeLayer;
    // get identifier;
    var ref = new ActionReference();
    ref.putProperty (stringIDToTypeID ("property"), stringIDToTypeID ("layerID"));
    ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
    return executeActionGet(ref).getInteger(stringIDToTypeID("layerID"));
    };
// 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); 
    }
    };
////// duplicate layer (id, xOffset, yOffset, theXScale, theYScale, theAngle) //////
function layerDuplicateOffsetScaleRotate (theIdentifier, xOffset, yOffset, theXScale, theYScale, theAngle, copy) {
    selectLayerByID(theIdentifier, false);
        var desc23 = new ActionDescriptor();
        var idnull = charIDToTypeID( "null" );
            var ref2 = new ActionReference();
//            ref2.putIdentifier ( charIDToTypeID( "Lyr " ), theIdentifier );
            ref2.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
        desc23.putReference( idnull, ref2 );
        desc23.putEnumerated( charIDToTypeID( "FTcs" ), charIDToTypeID( "QCSt" ), charIDToTypeID( "Qcsa" ) );
        var idOfst = charIDToTypeID( "Ofst" );
            var desc24 = new ActionDescriptor();
            var idPxl = charIDToTypeID( "#Pxl" );
            desc24.putUnitDouble( charIDToTypeID( "Hrzn" ), idPxl, xOffset );
            desc24.putUnitDouble( charIDToTypeID( "Vrtc" ), idPxl, yOffset );
        desc23.putObject( idOfst, idOfst, desc24 );
        var idPrc = charIDToTypeID( "#Prc" );
        desc23.putUnitDouble( charIDToTypeID( "Wdth" ), idPrc, theXScale );
        desc23.putUnitDouble( charIDToTypeID( "Hght" ), idPrc, theYScale );
        desc23.putUnitDouble( charIDToTypeID( "Angl" ), charIDToTypeID( "#Ang" ), theAngle );
        desc23.putEnumerated( charIDToTypeID( "Intr" ), charIDToTypeID( "Intp" ), stringIDToTypeID( "bicubicAutomatic" ) );
        if (copy == true) {desc23.putBoolean( charIDToTypeID( "Cpy " ), true )};
    executeAction( charIDToTypeID( "Trnf" ), desc23, DialogModes.NO );
    };

 

 

code updated 2022-07-10, noticed problems on testing with other files

Votes

Translate

Translate

Report

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
Guide ,
Jul 10, 2022 Jul 10, 2022

Copy link to clipboard

Copied

Interesting way! I'll keep it for myself to understand in detail (I very rarely work with paths)

Votes

Translate

Translate

Report

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 ,
Jul 09, 2022 Jul 09, 2022

Copy link to clipboard

Copied

The Touch Type Tool in Adobe Illustrator is meant for this type of text adjustment.

 

Select the text in Photoshop and copy and paste it to a Text Object in Illustrator (the formatting should be maintained) or start a Text Object in Illustrator from scratch.

Text Object in Adobe Illustrator before using the Tough Type ToolText Object in Adobe Illustrator before using the Tough Type Tool

 

Press Shift T to enable the Touch Type Tool and select a character to start making adjustments the corresponding character's scale, rotaion and posiiton.  Text Object in Adobe Illustrator while using the Tough Type ToolText Object in Adobe Illustrator while using the Tough Type Tool

The text remains fully editable on the Illustrator side, including making changes in the Character panel and the Paragraph Panel.

 

Save the Illustrator file, select the Text Object, and copy and paste back to Photoshop.  When Photoshop presents the Paste options dialog box, choose the option that best matches how you would like to work with the resulting Layer in Photoshop.

Paste options dialog box in Photoshop when pasting a Text Object from Illustrator to PhotoshopPaste options dialog box in Photoshop when pasting a Text Object from Illustrator to Photoshop

Votes

Translate

Translate

Report

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
Guide ,
Jul 10, 2022 Jul 10, 2022

Copy link to clipboard

Copied

LATEST

Thank you! An interesting way. I'm sure it can be automated too 🙂

Votes

Translate

Translate

Report

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 ,
Jul 09, 2022 Jul 09, 2022

Copy link to clipboard

Copied

Hi @jazz-y , not sure if this helps, but the coding might be easier over in InDesign. This gets the selected text and makes frames for each character with random scales and rotations. With a bit more code the randomized text could be exported over to PS via BridgeTalk.

 

app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
var d = app.activeDocument
//some selected text
var t = d.selection[0].characters.everyItem().getElements()

var nf, tp, s;
for (var i = 0; i < t.length; i++){
    tp = t[i].properties
    nf=d.textFrames.add({geometricBounds: getCharBounds(t[i]), fillColor: "None", contents:t[i].contents})
    nf.characters[0].properties = t[i].properties;
    s= getRandom(90,110);
    nf.absoluteRotationAngle = getRandom(-5,5);
    nf.absoluteHorizontalScale = s;
    nf.absoluteVerticalScale = s;
};   
d.selection[0].parentTextFrames[0].remove()


function getCharBounds(t){
    var p = 1
    var y1 = (t.baseline-t.ascent)-p;
    var y2 = (t.baseline+t.descent)+p;
    var x1 = (t.horizontalOffset)-p;
    var x2 = (x1 + (t.endHorizontalOffset-t.horizontalOffset))+p;
    return [y1,x1,y2,x2]
}

function getRandom(min,max){
    return Math.floor(Math.random()*(max-min+1)+min);
}

 

 

Screen Shot 28.png

 

Screen Shot 27.png

Votes

Translate

Translate

Report

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
Guide ,
Jul 10, 2022 Jul 10, 2022

Copy link to clipboard

Copied

Thank you!

Yes, inDesign makes working with text a lot more convenient, as we can see from the amount of code required to access individual letters.

In my case, all layouts were prepared by designer in Photoshop. I could collect and transfer the text layers in inDesign, but fortunately, I already solved this problem without leaving Photoshop 😉

Votes

Translate

Translate

Report

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