예제 #1
0
VECTOR2D STROKE_FONT::computeTextSize( const UTF8& aText ) const
{
    VECTOR2D result = VECTOR2D( 0.0, m_glyphSize.y );

    for( UTF8::uni_iter it = aText.ubegin(), end = aText.uend(); it < end; ++it )
    {
        wxASSERT_MSG( *it != '\n',
                      wxT( "This function is intended to work with single line strings" ) );

        // If it is double tilda, then it is displayed as a single tilda
        // If it is single tilda, then it is toggling overbar, so we need to skip it
        if( *it == '~' )
        {
            if( ++it >= end )
                break;
        }

        // Index in the bounding boxes table
        int dd = *it - ' ';

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

        result.x += m_glyphSize.x * m_glyphBoundingBoxes[dd].GetEnd().x;
    }

    return result;
}
예제 #2
0
void STROKE_FONT::Draw( const UTF8& aText, const VECTOR2D& aPosition, double aRotationAngle )
{
    // Context needs to be saved before any transformations
    m_gal->Save();

    m_gal->Translate( aPosition );
    m_gal->Rotate( -aRotationAngle );

    // Single line height
    int lineHeight = getInterline();

    // The overall height of all lines of text
    double textBlockHeight = lineHeight * ( linesCount( aText ) - 1 );

    switch( m_verticalJustify )
    {
    case GR_TEXT_VJUSTIFY_CENTER:
        m_gal->Translate( VECTOR2D( 0, -textBlockHeight / 2.0 ) );
        break;

    case GR_TEXT_VJUSTIFY_BOTTOM:
        m_gal->Translate( VECTOR2D( 0, -textBlockHeight ) );
        break;

    case GR_TEXT_VJUSTIFY_TOP:
        break;

    default:
        break;
    }

    m_gal->SetIsStroke( true );
    m_gal->SetIsFill( false );

    if( m_bold )
        m_gal->SetLineWidth( m_gal->GetLineWidth() * BOLD_FACTOR );

    // Split multiline strings into separate ones and draw them line by line
    size_t  begin = 0;
    size_t  newlinePos = aText.find( '\n' );

    while( newlinePos != aText.npos )
    {
        size_t length = newlinePos - begin;

        drawSingleLineText( aText.substr( begin, length ) );
        m_gal->Translate( VECTOR2D( 0.0, lineHeight ) );

        begin = newlinePos + 1;
        newlinePos = aText.find( '\n', begin );
    }

    // Draw the last (or the only one) line
    if( !aText.empty() )
        drawSingleLineText( aText.substr( begin ) );

    m_gal->Restore();
}
예제 #3
0
int main()
{
    std::string str = "input";

    UTF8        u0 = L"wide string";
    UTF8        u1 = "initial";
    wxString    wx = wxT( "input2" );

    printf( "u0:'%s'\n", u0.c_str() );
    printf( "u1:'%s'\n", u1.c_str() );

    u1 = str;

    wxString    wx2 = u1;

    // force a std::string into a UTF8, then into a wxString, then copy construct:
    wxString    wx3 = (UTF8&) u1;

    UTF8        u2 = wx2;

    u2 += 'X';

    printf( "u2:'%s'\n", u2.c_str() );

    // key accomplishments here:
    // 1) passing a UTF8 to a function which normally takes a wxString.
    // 2) return a wxString back into a UTF8.
    UTF8    result = wxFunctionTaking_wxString( u2 );

    printf( "result:'%s'\n", result.c_str() );

    // test the unicode iterator:
    for( UTF8::uni_iter it = u2.ubegin();  it < u2.uend();  )
    {
        // test post-increment:
        printf( " _%02x_", *it++ );
    }

    printf( "\n" );

    UTF8::uni_iter it = u2.ubegin();

    UTF8::uni_iter it2 = it++;

    printf( "post_inc:'%c' should be 'i'\n", *it2 );

    it2 = ++it;

    printf( "pre_inc:'%c' should be 'p'\n", *it2 );

    printf( "u[1]:'%c' should be 'n'\n", u2[1] );

    return 0;
}
예제 #4
0
FPID::FPID( const wxString& aId ) throw( PARSE_ERROR )
{
    UTF8 id = aId;

    int offset = Parse( id );

    if( offset != -1 )
    {
        THROW_PARSE_ERROR( _( "Illegal character found in FPID string" ),
                           aId,
                           id.c_str(),
                           0,
                           offset );
    }
}
예제 #5
0
int FPID::Parse( const UTF8& aId )
{
    clear();

    size_t      cnt = aId.length() + 1;
    char        tmp[cnt];  // C string for speed

    std::strcpy( tmp, aId.c_str() );

    const char* rev = EndsWithRev( tmp, tmp+aId.length(), '/' );
    size_t      revNdx;
    size_t      partNdx;
    int         offset;

    //=====<revision>=========================================
    if( rev )
    {
        revNdx = rev - aId.c_str();

        // no need to check revision, EndsWithRev did that.
        revision = aId.substr( revNdx );
        --revNdx;  // back up to omit the '/' which precedes the rev
    }
    else
    {
        revNdx = aId.size();
    }

    //=====<nickname>==========================================
    if( ( partNdx = aId.find( ':' ) ) != aId.npos )
    {
        offset = SetLibNickname( aId.substr( 0, partNdx ) );

        if( offset > -1 )
        {
            return offset;
        }

        ++partNdx;  // skip ':'
    }
    else
    {
        partNdx = 0;
    }

    //=====<footprint name>====================================
    if( partNdx >= revNdx )
        return partNdx;

    SetFootprintName( aId.substr( partNdx, revNdx ) );

    return -1;
}
예제 #6
0
int FPID::SetFootprintName( const UTF8& aFootprintName )
{
    int separation = int( aFootprintName.find_first_of( "/" ) );

    if( separation != -1 )
    {
        footprint = aFootprintName.substr( 0, separation-1 );
        return separation;
    }
    else
    {
        footprint = aFootprintName;
    }

    return -1;
}
int LIB_ID::SetLibItemName( const UTF8& aLibItemName, bool aTestForRev )
{
    int separation = int( aLibItemName.find_first_of( "/" ) );

    if( aTestForRev && separation != -1 )
    {
        item_name = aLibItemName.substr( 0, separation-1 );
        return separation;
    }
    else
    {
        item_name = aLibItemName;
    }

    return -1;
}
예제 #8
0
int FPID::SetFootprintName( const UTF8& aFootprintName )
{
    int separation = int( aFootprintName.find_first_of( "/" ) );

    if( separation != -1 )
    {
        nickname = aFootprintName.substr( separation+1 );
        return separation + (int) nickname.size() + 1;
    }
    else
    {
        footprint = aFootprintName;
    }

    return -1;
}
예제 #9
0
static void generateJSONString(Error& error, const HOutputStream& out, const UTF8& s)
{
	UTF16Buffer sb(2 + s.length() + 1);

	sb << '"';

	if (error)
		return;

	for (const Chr8* p = s.ptr(); (*p) != '\0'; p++)
	{
		Chr8 c = *p;

		switch (c)
		{
		case '\"' : sb << '\\' << '\"'; break;
		case '\\' : sb << '\\' << '\\'; break;
		case '/' :  sb << '\\' << '/'; break;
		case '\b' : sb << '\\' << 'b'; break;
		case '\f' : sb << '\\' << 'f'; break;
		case '\n' : sb << '\\' << 'n'; break;
		case '\r' : sb << '\\' << 'r'; break;
		case '\t' : sb << '\\' << 't'; break;
		default:
			if (c >= 0x20)
			{
				sb << c;
			}
			else
			{
				sb << UTF8("\\u00") << UTF8::format("%.2X",UInt32(c));
			}
		break;
		}
	}

	sb << '"';

	out->twrite(error, UTF8(sb));
};
예제 #10
0
int FPID::Parse( const UTF8& aId )
{
    clear();

    const char* buffer = aId.c_str();
    const char* rev = EndsWithRev( buffer, buffer+aId.length(), '/' );
    size_t      revNdx;
    size_t      partNdx;
    int         offset;

    //=====<revision>=========================================
    // in a FPID like discret:R3/rev4
    if( rev )
    {
        revNdx = rev - buffer;

        // no need to check revision, EndsWithRev did that.
        revision = aId.substr( revNdx );
        --revNdx;  // back up to omit the '/' which precedes the rev
    }
    else
    {
        revNdx = aId.size();
    }

    //=====<nickname>==========================================
    if( ( partNdx = aId.find( ':' ) ) != aId.npos )
    {
        offset = SetLibNickname( aId.substr( 0, partNdx ) );

        if( offset > -1 )
        {
            return offset;
        }

        ++partNdx;  // skip ':'
    }
    else
    {
        partNdx = 0;
    }

    //=====<footprint name>====================================
    if( partNdx >= revNdx )
        return partNdx;     // Error: no footprint name.

    // Be sure the footprint name is valid.
    // Some chars can be found in board file (in old board files
    // or converted files from an other EDA tool
    std::string fpname = aId.substr( partNdx, revNdx-partNdx );
    ReplaceIllegalFileNameChars( &fpname, '_' );
    SetFootprintName( UTF8( fpname ) );

    return -1;
}
예제 #11
0
int main( int argc, char** argv )
{
    UTF8        bozo = "ü";

    callee( bozo );

    wxString s = bozo;

    wxString b = bozo;

    if( s.IsEmpty() )
    {
        printf( "string is empty\n" );
    }

    if(  s != bozo.wx_str() )
    {
        printf( "string miscompare\n" );
    }

    return 0;
}
UTF8 LIB_TABLE::FormatOptions( const PROPERTIES* aProperties )
{
    UTF8 ret;

    if( aProperties )
    {
        for( PROPERTIES::const_iterator it = aProperties->begin(); it != aProperties->end(); ++it )
        {
            const std::string& name = it->first;

            const UTF8& value = it->second;

            if( ret.size() )
                ret += OPT_SEP;

            ret += name;

            // the separation between name and value is '='
            if( value.size() )
            {
                ret += '=';

                for( std::string::const_iterator si = value.begin();  si != value.end();  ++si )
                {
                    // escape any separator in the value.
                    if( *si == OPT_SEP )
                        ret += '\\';

                    ret += *si;
                }
            }
        }
    }

    return ret;
}
예제 #13
0
UTF8 FPID::Format( const UTF8& aLogicalLib, const UTF8& aFootprintName,
                          const UTF8& aRevision )
    throw( PARSE_ERROR )
{
    UTF8    ret;
    int     offset;

    if( aLogicalLib.size() )
    {
        offset = okLogical( aLogicalLib );

        if( offset != -1 )
        {
            THROW_PARSE_ERROR( _( "Illegal character found in logical library name" ),
                               wxString::FromUTF8( aLogicalLib.c_str() ),
                               aLogicalLib.c_str(),
                               0,
                               offset );
        }

        ret += aLogicalLib;
        ret += ':';
    }

    if( aRevision.size() )
    {
        offset = okRevision( aRevision );

        if( offset != -1 )
        {
            THROW_PARSE_ERROR( _( "Illegal character found in revision" ),
                               wxString::FromUTF8( aRevision.c_str() ),
                               aRevision.c_str(),
                               0,
                               offset );
        }

        ret += '/';
        ret += aRevision;
    }

    return ret;
}
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();
}
예제 #15
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();
}
예제 #16
0
int wmain(int argc, Chr16** argv)
{
	Lock::setupGlobalLock();

	Error error;
	LogStdout log;
		
	class Fatal {};

	try
	{
		loginfo("Tomazos Resource Compiler 1.0 (c) Andrew Tomazos 2009");

		if (argc != 3)
		{
			error.what(L"Usage: ResourceCompiler <ResourceDir> <Out.cpp>");
			throw Fatal();
		}

		UTF16 sSourceDirPath = argv[1];
		UTF16 sOutPath = argv[2];

		Path sourceDir(error, sSourceDirPath);
		
		if (error)
			throw Fatal();

		UTF16 sFullSourceDirPath = UTF16(sourceDir);
		if (!sFullSourceDirPath.endsWith(L"\\"))
			sFullSourceDirPath = sFullSourceDirPath + L"\\";

		UTF16List fps;
		sourceDir.walk(ResourceCompilerWalker(fps));

		loginfo("Found %d files", fps.size());

		TreeMap<UTF16, Blob> data;

		{
			UTF16List::Iterator it(fps);
			UTF16 sFullFilePath;

			while (it(sFullFilePath))
			{
				if (!sFullFilePath.startsWith(sFullSourceDirPath))
				{
					Check();
					throw Fatal();
				}

				UTF16 sRelFilePath = sFullFilePath.suffix(sFullFilePath.length() - sFullSourceDirPath.length());

				Path file(error, sFullFilePath);
				
				if (error)
					throw Fatal();

				HInputStream fis;
				
				file.readFile(error, fis);

				if (error)
					throw Fatal();

				
				Blob sFileContent = fis->slurp(error);

				if (error)
					throw Fatal();

				loginfo("Found %s (%d bytes)", sRelFilePath.ptr(), sFileContent.length());

				data.add(sRelFilePath, sFileContent);
			}
		}

		Path outPath(error, sOutPath);

		if (error)
			throw Fatal();

		HOutputStream hOut;
		outPath.overwriteFile(error, hOut);

		if (error)
			throw Fatal();

		#define ResLine(x) { hOut->twrite(error, UTF8(x)); if (error) throw Fatal(); hOut->twrite(error, UTF8("\r\n")); if (error) throw Fatal(); }
		#define ResLineF(...) { ResLine(UTF8::format(__VA_ARGS__)); }

		ResLine("#include \"Runtime.h\"");
		ResLine("");
		ResLine("void ResourceManager::setup()");
		ResLine("{");

		{
			TreeMap<UTF16, Blob>::Iterator it(data);
			UTF16 sPath;
			Blob bData;
			int iCount = 0;

			int iNumResources = data.size();

			while (it(sPath, bData))
			{
				iCount++;
				UTF8 sId = UTF8::format("s_res_data_%d", iCount);
				
				ResLineF("    static UInt8 %s[] = { ", sId.ptr());
				for (int i = 0; i < bData.length(); i++)
				{
					if (i % 16 == 0)
					{
						hOut->twrite(error, UTF8("        "));
						if (error)
							throw Fatal();
					}

					hOut->twrite(error, UTF8::format("0x%.2X", UInt32(bData.idx<UInt8>(i))));

					if (error) throw Fatal();

					if (i != bData.length() - 1)
					{
						hOut->twrite(error, UTF8(", "));

						if (error)
							throw Fatal();
					}

					if (i % 16 == 15 || i == bData.length() - 1)
						ResLine("");
				}
				ResLineF("    };");
				ResLine("");
				ResLineF("    ResourceManager::instance()->set(%s, %s, %d);", stringToCStringLiteral(sPath).ptr(), sId.ptr(), bData.length());
				if (iCount != iNumResources)
					ResLine("");
			}
		}

		ResLine("}");

		#undef ResLine

		return 0;
	}
	catch (Fatal&)
	{
		if (error)
			logerr("%s", UTF16(error).ptr());
		
		return 1;
	}
}
void STROKE_FONT::Draw( const UTF8& aText, const VECTOR2D& aPosition, double aRotationAngle )
{
    if( aText.empty() )
        return;

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

    m_gal->Translate( aPosition );
    m_gal->Rotate( -aRotationAngle );

    // Single line height
    int lineHeight = getInterline( );
    int lineCount = linesCount( aText );
    const VECTOR2D& glyphSize = m_gal->GetGlyphSize();

    // align the 1st line of text
    switch( m_gal->GetVerticalJustify() )
    {
    case GR_TEXT_VJUSTIFY_TOP:
        m_gal->Translate( VECTOR2D( 0, glyphSize.y ) );
        break;

    case GR_TEXT_VJUSTIFY_CENTER:
        m_gal->Translate( VECTOR2D( 0, glyphSize.y / 2.0 ) );
        break;

    case GR_TEXT_VJUSTIFY_BOTTOM:
        break;

    default:
        break;
    }

    if( lineCount > 1 )
    {
        switch( m_gal->GetVerticalJustify() )
        {
        case GR_TEXT_VJUSTIFY_TOP:
            break;

        case GR_TEXT_VJUSTIFY_CENTER:
            m_gal->Translate( VECTOR2D(0, -( lineCount - 1 ) * lineHeight / 2) );
            break;

        case GR_TEXT_VJUSTIFY_BOTTOM:
            m_gal->Translate( VECTOR2D(0, -( lineCount - 1 ) * lineHeight ) );
            break;
        }
    }

    m_gal->SetIsStroke( true );
    //m_gal->SetIsFill( false );

    if( m_gal->IsFontBold() )
        m_gal->SetLineWidth( m_gal->GetLineWidth() * BOLD_FACTOR );

    // Split multiline strings into separate ones and draw them line by line
    size_t  begin = 0;
    size_t  newlinePos = aText.find( '\n' );

    while( newlinePos != aText.npos )
    {
        size_t length = newlinePos - begin;

        drawSingleLineText( aText.substr( begin, length ) );
        m_gal->Translate( VECTOR2D( 0.0, lineHeight ) );

        begin = newlinePos + 1;
        newlinePos = aText.find( '\n', begin );
    }

    // Draw the last (or the only one) line
    if( !aText.empty() )
        drawSingleLineText( aText.substr( begin ) );

    m_gal->Restore();
}
예제 #18
0
void callee( const wxString& aString )
{
    UTF8 arg = aString;

    printf( "%s: '%s'\n", __func__, arg.c_str() );
}
VECTOR2D STROKE_FONT::ComputeStringBoundaryLimits( const UTF8& aText, VECTOR2D aGlyphSize,
                                        double aGlyphThickness,
                                        double* aTopLimit, double* aBottomLimit ) const
{
    VECTOR2D string_bbox;
    double ymax = 0.0;
    double ymin = 0.0;

    for( UTF8::uni_iter it = aText.ubegin(), end = aText.uend(); it < end; ++it )
    {
        wxASSERT_MSG( *it != '\n',
                      wxT( "This function is intended to work with single line strings" ) );

        // If it is double tilda, then it is displayed as a single tilda
        // If it is single tilda, then it is toggling overbar, so we need to skip it
        if( *it == '~' )
        {
            if( ++it >= end )
                break;
        }

        // Index in the bounding boxes table
        int dd = *it - ' ';

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

        const BOX2D& box = m_glyphBoundingBoxes[dd];

        string_bbox.x += box.GetEnd().x;

        // Calculate Y min and Y max
        if( aTopLimit )
        {
            ymax = std::max( ymax, box.GetY() );
            ymax = std::max( ymax, box.GetEnd().y );
        }

        if( aBottomLimit )
        {
            ymin = std::min( ymin, box.GetY() );
            ymin = std::min( ymin, box.GetEnd().y );
        }
    }

    string_bbox.x *= aGlyphSize.x;
    string_bbox.x += aGlyphThickness;
    string_bbox.y = aGlyphSize.y + aGlyphThickness;

    // For italic correction, take in account italic tilt
    if( m_gal->IsFontItalic() )
        string_bbox.x += string_bbox.y * STROKE_FONT::ITALIC_TILT;

    if( aTopLimit )
        *aTopLimit = ymax * aGlyphSize.y;

    if( aBottomLimit )
        *aBottomLimit = ymin * aGlyphSize.y;

    return string_bbox;
}