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: https://github.com/logancollins/Mocha . Mocha comes with a class named MOPointer, which can be used like the following example: https://github.com/logancollins/Mocha/blob/master/UnitTests/Tests/CoreGraphics.js

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© 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: https://github.com/ccgus/fmjs )

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: