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

Convert Outlines back into Live text

Contributor ,
Dec 01, 2022 Dec 01, 2022

Copy link to clipboard

Copied

Hi everyone,

About a month ago, I came up with the idea of creating a script to covert outlines back into live text and I'm happy to announce that we made it! I would like to thank @Mike Bro@Laubender@pixxxelschubser
@m1b and @Manan Joshi for all the support and apologize if some of the questions raised were not clear in my previous posts.

So basicaly, the script makes a copy of the live text before going through the process of creating outlines, just make sure to create a new Character Style "Outlines" (without any formatting attibutes) and apply to the text you want to outline before running it.

var doc = app.activeDocument;

var myDoc = app.activeDocument;

if(doc.characterStyles.item("Outlines") == null) {
alert('Error!\nThe Character Style "Outlines" doesn'+"'"+'t exist. Create and apply the Character Style "Outlines" and try again.');
exit();
}

app.findTextPreferences = null;
app.findTextPreferences.appliedCharacterStyle = "Outlines";
var found = doc.findText();
for(var i =0;i<found.length;i++) {
			var trans = found[i];
			found[i].duplicate(LocationOptions.AT_BEGINNING , found[i]);
            }

// create character style and condition
  
var new_Style = app.documents[0].characterStyles.add()
new_Style.name = "Original"

try{
    
myDoc.conditions.add({name:"Original", indicatorMethod:ConditionIndicatorMethod.USE_HIGHLIGHT, visible:false})

}catch(e){}
    
// apply style and condition to all duplications

app.findGrepPreferences=app.changeGrepPreferences=null;
app.findGrepPreferences.findWhat = "([\\S\\s]+)\\K\\1";
app.findGrepPreferences.appliedCharacterStyle = "Outlines";
app.changeGrepPreferences.changeTo = "";
app.changeGrepPreferences.appliedCharacterStyle = "Original";
app.changeGrepPreferences.appliedConditions = ["Original"]; 
doc.changeGrep();

// turn on auto-size 

function main() {

    var doc = app.activeDocument;

    // reset grep prefs
    app.findGrepPreferences = NothingEnum.NOTHING;
    app.changeGrepPreferences = NothingEnum.NOTHING;

    // find criteria
    app.findGrepPreferences.appliedCharacterStyle = 'Outlines';

    var found = doc.findGrep();

    for (var i = 0; i < found.length; i++)

        for (var j = 0; j < found[i].parentTextFrames.length; j++) {

            var frame = found[i].parentTextFrames[j];

            if (frame.isValid) {
                frame.textFramePreferences.autoSizingReferencePoint = AutoSizingReferenceEnum.TOP_CENTER_POINT;
                frame.textFramePreferences.autoSizingType = AutoSizingTypeEnum.HEIGHT_ONLY;
            }

        }

}; 

// end main

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Set Autosizing');

// create outlines

app.findTextPreferences = null;
app.findTextPreferences.appliedCharacterStyle = "Outlines";
var found = doc.findText();
for(var i =0;i<found.length;i++)
{
    try{
        found[i].createOutlines();
     }catch(e){}
    }
app.findTextPreferences = null;

// hide original

app.activeDocument.conditions.item("Original").visible = true;
app.activeDocument.conditions.item("Original").visible = false;


Then, you can use the code below to remove the outlines and make the live text visible. Please note that it only works if you use the script above for outlining in the first place.

var doc = app.activeDocument;

app.findTextPreferences = null;
app.findTextPreferences.appliedCharacterStyle = "Outlines";
var found = doc.findText();
for(var i =0;i<found.length;i++)
{
        found[i].remove();
    }
app.findTextPreferences = null;

// make original visible

myConditions = app.activeDocument.conditions;
app.activeDocument.conditions.itemByName("Original").remove();

// turn off auto-size

