NS_IMETHODIMP
nsThebesRenderingContext::DrawString(const PRUnichar *aString, PRUint32 aLength,
                                   nscoord aX, nscoord aY,
                                   PRInt32 aFontID,
                                   const nscoord* aSpacing)
{
    PRUint32 maxChunkLength = GetMaxChunkLength(this);
    if (aLength <= maxChunkLength) {
        return DrawStringInternal(aString, aLength, aX, aY, aFontID, aSpacing);
    }

    PRBool isRTL = PR_FALSE;
    GetRightToLeftText(&isRTL);

    if (isRTL) {
        nscoord totalWidth = 0;
        if (aSpacing) {
            for (PRUint32 i = 0; i < aLength; ++i) {
                totalWidth += aSpacing[i];
            }
        } else {
            nsresult rv = GetWidth(aString, aLength, totalWidth);
            if (NS_FAILED(rv))
                return rv;
        }
        aX += totalWidth;
    }

    while (aLength > 0) {
        PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength);
        nscoord width = 0;
        if (aSpacing) {
            for (PRInt32 i = 0; i < len; ++i) {
                width += aSpacing[i];
            }
        } else {
            nsresult rv = GetWidthInternal(aString, len, width);
            if (NS_FAILED(rv))
                return rv;
        }

        if (isRTL) {
            aX -= width;
        }
        nsresult rv = DrawStringInternal(aString, len, aX, aY, aFontID, aSpacing);
        if (NS_FAILED(rv))
            return rv;
        aLength -= len;
        if (!isRTL) {
            aX += width;
        }
        aString += len;
        if (aSpacing) {
            aSpacing += len;
        }
    }
    return NS_OK;
}
NS_IMETHODIMP
nsThebesRenderingContext::DrawString(const char *aString, PRUint32 aLength,
                                   nscoord aX, nscoord aY,
                                   const nscoord* aSpacing)
{
    PRUint32 maxChunkLength = GetMaxChunkLength(this);
    while (aLength > 0) {
        PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength);
        nsresult rv = DrawStringInternal(aString, len, aX, aY);
        if (NS_FAILED(rv))
            return rv;
        aLength -= len;

        if (aLength > 0) {
            nscoord width;
            rv = GetWidthInternal(aString, len, width);
            if (NS_FAILED(rv))
                return rv;
            aX += width;
            aString += len;
        }
    }
    return NS_OK;
}
예제 #3
0
void FCanvasTextItem::Draw( class FCanvas* InCanvas )
{	
	SCOPE_CYCLE_COUNTER(STAT_Canvas_TextItemTime);

	if(Font == NULL || Text.IsEmpty() )
	{
		return;
	}

	XScale = Scale.X;
	YScale = Scale.Y;

	bool bHasShadow = ShadowOffset.Size() != 0.0f;
	if( ( FontRenderInfo.bEnableShadow == true ) && ( bHasShadow == false ) )
	{
		EnableShadow( FLinearColor::Black );
		bHasShadow = true;
	}
	if (Font->ImportOptions.bUseDistanceFieldAlpha)
	{
		// convert blend mode to distance field type
		switch(BlendMode)
		{
		case SE_BLEND_Translucent:
			BlendMode = (FontRenderInfo.bEnableShadow) ? SE_BLEND_TranslucentDistanceFieldShadowed : SE_BLEND_TranslucentDistanceField;
			break;
		case SE_BLEND_Masked:
			BlendMode = (FontRenderInfo.bEnableShadow) ? SE_BLEND_MaskedDistanceFieldShadowed : SE_BLEND_MaskedDistanceField;
			break;
		}
		// Disable the show if the blend mode is not suitable
		if (BlendMode != SE_BLEND_TranslucentDistanceFieldShadowed && BlendMode != SE_BLEND_MaskedDistanceFieldShadowed)
		{
			bHasShadow = false;
		}
	}	

	CharIncrement = ( (float)Font->Kerning + HorizSpacingAdjust ) * Scale.X;
	DrawnSize.Y = Font->GetMaxCharHeight() * Scale.Y;

	FVector2D DrawPos( Position.X , Position.Y );

	// If we are centering the string or we want to fix stereoscopic rending issues we need to measure the string
	if( ( bCentreX || bCentreY ) || ( !bDontCorrectStereoscopic ) )
	{
		FTextSizingParameters Parameters( Font, Scale.X ,Scale.Y );
		UCanvas::CanvasStringSize( Parameters, *Text.ToString() );
				
		// Calculate the offset if we are centering
		if( bCentreX || bCentreY )
		{		
			// Note we drop the fraction after the length divide or we can end up with coords on 1/2 pixel boundaries
			if( bCentreX )
			{
				DrawPos.X = DrawPos.X - (int)( Parameters.DrawXL / 2 );
			}
			if( bCentreY )
			{
				DrawPos.Y = DrawPos.Y - (int)( Parameters.DrawYL / 2 );
			}
		}

		// Check if we want to correct the stereo3d issues - if we do, render the correction now
		bool CorrectStereo = !bDontCorrectStereoscopic  && GEngine->IsStereoscopic3D();
		if( CorrectStereo )
		{
			FVector2D StereoOutlineBoxSize( 2.0f, 2.0f );
			TileItem.MaterialRenderProxy = GEngine->RemoveSurfaceMaterial->GetRenderProxy( false );
			TileItem.Position = DrawPos - StereoOutlineBoxSize;
			FVector2D CorrectionSize = FVector2D( Parameters.DrawXL, Parameters.DrawYL ) + StereoOutlineBoxSize + StereoOutlineBoxSize;
			TileItem.Size=  CorrectionSize;
			TileItem.bFreezeTime = true;
			TileItem.Draw( InCanvas );
		}		
	}
	
	FLinearColor DrawColor;
	BatchedElements = NULL;
	TextLen = Text.ToString().Len();
	if( bOutlined )
	{
		DrawColor = OutlineColor;
		DrawColor.A *= InCanvas->AlphaModulate;
		DrawStringInternal( InCanvas, DrawPos + FVector2D( -1.0f, -1.0f ), DrawColor );
		DrawStringInternal( InCanvas, DrawPos + FVector2D( -1.0f, 1.0f ), DrawColor );
		DrawStringInternal( InCanvas, DrawPos + FVector2D( 1.0f, 1.0f ), DrawColor );
		DrawStringInternal( InCanvas, DrawPos + FVector2D( 1.0f, -1.0f ), DrawColor );
	}
	// If we have a shadow - draw it now
	if( bHasShadow )
	{
		DrawColor = ShadowColor;
		// Copy the Alpha from the shadow otherwise if we fade the text the shadow wont fade - which is almost certainly not what we will want.
		DrawColor.A = Color.A;
		DrawColor.A *= InCanvas->AlphaModulate;
		DrawStringInternal( InCanvas, DrawPos + ShadowOffset, DrawColor );
	}
	DrawColor = Color;
	DrawColor.A *= InCanvas->AlphaModulate;	
	DrawStringInternal( InCanvas, DrawPos, DrawColor );
	
	return;
}