Copy link to clipboard
Copied
Please, could you help me build a code?
I am trying to get bounds from the selection (visiblebounds) but with the peculiarity of that of the text bounds (be outlines).
This code works only in groups that are not masked. Could you help correct it please?
Or do you know a better code?
function getBounds(obj) {
var selObj1 = new Array();
var selObj2 = new Array();
var vgb1 = new Array();
var vgb2 = new Array();
var n = obj.length;
if (n > 0) {
// ignore worst case of (1) type on path or (2) guide items
if ((obj[0].guides == true)) {
// do nothing
} else {
if (obj[0].typename == 'TextFrame') {
//alert("1 - obj.typename=TextFrame")
objcopy = obj[0].duplicate().createOutline();
vgb1 = objcopy.visibleBounds;
objcopy.remove();
}
// group items that are masked case
else if ((obj[0].typename == 'GroupItem') && obj[0].clipped && (obj[0].pageItems.length > 1)) {
clipObj = obj[0].pathItems[0].visibleBounds;
vgb1 = clipObj;
} else {
selObj1 = obj[0];
vgb1 = selObj1.visibleBounds;
}
/* } else {
vgb1 = new Array;
vgb1[0] = vgb1[1] = vgb1[2] = vgb1[3] = null;
*/
}
// loose page items case
if (n > 1) {
for (i = 1; i < n; i++) {
selObj2 = obj;
// do a test here for the path type (ignore it, break to next object)
/*if( (obj.guides) ){
continue;
}*/
// do a test here for the guides type (ignore it, break to next object)
if ((obj.guides == true)) {
// do nothing
} else {
if (obj.typename == 'TextFrame') {
//alert("1 - obj.typename=TextFrame")
objcopy = obj.duplicate().createOutline();
vgb2 = objcopy.visibleBounds;
objcopy.remove();
}
// layer clipping mask case
else if ((obj.typename == 'PathItem') && (obj.clipping)) {
clipObj = obj.geometricBounds;
vgb2 = clipObj;
return vgb2;
}
if ((obj.typename == 'GroupItem') && obj.clipped && (obj.pageItems.length > 1)) {
vgb2 = obj.pathItems[0].visibleBounds;
} else {
vgb2 = selObj2.visibleBounds;
}
if (vgb1[0] > vgb2[0]) vgb1[0] = vgb2[0];
if (vgb1[1] < vgb2[1]) vgb1[1] = vgb2[1];
if (vgb1[2] < vgb2[2]) vgb1[2] = vgb2[2];
if (vgb1[3] > vgb2[3]) vgb1[3] = vgb2[3];
}
}
}
}
return vgb1;
}
Thank you very much.
Greetings.
Copy link to clipboard
Copied
Hi, levi23​!
Here it seems to be what you need:
//@target illustrator
getMaxCollectionBnds(selection, 'geometricBounds');
/**
* get maximum bounds of the collection of the elements or one element
*
* @param {Array/PageItem} collection
* @param {String} boundsType - geometricBounds or visibleBounds
* @return {Array} bounds - array af the maximal bounds of the entire colleciton or element
* */
function getMaxCollectionBnds(collection, boundsType) {
var bndsType = boundsType || 'geometricBounds';
var bounds = _getMaxBnds(collection, []);
return bounds;
/**
* recursive search maximum bounds
*
* @param {Object} collection - selection, PageItems or PageItem
* @param {Array} bounds - last maximal bounds
* @return {Array} bounds - maximal bound
* */
function _getMaxBnds(collection, bounds) {
var bnds = bounds;
// case then passed one item rather then true collection
if (collection.typename == 'PathItem' ||
collection.typename == 'CompoundPathItem' ||
collection.typename == 'TextFrame') {
return _cmprBnds(collection, bnds);
}
for (var j = 0; j < collection.length; j++) {
var el = collection
; // anything PageItem exclude GroupItem
if (el.typename != 'GroupItem') {
if (bnds == '') {
bnds = _getElemBnds(el);
continue;
}
bnds = _cmprBnds(el, bnds);
}
// group contains a mask -> search this mask
if (el.typename == 'GroupItem' && el.clipped) {
var groupPaths = el.pathItems;
for (var i = 0; i < groupPaths.length; i++) {
if (groupPaths.clipping) {
if (bnds == '') {
bnds = _getElemBnds(groupPaths);
continue;
}
bnds = _cmprBnds(groupPaths, bnds);
}
}
}
// group contains no a mask and a groups
if (el.typename == 'GroupItem' && !el.clipped && !el.groupItems) {
if (bnds == '') {
bnds = _getElemBnds(el);
continue;
}
bnds = _cmprBnds(el[bndsType], bnds);
}
// group contains no a mask, but contains a groups -> recurse
if (el.typename == 'GroupItem' && !el.clipped && el.groupItems) {
bnds = _getMaxBnds(el.pageItems, bnds);
continue;
}
}
return bnds;
}
/**
* comparing the geometricBounds of two PageItems
*
* @param {PageItem} elem - the object of Illustrator DOM PageItem class
* @param {Array} boundsToCompare
* @return {Array} [left, top, right, bottom]
* */
function _cmprBnds(elem, bndsToCompare) {
var elemBnds = _getElemBnds(elem);
return [
Math.min(elemBnds[0], bndsToCompare[0]),
Math.max(elemBnds[1], bndsToCompare[1]),
Math.max(elemBnds[2], bndsToCompare[2]),
Math.min(elemBnds[3], bndsToCompare[3])
]
}
/**
* get the bounds of one element
*
* @param {PageItem} elem - object of PageItem of Illustrator DOM class
* @return {Array} elemBnds - element bounds
* */
function _getElemBnds(elem) {
var elemBnds;
if (elem.typename == 'TextFrame') {
var elemCurvedCopy = elem.duplicate().createOutline();
elemBnds = elemCurvedCopy[bndsType];
elemCurvedCopy.remove();
} else {
elemBnds = elem[bndsType];
}
return elemBnds;
}
}
Copy link to clipboard
Copied
This is great code, and for smart, intelligent, individuals it will be a great method to get the bounds of clipped text objects.
However, for those who want to take the easy way out and 'cheat' (provided, CS6+ is used), the following will suffice after a grouped copy has been made of all the items needed:
app.executeMenuCommand("outline");
app.executeMenuCommand("Live Pathfinder Trim");
app.executeMenuCommand("expandStyle");
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Excuse a question. How does the code work without selections?
* @param {Object} collection - selection, PageItems or PageItem
With selection it works perfectly, but if concrete an PathItem returns
NaN, NaN, NaN, NaN
sel = activeDocument.selection;
getMaxCollectionBnds(sel[0], 'geometricBounds');//retun NaN, NaN, NaN, NaN
Any help please?
Supposedly it works with ... * PageItems or PageItem
How?
Thanks in advance.
Regards
Copy link to clipboard
Copied
fixed:
getMaxCollectionBnds(selection[0], 'geometricBounds');
function getMaxCollectionBnds(collection, boundsType) {
var bndsType = boundsType || 'geometricBounds';
var bounds = _getMaxBnds(collection, []);
return bounds;
function _getMaxBnds(collection, bounds) {
var bnds = bounds;
// case then passed one item rather then true collection
try {
var oneElemBnds = collection[boundsType];
if (oneElemBnds[0]) {
return oneElemBnds;
}
} catch (e) {
}
for (var j = 0; j < collection.length; j++) {
var el = collection
; // anything PageItem exclude GroupItem
if (el.typename != 'GroupItem') {
if (bnds == '') {
bnds = _getElemBnds(el);
continue;
}
bnds = _cmprBnds(el, bnds);
}
// group contains a mask -> search this mask
if (el.typename == 'GroupItem' && el.clipped) {
var groupPaths = el.pathItems;
for (var i = 0; i < groupPaths.length; i++) {
if (groupPaths.clipping) {
if (bnds == '') {
bnds = _getElemBnds(groupPaths);
continue;
}
bnds = _cmprBnds(groupPaths, bnds);
}
}
}
// group contains no a mask and a groups
if (el.typename == 'GroupItem' && !el.clipped && !el.groupItems) {
if (bnds == '') {
bnds = _getElemBnds(el);
continue;
}
bnds = _cmprBnds(el[bndsType], bnds);
}
// group contains no a mask, but contains a groups -> recurse
if (el.typename == 'GroupItem' && !el.clipped && el.groupItems) {
bnds = _getMaxBnds(el.pageItems, bnds);
continue;
}
}
return bnds;
}
function _cmprBnds(elem, bndsToCompare) {
var elemBnds = _getElemBnds(elem);
return [
Math.min(elemBnds[0], bndsToCompare[0]),
Math.max(elemBnds[1], bndsToCompare[1]),
Math.max(elemBnds[2], bndsToCompare[2]),
Math.min(elemBnds[3], bndsToCompare[3])
]
}
function _getElemBnds(elem) {
var elemBnds;
if (elem.typename == 'TextFrame') {
var elemCurvedCopy = elem.duplicate().createOutline();
elemBnds = elemCurvedCopy[bndsType];
elemCurvedCopy.remove();
} else {
elemBnds = elem[bndsType];
}
return elemBnds;
}
}
Copy link to clipboard
Copied
It works. Thank you very much for your help.
Greetings.
Copy link to clipboard
Copied
Thank you for helping to find a bug!
Copy link to clipboard
Copied
Sorry again but I found another bug.
When the code is applied on a clipmask, and the content is larger than the mask. The resulting bounds (visibleBounds) do not return the measures of the mask. (Include parts of clipped paths)
Someone help me to solve it ?. Many thanks.
Sorry for bothering you.
A greeting.
Copy link to clipboard
Copied
Many thanks. The code is perfect
Copy link to clipboard
Copied
I show you the Bug that I detected
If you try the code on a clipmask in which the content is greater than the mask you can verify that the code is malfunctioning.
function getMaxCollectionBnds(collection, boundsType) {
var bndsType = boundsType || 'geometricBounds';
var bounds = _getMaxBnds(collection, []);
return bounds;
function _getMaxBnds(collection, bounds) {
var bnds = bounds;
// case then passed one item rather then true collection
try {
var oneElemBnds = collection[boundsType];
if (oneElemBnds[0]) {
return oneElemBnds;
}
} catch (e) {
}
for (var j = 0; j < collection.length; j++) {
var el = collection
; // anything PageItem exclude GroupItem
if (el.typename != 'GroupItem') {
if (bnds == '') {
bnds = _getElemBnds(el);
continue;
}
bnds = _cmprBnds(el, bnds);
}
// group contains a mask -> search this mask
if (el.typename == 'GroupItem' && el.clipped) {
var groupPaths = el.pathItems;
for (var i = 0; i < groupPaths.length; i++) {
if (groupPaths.clipping) {
if (bnds == '') {
bnds = _getElemBnds(groupPaths);
continue;
}
bnds = _cmprBnds(groupPaths, bnds);
}
}
}
// group contains no a mask and a groups
if (el.typename == 'GroupItem' && !el.clipped && !el.groupItems) {
if (bnds == '') {
bnds = _getElemBnds(el);
continue;
}
bnds = _cmprBnds(el[bndsType], bnds);
}
// group contains no a mask, but contains a groups -> recurse
if (el.typename == 'GroupItem' && !el.clipped && el.groupItems) {
bnds = _getMaxBnds(el.pageItems, bnds);
continue;
}
}
return bnds;
}
function _cmprBnds(elem, bndsToCompare) {
var elemBnds = _getElemBnds(elem);
return [
Math.min(elemBnds[0], bndsToCompare[0]),
Math.max(elemBnds[1], bndsToCompare[1]),
Math.max(elemBnds[2], bndsToCompare[2]),
Math.min(elemBnds[3], bndsToCompare[3])
]
}
function _getElemBnds(elem) {
var elemBnds;
if (elem.typename == 'TextFrame') {
var elemCurvedCopy = elem.duplicate().createOutline();
elemBnds = elemCurvedCopy[bndsType];
elemCurvedCopy.remove();
} else {
elemBnds = elem[bndsType];
}
return elemBnds;
}
}
var doc = app.activeDocument;
sel = activeDocument.selection;
for (var s = 0; s < sel.length; s++) {
IntersectArtboardIndx = []
obj = sel
Bounds=getMaxCollectionBnds(obj, 'visibleBounds')
var rect = doc.pathItems.rectangle(Bounds[1], Bounds[0], (Bounds[2] - Bounds[0]), (Bounds[1] - Bounds[3]));
}
If we change this line: [obj] instead of obj
Bounds = getMaxCollectionBnds ([obj], 'visibleBounds')
The code seems to work correctly.
Could you please help me correct it?
Thank you very much in advance
Regards