NSPointArray in jstalk plugin?

I’d like to get the associated points of a shape’s bezierPath. My hope was to do something like the following but I am greeted by Acorn crashing with invalid memory address exceptions.

Is there a way to allocate and pass an NSPointArray for the associatedPoints?

Thanks!

        var path = [selectedShape bezierPath];       
        var count = [path elementCount];
        for (var i=0; i<count; i++) {
            try {
                var points = [];
                points[0] = NSMakePoint(0,0);
                points[1] = NSMakePoint(0,0);
                points[2] = NSMakePoint(0,0);  // I think 3 points is enough for all types

                var type = [path elementAtIndex:i associatedPoints:points]
                // do something with type and points
            }
            catch (err) {
            }
        }

EDIT:

I can get a memory buffer that (I think) works with elementAtIndex but now I need to figure out how to get an NSPoint out of an NSMutableData. I’m not a Cocoa/Mac expert by any means so this might be obvious. :slight_smile:

                var data = [[NSMutableData alloc] init]
                [data setLength:(4*2*8)];     // four pairs of doubles
                var points = [data mutableBytes];

                var type = [path elementAtIndex:i associatedPoints:points]

This is going to be pretty tough. I think it might be best for me to update Acorn with some better accessors for it. But maybe you want to give the following a try.

JSTalk is built on Mocha: GitHub - logancollins/Mocha: Objective-C / JavaScript Bridge and Scripting Environment . Mocha comes with a class named MOPointer, which can be used like the following example: Mocha/CoreGraphics.js at master · logancollins/Mocha · GitHub

The problem is, you’re wanting an array of these structs, and I’m not sure it’s going to play nicely with it at all.

So- what about an API on NSBezierPath that looks like this:

- (NSArray*)associatedPointsAtIndex:(NSInteger)index;

That would return an array of NSValues, which you could then call -pointValue on. Would that work?

If you grab the latest build ( http://flyingmeat.com/download/latest/ ), you can do this:

function main(image, doc, layer) {
    
    var selectedShape = layer.selectedGraphics()[0]
    
    var path = selectedShape.bezierPath();
    var count = path.elementCount();
    for (var i=0; i<count; i++) {
        
        var elementType = path.elementAtIndex(i);
        var points = path.associatedPointsAtIndex(i);
        
        if (elementType != 3 /*NSBezierPathElementClosePath, which has no elements.*/) {
            
            // Print the first point
            var p = points[0].pointValue();
            print(p.x + ", " + p.y);
            
            // Or all of them.
            print(points);
        }
    }    
}

Try it out, and let me know if it needs tweaks!

Wow. Thanks for the awesome turnaround. This works great. I had one odd behavior that may be expected. In the following code, C.x and C.y are empty objects (e.g. {}) instead of the float values. If I add 0.0 I get the floats. I assume this is related to the bridge behavior for fields/properties of structs or something.

   var p = points[0].pointValue();
   var C = {
     x: p.x,   // x: p.x+0.0  works?
     y: p.y
   };

Yea, that is weird. Can you send me a sample .acorn file with a vector shape in it that reproduce the problem (sending it to support@flyingmeat.com will work). I’d like to see what’s going on over here.

Sounds good. I just sent a test.acorn and the .jstalk code I am using to support@flyingmeat.com

Thanks.

Thanks for sending that along.

So the reason is because the type of x (from p.x) is a javascript object. And if you just print it out, it’s all good- you see the right values. But then the values are being erased when you use JSON.stringify(C) on it. The JSON parser doesn’t know what to turn the value into.

So when you do p.x + 0, you’re telling javascript to coerce the type into a number, when JSON.stringify does know how to handle.

I’m not sure how to bridge the NSPoint struct over into JavaScript. Maybe there could be a NSPointToJSPoint function that takes one and does the right thing - returns a new object with the .x and .y fields set to the right type? You’re basically already doing that with your workaround.

So- I don’t have a good solution right now. But, I’ll be futzing around with it a bit with the JS bridge which will eventually replace JSTalk in Acorn (FMJS: GitHub - ccgus/fmjs: A JavaScript to C/Cocoa bridge )

Actually- I just tested out what you’re after with the new JS bridge and it handles it already so yay?

Sounds good to me. :slight_smile: