void STROKE_FONT::drawSingleLineText( const UTF8& aText )
{
    // By default the overbar is turned off
    bool overbar = false;

    double      xOffset;
    VECTOR2D    glyphSize( m_gal->GetGlyphSize() );
    double      overbar_italic_comp = computeOverbarVerticalPosition() * ITALIC_TILT;

    if( m_gal->IsTextMirrored() )
        overbar_italic_comp = -overbar_italic_comp;

    // Compute the text size
    VECTOR2D textSize = computeTextLineSize( aText );
    double half_thickness = m_gal->GetLineWidth()/2;

    // Context needs to be saved before any transformations
    m_gal->Save();

    // First adjust: the text X position is corrected by half_thickness
    // because when the text with thickness is draw, its full size is textSize,
    // but the position of lines is half_thickness to textSize - half_thickness
    // so we must translate the coordinates by half_thickness on the X axis
    // to place the text inside the 0 to textSize X area.
    m_gal->Translate( VECTOR2D( half_thickness, 0 ) );

    // Adjust the text position to the given horizontal justification
    switch( m_gal->GetHorizontalJustify() )
    {
    case GR_TEXT_HJUSTIFY_CENTER:
        m_gal->Translate( VECTOR2D( -textSize.x / 2.0, 0 ) );
        break;

    case GR_TEXT_HJUSTIFY_RIGHT:
        if( !m_gal->IsTextMirrored() )
            m_gal->Translate( VECTOR2D( -textSize.x, 0 ) );
        break;

    case GR_TEXT_HJUSTIFY_LEFT:
        if( m_gal->IsTextMirrored() )
            m_gal->Translate( VECTOR2D( -textSize.x, 0 ) );
        break;

    default:
        break;
    }

    if( m_gal->IsTextMirrored() )
    {
        // In case of mirrored text invert the X scale of points and their X direction
        // (m_glyphSize.x) and start drawing from the position where text normally should end
        // (textSize.x)
        xOffset = textSize.x - m_gal->GetLineWidth();
        glyphSize.x = -glyphSize.x;
    }
    else
    {
        xOffset = 0.0;
    }

    // The overbar is indented inward at the beginning of an italicized section, but
    // must not be indented on subsequent letters to ensure that the bar segments
    // overlap.
    bool last_had_overbar = false;

    for( UTF8::uni_iter chIt = aText.ubegin(), end = aText.uend(); chIt < end; ++chIt )
    {
        // Toggle overbar
        if( *chIt == '~' )
        {
            if( ++chIt >= end )
                break;

            if( *chIt != '~' )      // It was a single tilda, it toggles overbar
                overbar = !overbar;

            // If it is a double tilda, just process the second one
        }

        int dd = *chIt - ' ';

        if( dd >= (int) m_glyphBoundingBoxes.size() || dd < 0 )
            dd = '?' - ' ';

        GLYPH& glyph = m_glyphs[dd];
        BOX2D& bbox  = m_glyphBoundingBoxes[dd];

        if( overbar )
        {
            double overbar_start_x = xOffset;
            double overbar_start_y = - computeOverbarVerticalPosition();
            double overbar_end_x = xOffset + glyphSize.x * bbox.GetEnd().x;
            double overbar_end_y = overbar_start_y;

            if( !last_had_overbar )
            {
                overbar_start_x += overbar_italic_comp;
                last_had_overbar = true;
            }

            VECTOR2D startOverbar( overbar_start_x, overbar_start_y );
            VECTOR2D endOverbar( overbar_end_x, overbar_end_y );

            m_gal->DrawLine( startOverbar, endOverbar );
        }
        else
        {
            last_had_overbar = false;
        }

        for( GLYPH::iterator pointListIt = glyph.begin(); pointListIt != glyph.end();
             ++pointListIt )
        {
            std::deque<VECTOR2D> pointListScaled;

            for( std::deque<VECTOR2D>::iterator pointIt = pointListIt->begin();
                 pointIt != pointListIt->end(); ++pointIt )
            {
                VECTOR2D pointPos( pointIt->x * glyphSize.x + xOffset, pointIt->y * glyphSize.y );

                if( m_gal->IsFontItalic() )
                {
                    // FIXME should be done other way - referring to the lowest Y value of point
                    // because now italic fonts are translated a bit
                    if( m_gal->IsTextMirrored() )
                        pointPos.x += pointPos.y * STROKE_FONT::ITALIC_TILT;
                    else
                        pointPos.x -= pointPos.y * STROKE_FONT::ITALIC_TILT;
                }

                pointListScaled.push_back( pointPos );
            }

            m_gal->DrawPolyline( pointListScaled );
        }

        xOffset += glyphSize.x * bbox.GetEnd().x;
    }

    m_gal->Restore();
}
Exemplo n.º 2
0
void STROKE_FONT::drawSingleLineText( const UTF8& aText )
{
    // By default the overbar is turned off
    m_overbar = false;

    double      xOffset;
    VECTOR2D    glyphSize( m_glyphSize );

    // Compute the text size
    VECTOR2D textSize = computeTextSize( aText );

    m_gal->Save();

    // Adjust the text position to the given alignment
    switch( m_horizontalJustify )
    {
    case GR_TEXT_HJUSTIFY_CENTER:
        m_gal->Translate( VECTOR2D( -textSize.x / 2.0, 0 ) );
        break;

    case GR_TEXT_HJUSTIFY_RIGHT:
        if( !m_mirrored )
            m_gal->Translate( VECTOR2D( -textSize.x, 0 ) );
        break;

    case GR_TEXT_HJUSTIFY_LEFT:
        if( m_mirrored )
            m_gal->Translate( VECTOR2D( -textSize.x, 0 ) );
        break;

    default:
        break;
    }

    if( m_mirrored )
    {
        // In case of mirrored text invert the X scale of points and their X direction
        // (m_glyphSize.x) and start drawing from the position where text normally should end
        // (textSize.x)
        xOffset = textSize.x;
        glyphSize.x = -m_glyphSize.x;
    }
    else
    {
        xOffset = 0.0;
    }

    for( UTF8::uni_iter chIt = aText.ubegin(), end = aText.uend(); chIt < end; ++chIt )
    {
        // Toggle overbar
        if( *chIt == '~' )
        {
            if( ++chIt >= end )
                break;

            if( *chIt != '~' )      // It was a single tilda, it toggles overbar
                m_overbar = !m_overbar;

            // If it is a double tilda, just process the second one
        }

        int dd = *chIt - ' ';

        if( dd >= (int) m_glyphBoundingBoxes.size() || dd < 0 )
            dd = '?' - ' ';

        GLYPH& glyph = m_glyphs[dd];
        BOX2D& bbox  = m_glyphBoundingBoxes[dd];

        if( m_overbar )
        {
            VECTOR2D startOverbar( xOffset, -getInterline() * OVERBAR_HEIGHT );
            VECTOR2D endOverbar( xOffset + glyphSize.x * bbox.GetEnd().x,
                                 -getInterline() * OVERBAR_HEIGHT );

            m_gal->DrawLine( startOverbar, endOverbar );
        }

        for( GLYPH::iterator pointListIt = glyph.begin(); pointListIt != glyph.end();
                ++pointListIt )
        {
            std::deque<VECTOR2D> pointListScaled;

            for( std::deque<VECTOR2D>::iterator pointIt = pointListIt->begin();
                    pointIt != pointListIt->end(); ++pointIt )
            {
                VECTOR2D pointPos( pointIt->x * glyphSize.x + xOffset, pointIt->y * glyphSize.y );

                if( m_italic )
                {
                    // FIXME should be done other way - referring to the lowest Y value of point
                    // because now italic fonts are translated a bit
                    if( m_mirrored )
                        pointPos.x += pointPos.y * 0.1;
                    else
                        pointPos.x -= pointPos.y * 0.1;
                }

                pointListScaled.push_back( pointPos );
            }

            m_gal->DrawPolyline( pointListScaled );
        }

        xOffset += glyphSize.x * bbox.GetEnd().x;
    }

    m_gal->Restore();
}