Color letters in specific order via scripting? - Is it possible?
Copy link to clipboard
Copied
Hello everyone,
This is something I've done manually. The thing is, I'm going to do it with a quite long text and it would take an insane amount of time
doing it manually. How would I go about if I wanted to script this? Or is there an other way of doing this?
Help of any kind is greatly appreciated.
Thanks
Copy link to clipboard
Copied
Moved to scripting...
Copy link to clipboard
Copied
Hi Taruz,
This can be done using either nested styles or GREP styles.
Nested styles:
1) Highlight Drop Caps and Nested Styles in your paragraph style settings window.
2) Create a new nested style using the rule "Style1 through 1 character", where Style1 is a character style that loads the first color.
3) Do the same with Style2, Style3, etc.
4) Then, add a [Repeat] nested style over the last N styles, where N is the number of previously defined character styles (that is, the number of colors).
GREP styles:
Indiscripts :: Cyclic GREP Styles
@+
Marc
Copy link to clipboard
Copied
@Marc – I tested the GREP version (thank you for the patterns in your blog post) with 6 GREP Styles in one paragraph style.
Note: It's possible to spoil the pattern a bit, if the feature "Ligatures" is turned ON. (It is by default.)
See here:
Now the question is: Should the pattern start anew in every paragraph?
What to do, if we have table cells and the pattern should go on? Footnotes?
Then we need a more sophisticated approach by scripting this.
Uwe
Copy link to clipboard
Copied
@Uwe
This ligature issue is very enlightening, thanks! I never realized before that one cannot 'colorize' a character individually if that character belongs to a ligature. Yet it makes sense, since color is necessarily a glyph-level attribute.
Interestingly, you can note that the character 'h' (in the 'Th' ligature of your figure) has in fact the orange color applied, but this color is overridden by the red applied to the character 'T'. So, in a ligature, the first character wins.
@+
Marc
Copy link to clipboard
Copied
@Marc – yes, the Swatches Panel is showing an orange for the "h" glyph in the ligature "Th".
Since we are in the Scripting Forum here, we could ask for the fillColor.name of the individual character "h" in the ligature "Th" of my example.
Select the "h" and ask for:
var myFillColorName = app.selection[0].fillColor.name;
If we do, a red will be returned. That seems to be ok, but be cautious:
But that is misleading as well!
ALL the characters of that paragraph will return the same value: a red!
That's seem to be because of the first GREP Style in the rows of GREP Styles, that color all characters with a "red".
Select some more text, a bunch of different colored characters (5 in this case) and run the following snippet from the ESTK:
var myFillColorNamesArray = app.selection[0].texts[0].characters.everyItem().getElements();
for(var n=0;n<myFillColorNamesArray.length;n++){
$.writeln(myFillColorNamesArray
.fillColor.name); };
/*
RESULT IM MY CASE:
C=0 M=100 Y=100 K=0
C=0 M=100 Y=100 K=0
C=0 M=100 Y=100 K=0
C=0 M=100 Y=100 K=0
C=0 M=100 Y=100 K=0
*/
No different color names will be returned! Just the one name that is applied from the first GREP Style.
(InDesign CC-2014.1 on Mac OSX 10.7.5)
Now the question is: How can we make sure to get the "right" color names?
Let's probe this with textStyleRanges instead of individual characters:
app.selection[0].texts[0].textStyleRanges.length;
That will return one single textStyleRange ??!! How can that be…
Hm. No idea now how to test on for the rendered color on the page.
Uwe
Copy link to clipboard
Copied
Hm. Yes, the test would be:
Convert text to outlines and check the fill color of the individual paths of the outlined characters.
//For a single selected character:
var myDupArray = app.selection[0].characters[0].createOutlines(false); //Do a duplicate
$.writeln(myDupArray[0].fillColor.name);
myDupArray[0].remove();
What a mess!
Uwe
Copy link to clipboard
Copied
Laubender wrote:
[...] What a mess!
I had the same problem, but with underlining: an author wanted to have the first character of some words underlined, and if that started with 'fi' or 'fl' the entire ligature got underlined. A quick-and-dirty solution was switching off ligatures in my Underline character style
(... Converting to outlines is not an option for underlining ...)
Copy link to clipboard
Copied
Hi, Jongware!
Yes. Unfortunately…
But the base problem has nothing to do with ligatures turned "ON" or "OFF" I think.
It's far worse!
Just turn "OFF" ligatures and do my test for the fillColor.name again. Same mess.
It's all about GREP Styles and the building of, no, the not building of textStyleRanges on text level according to the rendered characters on the page.
Uwe
Copy link to clipboard
Copied
Here my cascade of GREP-Styles to color individual characters in sequence (adapted from Marc's example on his blog):
CharStyle-1 => Apply FillColor 1
.
CharStyle-2 => Apply FillColor 2
(?<=.).{1,5}
CharStyle-3 => Apply FillColor 3
(?<=..).{1,4}
CharStyle-4 => Apply FillColor 4
(?<=...).{1,3}
CharStyle-5 => Apply FillColor 5
(?<=....).{1,2}
CharStyle-6 => Apply FillColor 6
(?<=.....).
Here the screenshot of the paragraph style in question:
Uwe
Copy link to clipboard
Copied
The textStyleRange is built on the first of the cascading GREP Styles.
That's all to it. Really mean!
Uwe
Copy link to clipboard
Copied
Hm, that's not all to it 😉
By far.
In my example only one property is assigned to all my applied GREP Styles: fillColor
Would different textStyleRanges be built, if we change a different second property in every character style of the GREP Styles?
Something that would have no or only a little visible effect on the page?
How about vericalScale to a minute amount: 100,1%. 100,2% etc.; different to every of the character styles?
Or how about using an exotic property like warichuSize ? Don't know exactly what that is, but sounds exotic enough, that when applied on a plain western character, no visible effect will be there.
Since it's easier to this with verticalScale in the UI, I made a little experimentand just did that.
RESULT: Also a single textStyleRange !!!
That is mad!
Uwe
Copy link to clipboard
Copied
But of course I could have tricked myself here!
I should have used 6 different properties for GREP Styles instead of 6 different values of a second property.
Then we could have 6 different textStyleRanges?
Tested that, but with the same sad result: Only one single textStyleRange.
Then, a final test:
Use 6 totally different character styles.
No applied property in common.
Result: Only one single textStyleRange.
Uwe
Copy link to clipboard
Copied
And on with some tests.
Say, we have one paragraph applied to a Paragraph Style with a cascade of GREP Styles like the one above.
And we decouple the paragraph style from the paragraph:
That menu command from the Paragraph Styles Panel would be: "Verknüpfung mit Format aufheben" in my German InDesign.
In English "Break Link with Style" or "Break Link To Style" (I'm not sure).
How many textStyleGroups would you expect now, if the paragraph consists of 15 characters and no paragraph return sign? 15 ?
Wrong. It's just one single textStyleGroup. Why? The GREP Styles have survived and are still attached to the paragraph.
You can see that, if you visit the Paragraph Panel (not the Pragraph Style Panel).
All tests with inDesign CC-2014.1 on Mac OSX 10.7.5.
Uwe
Copy link to clipboard
Copied
My guess is that text style ranges do not consider actual formatting. Splits are made based on formal attributes, that is character and character-style settings.
GREP and nested styles should be regarded as artifacts. TextStyleRanges do not see their effects.
@+
Marc
Copy link to clipboard
Copied
GREP and nested styles should be regarded as artifacts. TextStyleRanges do not see their effects.
@Marc – yes indeed. We should be cautious with reading out properties and interpreting their values when GREP Styles or nested styles are at play.
Could we somehow enclose ligatures in that class of artifacts? Or other OTF (OpenTypeFont) features? Like OT discretionary ligatures.
As I see it, ligatures could be present as:
1. Standard Ligatures (as the font creator has defined them in OTF, TT and PostScript Type1 fonts)
2. Open Type Discretionary Ligatures (as the OTF creator has defined them)
And of course, if the user has set these options on character level, on paragraph level, with or without paragraph styles or character styles influenced by GREP Styles and other Nested Styles.
Back to that what I said about a plug-in to show the rendered properties of a character.
After some tests with OT Discretionary Ligatures I'm not sure at all, this could be done even with a plug-in.
The UI can only "guess" what the rendered color or form is.
Better put: We sometimes are thinking that the UI is knowing what the rendered color or form is.
A very good example of this is indeed a ligature for two (or even three) characters with more than one fill colors applied:
In the example above we simply cannot detect what the fill color rendered on the screen really is.
We can do some assumptions, we can calculate a lot, but we wouldn't know.
And sometimes we have to fail… 😉 😉
Uwe
PS.: I hope, I will never underestimate the creative energy of my customers using the tools of InDesign…
Copy link to clipboard
Copied
Hi guys,
are you aware of the appliedNestedStyles property?
Just tried with CS5 and CS6, it yields the chararacter style applied by a grep style.
Btw, in the SDK the term for all those different ways to dynamically invoke a character style is "run-in style"
Copy link to clipboard
Copied
@Dirk
Wow! Indeed appliedNestedStyles does include GREP-based styles.
Thanks for pointing this out.
@+
Marc
Copy link to clipboard
Copied
Hi, Dirk!
Yes. Now that you mentioned that property, I'm aware of it. 😉
So what will that property return in the case of our applied cascade of GREP Styles?
An array of all character styles applied in the paragraph. The order is from top to bottom.
Which of the character styles' properties will trickle through these styles?
That will determine the engine behind the GREP Styles.
The bottom most value of a given property will win, if the GREPs format the same character with the same property.
At least that's the theory behind it, I think.
I'll do some tests, if that will help to determine what a character will look like rendered.
But I'm not optimistic that this will lead to a "water-proof" algorithm.
I am working at a phenomenon concerning cascading (circular) GREP Styles vs. GREP search and replace sequences.
Have to think this through first before going into details here.
Uwe
Copy link to clipboard
Copied
@Uwe
Looks like it's a 'stack' array. The latest applied style is on top (=the higher index).
Copy link to clipboard
Copied
@Marc – see my screenshot in answer #9. The returned array of appliedNestedStyles is built like that.
Top character style is index 0, bottom character style is index 5..
Uwe
Copy link to clipboard
Copied
@Marc – all six character styles are returned, if we inspect every sixth character of the paragraph.
The first character will return just one, the second character the character style 1 and 2, and so on.
That sequence will begin anew with character seven.
Ok. So we could calculate a list of all applied properties for every character style that is involved for every single character.
We know the hierarchy. The ingredients for an algorithm are there…
That leave us with the task to determine if ligatures are at work and calculating their effects on character styling…
Uwe
Copy link to clipboard
Copied
@Uwe
As far as I can see the ligature 'artifact' is a very different problem, a rendering thing, which we shouldn't blend with run-in styles.
1. Thanks to Dirk one can now easily design an algorithm that tells which character styles are finally, actually applied to any single character, including dynamic attributes. That's the big news for me, since until now I didn't know any way to retrieve this information. In terms of character attributes, the scripting DOM will now tell us exactly what the GUI tells to the user.
2. As for ligatures, they take the topic to a whole new level (which however remains more anecdotal IMHO). The fact is that a ligature is a single glyph—not a character—that 'owns' more than one character. In most cases the ligature is broken as soon as its embedded characters do not share the same attributes (size, style, scaling, and many more). There are only a few exceptions to this rule: color, underline, strikethrough (and probably a few more I've not in mind). In those very specific cases the attribute of the 1st character (within the ligature) takes the precedence at the rendering level, and only at the rendering level, despite the possibility that next characters have a distinct value for the considered attribute. E.g. in 'fi' a different color may be applied to 'i'—and this is what the Swatch panel indicates when you only select that character—but as long as the glyph substitution is done the 'i' somewhat loses its graphic individuality and just inherits the color of the entire glyph, which is determined by the color applied to the first character.
But take note that a character-driven algorithm will still report attributes that match those seen in the GUI. So the question is, do you really want to provide a script that doesn't fit InDesign own rules?
@+
Marc
Copy link to clipboard
Copied
Hi again,
it is going to be a bit more complicated.
OpenType fonts have mechanisms that can combine glyphs - e.g. into ligatures, but there are also mechanisms for the opposite way. As I understand it that is mainly used for intermediate glyph strings to decompose complicated glyphs in non-roman scripts before they are reassembled, e.g. allowing for ligature glyph substitutions on the reduced set of intermediates.
Even for roman script you should also not forget about combining diacritical marks, there are special unicode values that would for example place the Umlaut dots u\0308 onto a plain ascii "a". That way it should also be possible to colorize the base character and the diacritical mark separately! At least if the font supports the diacritical mark, e.g. Arial. Unfortunately it did not work when I tried it right now, until I also applied a baseline shift which at the same time moved the dots to the right by a half character. That's some obscure composer bug 😉
Regarding obscure composer bugs, I'd also consider the underline extending to the following characters of the ligature a bug - obviously InDesign can determine the width of individual character parts at least for the display of selection highlights, as shown in Uwe's big screen shot.
Some more theory: When the composer analyzes our text, its main product is a complicated display list "wax" of glyph strings "wax run" with shared attributes, arranged in "wax lines", otherwise roughly similar to our text style runs. Of course only attributes relevant for quick rendering is recorded - fonts, colors, scale and positioning, glyph IDs, start and end character offsets. Even though not exposed to scripting or IDML, this data structure is perfectly accessibly for plugins and it is persisted with its text story, so that documents are rendered the same way even across versions, until recompose is triggered.
This also explains the horizontal offset after I applied the baseline shift to the combining diaeresis: apparently the composer tears the wax runs apart before positioning the dots - baseline shift is relevant -, as it can not maintain strict associations between the character bound attribute spans and the glyph strings derived from the characters. The positioning is then a wild guess from the font designer, rather than considering the preceding glyph.
Regarding the order of character styles: the composers obtain all run-in styles by means of a single call, and that's most likely also delivered thru the appliedNestedStyles property. Within the set of styles there is an order by kind, then by order in the kind (increasing priority): drop caps, nested styles, grep styles, line styles. And don't forget that the applied character style beats all but the direct overrides.
Please also note: When I the last time used the appliedNestedStyles property, I had some situation where Null was delivered instead of one char style. I just remembered it from a code comment but not the exact circumstances, so beware.
Btw, as you above theorized about a plugin, do you really see a practical use for something that would provide readonly access to all those metrics? Not that I have had too much spare time recently ...
Copy link to clipboard
Copied
Hi, Dirk!
All that is really fascinating.
Thank's for your insight!
Now for the purpose of that proposed plugin:
It wouldn't be for the "normal", none-scripting community.
At least not as a stand-alone utility.
For scripters, I could see some purposes. The plugin (or a reliable ExtendScript method, but we possibly would not get there) will be like an intermedia step, maybe a reliable method we can call when working with text: To store "visible" formatting, so we could successfully translate that to environments that do not know about Nested Styles, GREP Styles (or ligatures).
Especially Adobe Illustrator, PhotoShop and AfterEffects reachable through BridgeTalk come to mind.
In short: It would help for getting rid of styles in situations where the appearance of a text should be absent of the influence of styles.
Just plain overrides, that could be applied in other apps. Or helping to move successfully "rendition" of text from one InDesign document to another without losing control because of the influence of set target styles with the same name.
IDMS is no big help in this regards, because the target can dictate the styling of the placed snippet. This could be good, this could be bad.
Libraries come to mind, if I think of exchanging assets between apps like Illustrator and PhotoShop. CC Libraries currently work between PhotoShop and Illustrator. Adobe is planning to include InDesign in that game. See: Re: Adding Libraries (2014 CC) to InDesign
Perhaps we should wait what will become of that project…
Uwe


-
- 1
- 2