Skip to main content
Inspiring
February 24, 2012
Answered

Getting the global position matrix for each text character

  • February 24, 2012
  • 1 reply
  • 1723 views

This post is a follow up to this related post.

I need to get the position and orientation of the first and the last character in a text frame art, that is, I need its  matrix.

There are a number of functions in the API that is supposed to help you; here's a snippet from the file ATESuites.h

/** Return transformation matrix of this run.

The matrix returned spesify the full transformation of the given run.  You need to transform the origin by IGlyphRun::GetOrigins() and

concat with ITextFrame::GetMatrix() in order to get the location of the glyphs.

*/

ATEErr (*GetMatrix) ( GlyphRunRef glyphrun, ASRealMatrix* ret);

Hence, getting the matrix of the first character or glyph should look something like this:

AIErr

VMGetFirstTextMatrix(  AIArtHandle textArt, AIRealMatrix *matrix)

{

    ASRealMatrix frameMatrix, glyphMatrix;

    ASRealPoint firstPoint;

    try

    {

        TextFrameRef ateTextRef;

        sAITextFrame->GetATETextFrame( textArt, &ateTextRef);

        ITextFrame textFrame( ateTextRef);

        ITextLinesIterator lnItr = textFrame.GetTextLinesIterator();

        ITextLine txtLine = lnItr.Item();   

       

        IGlyphRunsIterator grItr = txtLine.GetGlyphRunsIterator();

        IGlyphRun glyphRun = grItr.Item();

       

        IArrayRealPoint pointArray = glyphRun.GetOrigins();

        firstPoint = pointArray.Item(0);   // comes out with wrong values!!!

       

        frameMatrix = textFrame.GetMatrix();

        glyphMatrix = glyphRun.GetMatrix();

              

        sMath->AIRealMatrixConcatTranslate( &glyphMatrix,

                        firstPoint.h, firstPoint.v);

        sMath->AIRealMatrixConcat( (AIRealMatrix*) &glyphMatrix,

                   (AIRealMatrix*) &frameMatrix,

                   matrix);

                      

        return kNoErr;

    }

    catch (ATE::Exception e)

    {

        return e.error;

    }

   

        return kNoErr;

}

But the coordinates, either returned in frameMatrix (tx and ty) or the firstPoint are obviously wrong. It appears that they an offset which is allmost constant.  The x-values are approx 7664 points too large (give and take a few decimals), and the y-values are approx 7893 too large (also give and take a few decimals).

I'm reall puzzled by this, because I need to get accurate positions...

This topic has been closed for replies.
Correct answer arenol

Well, I worked it out eventually.

The ITextFrame::GetMatrix() method usually  returns an identity matrix, unless I have moved or transformed the text frame object on the artboard.  For example, if I have duplicated a text frame object by draging the object while pressing the alt-key, this matrix will hold the relative transformation compared to the object it was spawned from. Since this is a relative transformation, it's neither in hard nor soft coordinates, so it makes no sense to harden or soften it (actually, you musn't do that).

Next, the IGlyphRun::GetMatrix() method will  usually return the identity matrix, but will contain a rotation for example if the object is a text along a path.

Finally, the IGlyphRun::GetOrigins() method will return hard coordinates for each glyph position, but without the transformation from the frame matrix.  This method is oblivious to the GetCoordinateSystem / SetCoordinateSystem functions of the HardSoft suite, and returns hard coordinates regardlessly.

Thus, in order to get the actual art board coordinates of a glyph, the following code will do the trick:

    IArrayRealPoint pointArray = glyphRun.GetOrigins();

    AIRealPoint firstPoint = pointArray.Item(0);

    AIRealMatrix frameMatrix = textFrame.GetMatrix();

    sMath->AIRealMatrixXformPoint( &frameMatrix, &firstPoint, &hardPoint);

    sHardSoft->AIRealPointSoften( &hardPoint, &glyphPoint);

In order to get the absolute position matrix of the first glyph of a text frame art, the following function seem to work:

AIErr

GetFirstTextMatrix(  AIArtHandle textArt, AIRealMatrix *matrix)

