Skip navigation
Currently Being Moderated

Quartz and Quickdraw with MacOS

Apr 6, 2012 3:31 AM

Hello guys,

long time no posts...

 

I m trying to make my plugins running on Windows and Mac.

Basically it works... except for the UI part.

As for drawing rectangle and so on... i succeded to do it with quickdraw until CS4 and with drawBot with CS5

My problem is for circular handles, that i want to get stretched, rotated according to the Layer scale, rotation, zoom factor...

With windows, I succeed to get my stuff done using GDI+

 

void

getLayer2FrameMatrix(

    PF_FloatMatrix&            xform,

    const PF_InData        *in_data,

    const PF_EventExtra    *event_extra)

{

    event_extra->cbs.get_layer2comp_xform(event_extra->cbs.refcon, event_extra->contextH, in_data->current_time, in_data->time_scale, &xform);

    //need to nullify the translation column?

    //xform.set(tmp);

 

    //! Transforms the source coordinates in the current context to screen coordinates.

    //! Screen (frame) coordinates are affected by the current zoom level.

    PF_FixedPoint scale = { INT2FIX(1), INT2FIX(1) };

    event_extra->cbs.source_to_frame(event_extra->cbs.refcon, event_extra->contextH, &scale);

 

    float scaleX = static_cast<float>(FIX_2_FLOAT(scale.x));

    float scaleY = static_cast<float>(FIX_2_FLOAT(scale.y));

 

    xform.mat[0][0] *= scaleX;

    xform.mat[0][1] *= scaleY;

    xform.mat[1][0] *= scaleX;

    xform.mat[1][1] *= scaleY;

    xform.mat[2][0] *= scaleX;

    xform.mat[2][1] *= scaleY;

}

 

     PF_FixedPoint center ={cx ,cy};

     PF_FloatMatrix xform;       

     getLayer2FrameMatrix(xform, in_data, event_extraP);

         HDC hdc;

        PF_GET_CGRAF_DATA((*(event_extraP->contextH))->cgrafptr, PF_CGrafData_HDC, reinterpret_cast<void**>(&hdc));

        Gdiplus::Graphics g(hdc);

        Gdiplus::Pen pen(Gdiplus::Color(color.alpha, color.red, color.green, color.blue), 1);

        pen.SetDashStyle(static_cast<Gdiplus::DashStyle>(style));

        Gdiplus::Matrix mat(xform.mat[0][0], xform.mat[0][1], xform.mat[1][0], xform.mat[1][1], xform.mat[2][0], xform.mat[2][1]);

        g.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);

        g.SetTransform(&mat);

        g.DrawEllipse(&pen, center.x-cr, center.y-cr, cr+cr, cr+cr);

 

 

This is ok for windows and make the deal.

 

My problem occurs when i do it with Mac...

Of course drawbot with CS5 works perfectly. My problem is for anterior version of after effects.

 

With quickdraw there is no ways to make like with GDI+ and specify a matrix.

So I have two solution:

1) compute transform matrix, computing all the point of my circle, transform them with a transformation matrix, use the PaintPoly and FillPoly function

2) use Quartz and its context transformation matrix...

 

I thought that Quartz would work perfectly and simply...

but i was wrong.

The coordinate system is different....

Y is inverted, and the origin is not top left, but bottom left.

I tried to make it work anyways... but it did not...

So i just tried to understand what s happening. I tried to paint a rectangle at the origin of the coordinate system:

 

void *dp = (*(event_extraP->contextH))->cgrafptr;

CGrafPtr port = reinterpret_cast<CGrafPtr>(dp);

CGContextRef context;

OSStatus err = QDBeginCGContext (port, &context);

if (err== noErr){

            CGRect rect = CGRectMake ( 0,0,100,100);      

            CGAffineTransform userToDevice = CGContextGetUserSpaceToDeviceSpaceTransform (context);

            CGAffineTransform deviceToUser = CGAffineTransformInvert ( userToDevice);

            CGContextSetRGBFillColor (context, 1, 0, 0, 1);

            CGContextFillRect (context,rect)

            QDEndCGContext (port, &context);    

}

 

I get a red rectangle... but not on the top or bottom left corner, kind of in the middle of theleft edge of the layer...

 

Then I tried to go back to more basics  and tried

CGAffineTransform userToDevice = CGContextGetUserSpaceToDeviceSpaceTransform (context);
CGAffineTransform deviceToUser = CGAffineTransformInvert ( userToDevice);

to transform my rectangle, and i got in the top left corner of the panel containing the layer panel.

That would be helpfull if I could get the top left corner of the layer panel... But I did not find a way to get it

source_to_frame gives only zoom factor

and

layer_to_comp get the transformation into the layer panel...

 

I m really thinking about going back to the solution 1)...

 

Does anyone have any idea of how to use properly quartz inside after effects?

 

 

Sorry for the vague of my question.

 
Replies
  • Currently Being Moderated
    Apr 7, 2012 2:40 PM   in reply to salvati marc

    i hear your pain.

    seriously, i do.

     

    this is what i did to solve it. (after almost giving up)

     

    CGPoint zero = {0,0};

    CGPoint flipOrigin = CGContextConvertPointToUserSpace(context, zero);

    flippedY = flipOrigin.y - (originaY - event_extraP->u.draw.update_rect.top);


     

    i changed the param names to such that would make sense to you.

    i hope i didn't screw it up while changing.

    you need to get flipOrigin only once per draw call, and not for each drawing operation you do. (but that's obvious)

    :-)

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 9, 2012 2:49 AM   in reply to salvati marc

    no problem man.

    i'm just glad that my sorrow brought joy to someone.

     

    p.s.

    kudos to you for posting your full solution code!

    that's how real contribution to the common knowledge looks like!

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points