function main() {

    var doc = app.activeDocument;

    // reset grep prefs
    app.findGrepPreferences = NothingEnum.NOTHING;
    app.changeGrepPreferences = NothingEnum.NOTHING;

    // find criteria
    app.findGrepPreferences.appliedCharacterStyle = 'Original';

    var found = doc.findGrep();

    for (var i = 0; i < found.length; i++)

        for (var j = 0; j < found[i].parentTextFrames.length; j++) {

            var frame = found[i].parentTextFrames[j];

            if (frame.isValid) {
                frame.textFramePreferences.autoSizingType = AutoSizingTypeEnum.OFF;
            }

        }

}; 

// end main

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Set Autosizing');

// remove character styles

app.activeDocument.characterStyles.itemByName("Outlines").remove();
app.activeDocument.characterStyles.itemByName("Original").remove();


I hope you find it useful and any feedback would be greatly appreciated! 🙂

Regards,
Rogerio

TOPICS
Scripting

Views

1.4K

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 ,
Dec 02, 2022 Dec 02, 2022

Copy link to clipboard

Copied

Hi @Rogerio5C09, super work! That's a cool idea, setting up a condition like that. When I have time I will give you some feedback to make your code a bit more robust. Most of all—thanks for sharing with us all!

- Mark

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
Contributor ,
May 15, 2023 May 15, 2023

Copy link to clipboard

Copied

Hi Mark,

I hope you are doing well! 🙂

Listen, I'm creating a version of the outline script that works with all docs. The code below seems promissing, the only problem is that the script is hiding the conditional text only in the active document, so the condition appers hidden in the other docs, but somehow the text is still visible. Weird, right? Is there any way to hide it in all docs?

var doc = app.activeDocument;

var myDoc = app.activeDocument;

if(doc.characterStyles.item("Outlines") == null) {
alert('Error!\nThe Character Style "Outines" doesn'+"'"+'t exist. Create and apply the Character Style "Outines" and try again.');
exit();
}

app.findTextPreferences = null;
app.findTextPreferences.appliedCharacterStyle = "Outlines";
var found = app.findText();
for(var i =0;i<found.length;i++) {
			var trans = found[i];
			found[i].duplicate(LocationOptions.AT_BEGINNING , found[i]);
            }

// Create character style and condition
  
var new_Style = app.documents[0].characterStyles.add()
new_Style.name = "Original"

try{
    
myDoc.conditions.add({name:"Original", indicatorMethod:ConditionIndicatorMethod.USE_HIGHLIGHT, visible:false})

}catch(e){}
    
// Apply style and condition to all duplications

app.findGrepPreferences=app.changeGrepPreferences=null;
app.findGrepPreferences.findWhat = "([\\S\\s]+)\\K\\1";
app.findGrepPreferences.appliedCharacterStyle = "Outlines";
app.changeGrepPreferences.changeTo = "";
app.changeGrepPreferences.appliedCharacterStyle = "Original";
app.changeGrepPreferences.appliedConditions = ["Original"]; 
app.changeGrep();

// Turn on auto-size 

function main() {

    // reset grep prefs
    app.findGrepPreferences = NothingEnum.NOTHING;
    app.changeGrepPreferences = NothingEnum.NOTHING;

    // find criteria
    app.findGrepPreferences.appliedCharacterStyle = 'Outlines';

    var found = app.findGrep();

    for (var i = 0; i < found.length; i++)

        for (var j = 0; j < found[i].parentTextFrames.length; j++) {

            var frame = found[i].parentTextFrames[j];

            if (frame.isValid) {
                frame.textFramePreferences.autoSizingReferencePoint = AutoSizingReferenceEnum.TOP_CENTER_POINT;
                frame.textFramePreferences.autoSizingType = AutoSizingTypeEnum.HEIGHT_ONLY;
            }

        }

}; 

// end main

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Set Autosizing');

// Create outlines

app.findTextPreferences = null;
app.findTextPreferences.appliedCharacterStyle = "Outlines";
var found = app.findText();
for(var i =0;i<found.length;i++)
{
    try{
        found[i].createOutlines();
     }catch(e){}
    }
app.findTextPreferences = null;

// Hide original

app.documents[0].conditions.item("Original").visible = true;
app.documents[0].conditions.item("Original").visible = false;


Thanks in advance for your help!

Regards,
Rogerio


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 ,
May 18, 2023 May 18, 2023

Copy link to clipboard

Copied

Hi @Rogerio5C09, before I get to discussing the issue you describe, I had some other issues that came up, and some of them are discouraging for this particular project, but please don't be discouraged, overall.

 

1. Try and make the script more forgiving for people using it however they like. For example, I ran it, and it told me I needed to create (and apply) an "Outlines" character style which was good—so I made the style, applied it and the script worked. However, then I set some more text in Outlines character style and ran the script again... and received an uncaught error that the name "Original" was already in use and the script aborted. So you need to catch that case and only create the style if it doesn't already exist.

 

2. Maybe another idea is to just have the script work on selected text immediately. So I would select my text I wanted to outline, and run script and it would immediately put the selected text in "outline" condition. With this way, the script could make the "Outlines" character style too and not bother me with the errror from 1.

 

3. I suggest you set the outlined anchored text in a new "Outlined" condition—that way I can just jump between "Outlined" and "Original" conditions and see the change easily. But if you do that you will notice...

 

4. There is a challenge when outlining a part of a story in Indesign—it moves. I have some ideas about how to fix this, but it is not a trivial task. See what you think.

 

5. I really don't want to be discouraging—you're actually doing great, and scripting is hard—but, like @Eugene Tyson, I would never use this script myself. I've been producing artwork for 30 years and I just don't have a use for it. Of course, others may love the functionality you are going-for, so you must be the judge of that.

 

Please have a think about those points, and we'll see where you are after that. The main thing is: keep up the scripting—the more you do, the better you'll get. Hope I haven't discouraged you too much.

- Mark

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 ,
May 15, 2023 May 15, 2023

Copy link to clipboard

Copied

Hi @Rogerio5C09 , I tried your script on an example with properties that typically won’t survive outlining—stroked text frame, Underline text, bullet list, Strikethrough text—and I got this:

 

The original:

Screen Shot 4.png

 

Outlining with your first script:

 

Screen Shot 5.png

 

Restoring with your 2nd script:

 

Screen Shot 6.png

 

I’ve attached the problem file

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 ,
May 15, 2023 May 15, 2023

Copy link to clipboard

Copied

Cool idea - and I appreciate all the effort you put into it.

 

I'm not a fan of outlining text in InDesign - and PDF is the best place to do this after you've created your PDF you can use the Preflight tools to Outline the text.

https://www.copperbottomdesign.com/blog/converting-fonts-to-outlines

 

I'm not really sure I'd have a lot of use for this conversion back.

 

Wouldn't it be simpler to create a new layer for the text and duplicate the text to it - then convert and just hide the other layer?

 

A lot of outlining features don't survive, the outline process in InDesign is unreliable, for underlines, strikethroughs etc. 

 

Cool project though. And it's the first release and hopefully it can be a lot more robust in the future. 

It would be an amazing edition to InDesign to convert to outlines and then convert back to the original text. 

That is pretty awesome. 

 

Well done. And apologies for my random thoughts. 

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 ,
May 18, 2023 May 18, 2023

Copy link to clipboard

Copied

I'm in the same place. Applause for the concept, much appreciation for the effort.

 

But... outlining text is a largely graphical operation that rarely has much need to reverse out, at least in reasonable usage. If you're outlining more than a few words in a headline or title, I think it's a questionable workflow. And you can pretty easily delete a few words and rebuild them if the outlining doesn't work out.

 

Just... seems like a lot of work at a complex solution to what should be a simple problem. Maybe I'm not looking at it right, though. 🙂


╟ Word & InDesign to Kindle & EPUB: a Guide to Pro Results (Amazon) ╢

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 ,
May 18, 2023 May 18, 2023

Copy link to clipboard

Copied

I agree with @James Gifford—NitroPress  and @m1b 

There's a very real case for it - where Cyrillic or non-Latin text is involved, it is crucial that text doesn't reflow/change dramatically if opened again or font changes/updates etc. 

 