{

    ASRealMatrix frameMatrix, glyphMatrix;

    ASRealPoint firstPoint, softPoint, hardPoint;

    try

    {

        TextFrameRef ateTextRef;

        sAITextFrame->GetATETextFrame( textArt, &ateTextRef);

        ITextFrame textFrame( ateTextRef);

        ITextLinesIterator lnItr = textFrame.GetTextLinesIterator();

        ITextLine txtLine = lnItr.Item();   

        IGlyphRunsIterator grItr = txtLine.GetGlyphRunsIterator();

        IGlyphRun glyphRun = grItr.Item();

        IArrayRealPoint pointArray = glyphRun.GetOrigins();

        firstPoint = pointArray.Item(0);

        sHardSoft->AIRealPointSoften( &firstPoint, &softPoint);

        frameMatrix = textFrame.GetMatrix();

        glyphMatrix = glyphRun.GetMatrix();

        sMath->AIRealMatrixXformPoint( &frameMatrix, &firstPoint, &hardPoint);

        sHardSoft->AIRealPointSoften( &hardPoint, &softPoint);

        sMath->AIRealMatrixConcat( (AIRealMatrix*) &glyphMatrix,

                  (AIRealMatrix*) &frameMatrix,

                  matrix);

        matrix->tx = softPoint.h;

        matrix->ty = softPoint.v;

        return kNoErr; 

    }

    catch (ATE::Exception e)

    {

        return e.error;

    }

}

But, this didn't come easy, and I must be allowed to blame the poor documentation on this issue...

Agnar

1 reply

February 24, 2012

Like I said in the other thread.... it sounds like you need to convert between hard and soft coordinates.

arenolAuthorCorrect answer
Inspiring
March 12, 2012

Well, I worked it out eventually.

The ITextFrame::GetMatrix() method usually  returns an identity matrix, unless I have moved or transformed the text frame object on the artboard.  For example, if I have duplicated a text frame object by draging the object while pressing the alt-key, this matrix will hold the relative transformation compared to the object it was spawned from. Since this is a relative transformation, it's neither in hard nor soft coordinates, so it makes no sense to harden or soften it (actually, you musn't do that).

Next, the IGlyphRun::GetMatrix() method will  usually return the identity matrix, but will contain a rotation for example if the object is a text along a path.

Finally, the IGlyphRun::GetOrigins() method will return hard coordinates for each glyph position, but without the transformation from the frame matrix.  This method is oblivious to the GetCoordinateSystem / SetCoordinateSystem functions of the HardSoft suite, and returns hard coordinates regardlessly.

Thus, in order to get the actual art board coordinates of a glyph, the following code will do the trick:

    IArrayRealPoint pointArray = glyphRun.GetOrigins();

    AIRealPoint firstPoint = pointArray.Item(0);

    AIRealMatrix frameMatrix = textFrame.GetMatrix();

    sMath->AIRealMatrixXformPoint( &frameMatrix, &firstPoint, &hardPoint);

    sHardSoft->AIRealPointSoften( &hardPoint, &glyphPoint);

In order to get the absolute position matrix of the first glyph of a text frame art, the following function seem to work:

AIErr

GetFirstTextMatrix(  AIArtHandle textArt, AIRealMatrix *matrix)

{

    ASRealMatrix frameMatrix, glyphMatrix;

    ASRealPoint firstPoint, softPoint, hardPoint;

    try

    {

        TextFrameRef ateTextRef;

        sAITextFrame->GetATETextFrame( textArt, &ateTextRef);

        ITextFrame textFrame( ateTextRef);

        ITextLinesIterator lnItr = textFrame.GetTextLinesIterator();

        ITextLine txtLine = lnItr.Item();   

        IGlyphRunsIterator grItr = txtLine.GetGlyphRunsIterator();

        IGlyphRun glyphRun = grItr.Item();

        IArrayRealPoint pointArray = glyphRun.GetOrigins();

        firstPoint = pointArray.Item(0);

        sHardSoft->AIRealPointSoften( &firstPoint, &softPoint);

        frameMatrix = textFrame.GetMatrix();

        glyphMatrix = glyphRun.GetMatrix();

        sMath->AIRealMatrixXformPoint( &frameMatrix, &firstPoint, &hardPoint);

        sHardSoft->AIRealPointSoften( &hardPoint, &softPoint);

        sMath->AIRealMatrixConcat( (AIRealMatrix*) &glyphMatrix,

                  (AIRealMatrix*) &frameMatrix,

                  matrix);

        matrix->tx = softPoint.h;

        matrix->ty = softPoint.v;

        return kNoErr; 

    }

    catch (ATE::Exception e)

    {

        return e.error;

    }

}

But, this didn't come easy, and I must be allowed to blame the poor documentation on this issue...

Agnar