Copy link to clipboard
Copied
I'm trying to detect corrupt compoundPathsItems (those with groupItems within them) I'm asking here before I'm going the SDK route. I've seen different solutions to this here:
Solved: Dealing with Compound Paths made of Groups - Adobe Community - 8826626
My simple idea to do this blazingly fast is to:
1. count doc.groupItem.length
2. duplicate the compoundPathItem
3. check if the doc.groupItem.length has increased.
Simple. The problem is that it ut doesn't update the groupItem count after the duplication. redraw() doesn't have an effect. The only thing I found so far to update the count is to:
item.selected = true; // select something
doc.selection = null; // deselect everything
Maybe you guys have some trix up your sleaves?
Thanks!
oh ok, try this
var idoc = app.activeDocument;
alert(checkIfCorrupt (idoc.compoundPathItems[0]));
function checkIfCorrupt(item) {
var doc = app.activeDocument;
var itemCpy = item.duplicate(item, ElementPlacement.PLACEAFTER);
// Update groupItem count.
itemCpy.translate(10,10);
//item.selected = true;
//doc.selection = null;
for (var i = 0; i < doc.groupItems.length; i++) {
if (doc.groupItems[i].parent == itemCpy) {
itemCpy.remove();
// Return true if corr
...
Copy link to clipboard
Copied
from all the wonderfull workarounds in the link you posted, I would go with
1. checking all groupItem's parent
2. if parent == compoundPath, problem item
3. release, ungroup, remake
Copy link to clipboard
Copied
Hi, I tried all the workarounds in that thread, they are very slow I'm afraid. It takes about 10 seconds on my documents.
My idea is superfast but I'm looking for a better method to "update" the groupItem count.
Selecting/deselecting works but feels a bit clitchy/hacky maybe there's a better way.
function findByComparing(item) {
var doc = app.activeDocument;
var preNum = doc.groupItems.length;
var itemCpy = item.duplicate(item, ElementPlacement.PLACEAFTER);
// update groupItems count
item.selected = true;
doc.selection = null;
if (preNum - doc.groupItems.length != 0) {
itemCpy.remove();
return true;
} else {
itemCpy.remove();
return false;
}
}
Copy link to clipboard
Copied
oh ok, try this
var idoc = app.activeDocument;
alert(checkIfCorrupt (idoc.compoundPathItems[0]));
function checkIfCorrupt(item) {
var doc = app.activeDocument;
var itemCpy = item.duplicate(item, ElementPlacement.PLACEAFTER);
// Update groupItem count.
itemCpy.translate(10,10);
//item.selected = true;
//doc.selection = null;
for (var i = 0; i < doc.groupItems.length; i++) {
if (doc.groupItems[i].parent == itemCpy) {
itemCpy.remove();
// Return true if corrupt
return true;
}
}
itemCpy.remove();
}
** I would move the copy to the very top of the document to check GroupItems[0] parent instead of looping thru all group items in the document
Copy link to clipboard
Copied
it seems you updated your code, but the idea is the same, use the translate trick to force a refresh
Copy link to clipboard
Copied
Thanks, that's what I was looking for. translate() feels alot better than select/deselect. Moving stuff towards the top when iterating is also very clever.
Copy link to clipboard
Copied
Hi @CarlosCanto and @iLLMonkey I have been annoyed by this for a long time and have benefitted from your solutions! For my own benefit—and maybe others?—I have synthesized your ideas and also added option to fix the corrupt CompoundPathItems. As always, there will be complex cases where it fails, but for most cases it will be a good fix I think.
- Mark
/**
* Function to test if a CompoundPathItem is corrupted by internal GroupItems,
* ie. if a document fragment with grouped PathItems was "compounded".
* Also has the option to fix it.
* @discussion https://community.adobe.com/t5/illustrator-discussions/ideas-for-updating-doc-groupitems-length/m-p/14505679
*/
(function () {
var doc = app.activeDocument,
allCompoundPaths = doc.compoundPathItems,
counter = 0;
for (var i = allCompoundPaths.length - 1; i >= 0; i--)
if (compoundPathHasInternalGroups(doc, allCompoundPaths[i], true))
counter++;
alert('Fixed ' + (counter ? counter : 'no') + ' bad compound path items.');
})();
/**
* Returns true when a CompoundPathItem `item`
* is corrupted by internal GroupItems, and
* has the option to fix it using `doFix`.
* @author iLLMonkey - idea to check doc.groupitems.length to instantly measure bad groups in item
* @author CarlosCanto - idea to refresh doc.groupItems and access doc.groupItems[0]
* @author m1b - code to fix CompoundPathItems, and structure.
* @version 2024-03-23
* @param {Document} doc - an Illustrator Document.
* @param {CompoundPathItem} item - an Illustrator CompoundPathItem.
* @param {Boolean} [doFix] - wether to fix the bad compound path item (default: false).
* @returns {Boolean} - whether the item is/was corrupted with internal group items.
*/
function compoundPathHasInternalGroups(doc, item, doFix) {
var g = doc.groupItems.length;
var dup = item.duplicate(item, ElementPlacement.PLACEBEFORE);
dup.left += 1;
var badGroupCount = doc.groupItems.length - g,
isBad = badGroupCount > 0;
if (isBad && doFix) {
// move item to beginning of document, so group items are first
item.move(doc, ElementPlacement.PLACEATBEGINNING);
for (var g = badGroupCount - 1; g >= 0; g--) {
// we can use doc.groupItems[g] because `item` is the first page item
// page item, and any bad internal groups will be the first groups in document
if (item !== doc.groupItems[g].parent)
continue;
// rescue path items
rescuePathItemsFromBadGroup(doc.groupItems[0], item);
// clean up
doc.groupItems[0].remove();
}
// clean up
item.move(dup, ElementPlacement.PLACEAFTER)
}
// clean up
dup.remove();
// return true when the item has/had bad group(s) inside
return isBad;
/**
* Moves path items out of `badGroup` (recursively)
* and puts them into `destination` container.
* @author m1b
* @param {GroupItem} badGroup - an Illustrator GroupItem.
* @param {container} destination - an Illustrator pathItem container, eg. CompoundPathItem.
*/
function rescuePathItemsFromBadGroup(badGroup, destination) {
// rescue the bad groups path items
for (var i = badGroup.pageItems.length - 1; i >= 0; i--) {
if ('GroupItem' === badGroup.pageItems[i].constructor.name)
rescuePathItemsFromBadGroup(badGroup.pageItems[i], destination);
if ('PathItem' === badGroup.pageItems[i].constructor.name)
badGroup.pageItems[i].move(destination, ElementPlacement.PLACEATEND);
}
};
};
Copy link to clipboard
Copied
awesome, thanks for putting this together Mark