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(); }
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(); }