I'm sure there are other real-live scenarios for the usage.

 

I applaud it - maybe if InDesign could convert to outlines and back to text natively - and it outlined text correctly - perhaps more people would use it, perhaps not.

 

Converting back is the huge issue - and it's why I either save a 'live text' document and an 'outline document' - edit the Live Text - save - then save as Outline - and the outline the document - if I had to. Usually I'd just outline in the PDF after the generation.

 

And the other way I've tackled it in the past, when I had to, was to use a separate layer for the live text, then outline the text on a copied layer. 

 

As @m1b notes - there is some shift in the text due to the 'hinting' being removed when outlined. 

 

 

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 ,
May 19, 2023 May 19, 2023

Copy link to clipboard

Copied

Hi @Eugene Tyson, I actually wasn't thinking about the loss of hinting—although that is definitely a consideration for low-res applications where grid-fitting is done. I meant that when Text (as in Story, Paragraph, Word objects etc) is outlined in Indesign, it will move left (in left-aligned text) by the amount of the left-sidebearing of the left-most glyph on each line. To get around this we can outline the whole TextFrame. But ...

 

Outlining, manually in Indesign or by createOutlines, just doesn't work on some things. For example, bullets and numbering isn't outlined—if you outline the Story then the bullets/numbering will remain un-outlined, and if you outline the TextFrame, then they'll just disappear. D: @rob day you already knew this—and told us here!—but I didn't quite pick up on how serious it was. Even paragraph rules and table strokes go away!

 

I only just realised this stuff after attempting a "quick", "little" script that (a) makes a copy of a document with a suffix, eg "_OUTLINED", and (b) would just iterate over everything in the document and outline it. Simple.

 

Nope. See below for the actual script. And, read the warning. Still for some jobs it might be useful so I posted anyway.

 

Also I wondered if, @Rogerio5C09, you might have a look and see how a potentially simple script (the original script was just a few lines, and did 95% of what the script below does) expands to handle different problems... auto-page-numbering, in-line anchored text frames, a weird thing that happens when you outline a textframe containing a table in the second-last text frame in a story where the table is the last character... phew! ... and this is just a brand-new script that hasn't been tested pretty much at all. There are probably hundreds of cases where it will fail.

 

I applaud you for posting here though, because it gives everyone a chance to use/test the scripts and make them better. As I said earlier, keep it up!

- Mark

 

/**
 * @file Save Copy As Outlined Document.js
 *
 * @warning DO NOT USE THIS
 * SCRIPT IF YOUR CONTENT
 * CANNOT BE OUTLINED!
 * These features cannot be outlined:
 * - bullet/numbering styles
 * - paragraph rules
 * - underlining, strikethrough, etc
 * - tables, except text
 * - other things!
 *
 * @author m1b
 * @version 2023-05-20
 */
var settings = {
    suffix: '_OUTLINED',
    closeOutlinedDocument: false,
};

function main() {

    var originalDoc = app.activeDocument;

    // add the suffix to the current file's name
    var path = originalDoc.fullName.fsName.replace(/(\.[^\.]+)$/, settings.suffix + '$1');

    // save a copy
    originalDoc.saveACopy(path);

    // open the copy
    var outlinedDoc = app.open(File(path));

    // override master page items
    overrideMasterPageItems(outlinedDoc);
    outlinedDoc.pages.everyItem().appliedMaster = null;

    // every story
    var stories = outlinedDoc.stories.everyItem().getElements();

    // create outlines of anchored text frames
    for (var i = stories.length - 1; i >= 0; i--)
        outlineAnchoredStory(stories[i]);

    // every story again
    stories = outlinedDoc.stories.everyItem().getElements();

    // create outlines of remaining textframes
    for (var i = stories.length - 1; i >= 0; i--) {
        for (var j = stories[i].textContainers.length - 1; j >= 0; j--) {
            try {
                if (stories[i].textContainers[j])
                    stories[i].textContainers[j].duplicate().createOutlines();
            } catch (error) { }
        }
    }

    // remove the originals
    for (var i = stories.length - 1; i >= 0; i--) {
        for (var j = stories[i].textContainers.length - 1; j >= 0; j--) {
            try {
                if (stories[i].textContainers[j])
                    stories[i].textContainers[j].remove();
            } catch (error) { }
        }
    }

    // save
    outlinedDoc.save();

    //close
    if (settings.closeOutlinedDocument)
        outlinedDoc.close();

};

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Save Copy As Outlined Document');


