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

Performant way for exporting glyphs (codepoint plus bounds) on a per-Character-basis?

Guest
Nov 15, 2011 Nov 15, 2011

For (InDesign 5) export reasons I need to associate Character instances (unicode codepoint) and their corresponding glyph bounds (geometric position & dimension on a "per-character"-basis). ATM, I iterate over all TextFrame instances' characters, creating their outlines via Character.createOutlines(), performing boundary calculations (either by by using Polygon/Path/PathPoints in "more detail required"-variant, or Polygon.geometricBounds in "less detail required"-variant). The obvious downside of the approach is, that I hereby modify the document's content by creating additional objects, by using "createOutlines()", and the performance of the approach is slow: about 4 minutes for exporting ~1600 Characters distributed over two pages per document, avg ~6-7 chars per second (hexacore@2.8Ghz, 8GB RAM). I already "optimized" the approach by using an appropriate UndoMode and disabling the rendering while exporting, and now, after benchmarking different approaches, it seems like the main bottleneck is the required "createOutlines()"-call, for gaining access to geometric bounds on a "per-character"-basis.

Is there any other way, excluding "createOutlines()", for obtaining a Character's bounds?

TOPICS
Scripting
817
Translate
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 ,
Nov 15, 2011 Nov 15, 2011

Is there any other way, excluding "createOutlines()", for obtaining a Character's bounds?

You can call it once for each character/font/size and save the results.

Translate
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
Guest
Nov 15, 2011 Nov 15, 2011

That's indeed a possibility, but in order to be practicable, I need to ensure that for example affine transformations are also considered in the bounds calculations (then being done "manually"), and, to be honest, I currently can't predict how time consuming that might get, as well during implementation as well as during runtime. But I believe your idea should help me out getting more than ~6-7 chars/sec... so thank you for your suggestion.

Translate
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 ,
Nov 16, 2011 Nov 16, 2011

Tarek,
yes, " app.undo()" takes its time…

Instead of undoing every "createOutlines()" action I would prefer "createOutline(false)" which duplicates the character to an path object. After doing your calculation on that new path object you can remove it by "myPathObject.remove()".

Also to sample the results in an array it is faster not to use the "myArray.push(results)" method. Instead use myArray=results.

For that finding a big applause to Marc Autret at:
http://www.indiscripts.com/post/2011/06/comparing-the-performance-of-extendscript-snippets

See the following example code (please, before starting script execution, set the rulers of your test document to "millimeters" and select a bunch of characters). The results, simple width and height calculations on the path objects, will be written to a new table left from page one on the paste board of your document:

start_time = Date.now();

var _d = app.activeDocument;

var _selection = app.selection[0];

var _charactersArray = new Array();

var _charDimensionsArray = new Array();

var _charCount = _selection.characters.length;

for(var n=0;n<_charCount;n++){

    var _character = _selection.characters;

    var _noError = true;

    //In case of a blank there will be no path created, so we need a fall back scenario:

    try{

    var _characterToPath = _character.createOutlines(false);

        }catch(e){_noError = false};

//~     _charactersArray.push(_character.contents);

    //The faster method:

    _charactersArray=_character.contents;

    if(_noError == true){

        var _bounds = _characterToPath[0].visibleBounds;

        var _width = _bounds[3]-_bounds[1];

        var _height = _bounds[2]-_bounds[0];

//~         _charDimensionsArray.push("w x h = "+_width+" x "+_height);

        //The faster method feeding the array:

        _charDimensionsArray = "w x h = "+_width.toString()+" x "+_height.toString();

        //The faster method without using "app.undo()":

        _characterToPath[0].remove();

        }

    else{

        //In case of a blank just store:

        var _width = _character.insertionPoints[1].horizontalOffset - _character.insertionPoints[0].horizontalOffset;

//~         _charDimensionsArray.push("w = "+_width);

        //A faster method to feed the array:

        _charDimensionsArray = "w = "+_width.toString();

        };

    };

var _resultTextFrame = _d.textFrames.add({geometricBounds:[0,-210,297,0]});

var _resultTable = _resultTextFrame.insertionPoints[0].tables.add({

    columnCount:2,

    bodyRowCount:_charactersArray.length

    });

_resultTable.columns[0].width = 20;

_resultTable.columns[0].contents = _charactersArray;

_resultTable.columns[1].width = 190;

_resultTable.columns[1].contents = _charDimensionsArray;

end_time = Date.now();

elapsed_time = end_time - start_time;

alert(((elapsed_time/1000)/60)+" in minutes for "+_charCount+" characters.");

For around 1.600 characters  script execution took around 1.7 minutes on my MacBook Pro with a 2.4 GHz Intel Core 2 Duo and 4 GB 1067 MHz DDR3-ram.

Time will differ if you use it on varied fonts and character sizes.

Hope that helps,
Uwe

Message was edited by: Laubender (just deleted some comments in the script)

Translate
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
Guest
Nov 18, 2011 Nov 18, 2011
LATEST

Thanks Uwe, exspecially the hiresTimer-stuff was very useful for additional benchmarking precision...

Message was edited by: tarek1235 fixed typos

Translate
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