/**
 * Creates outlines of anchored text story.
 * @author m1b
 * @version 2023-05-20
 * @param {Story} story - an Indesign Story.
 */
function outlineAnchoredStory(story) {

    var isEmpty = /^\s*$/;

    if (
        story.textContainers.length !== 1
        || story.textContainers[0].parent.constructor.name !== 'Character'
        || story.textContainers[0].contents.length == 0
        || isEmpty.test(story.textContainers[0].contents)
    )
        // not anchored text frame
        return;

    var tf1 = tf2 = story.textContainers[0];

    // special handling of INLINE or ABOVE_LINE anchorPosition
    if (tf1.anchoredObjectSettings.anchoredPosition !== AnchorPosition.ANCHORED) {
        tf2 = tf1.duplicate();
        tf1.contents = '';
        tf2.geometricBounds = tf1.geometricBounds;
    }

    try {
        tf2.createOutlines();
    } catch (error) { }

};


/**
 * Override All Master Page Items on every page.
 * @author m1b
 * @version 2023-05-20
 * @param {Document} doc - an Indesign Document.
 * @param {Array<Pages>} [pages] - the pages to target (default: all pages).
 */
function overrideMasterPageItems(doc, pages) {

    pages = pages || doc.pages;

    var masterItems = [],
        counter = 0;

    for (var i = 0; i < doc.masterSpreads.length; i++)
        masterItems = masterItems.concat(doc.masterSpreads[i].pageItems.everyItem().getElements());

    for (var i = 0; i < masterItems.length; i++)
        for (var j = 0; j < pages.length; j++)
            try {
                masterItems[i].override(pages[j]);
                counter++;
            } catch (e) { }

    return counter;

};

 

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 ,
May 19, 2023 May 19, 2023

Copy link to clipboard

Copied

Well said Mark.

 

I did know about limitations of InDesign outlines too, bullets, underline, etc.

 

Then what about running headers, TOC, automated stuff too?

 

Maybe it couldnt cater for those scenarios?

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 ,
May 19, 2023 May 19, 2023

Copy link to clipboard

Copied

Yeah, Eugene, I think it was just me who didn't know! Not unusual for me. 🙂

 

I am quite curious as to @Rogerio5C09's use case—I assume that they are successfully (aside from the bug mentioned bug) using the script.

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 ,
May 20, 2023 May 20, 2023

Copy link to clipboard

Copied

In some settings once text is signed off you can't make any changes to it - so if this prevents people from editing an important medical or legal document then it could be a reason for it. 

 

 

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 ,
May 20, 2023 May 20, 2023

Copy link to clipboard

Copied

Yes I agree about not editing signed-off artwork., but I'm still not sure outlining is the thing to do here though. Outlining is good for stopping things accidentally moving after they're outlined, which is a nice feature, but I'm not so sure it does much to stop deliberate editing. One could just open it up and type new text over the old—and the outlined file being no harder than, say, a pdf exported without editing capabilities—which has always been adequate in my experience. Still, Rogerio5C09 may have some insight here.

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 ,
May 20, 2023 May 20, 2023

Copy link to clipboard

Copied

Yeh once had to make edits to a book and they had no files, so we scanned all the pages and then erased text and reset the text where the changes were required. 

 

There's always a way. But I think my idea of cyrllic or non-latin texts is a valid one. Opening on different devices/RIPs etc. could cause unintended glyph changes, which is problematic. 

 

 

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 ,
May 20, 2023 May 20, 2023

Copy link to clipboard

Copied

LATEST

Yep, outlining is excellent for that case!

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