We can manually ignore colour codes for the default.png text drawing backend, allocates less memory and optimises performance.

This commit is contained in:
UnknownShadow200 2016-04-11 14:42:59 +10:00
parent 3de395cb9f
commit c797909e76
4 changed files with 87 additions and 89 deletions

View File

@ -42,9 +42,6 @@ namespace ClassicalSharp {
FastBitmap bitmapWrapper = new FastBitmap(); FastBitmap bitmapWrapper = new FastBitmap();
public override void DrawBitmappedText( ref DrawTextArgs args, int x, int y ) { public override void DrawBitmappedText( ref DrawTextArgs args, int x, int y ) {
if( !args.SkipPartsCheck )
GetTextParts( args.Text );
using( bitmapWrapper ) { using( bitmapWrapper ) {
bitmapWrapper.SetData( curBmp, true, false ); bitmapWrapper.SetData( curBmp, true, false );
DrawBitmappedTextImpl( bitmapWrapper, ref args, x, y ); DrawBitmappedTextImpl( bitmapWrapper, ref args, x, y );
@ -70,26 +67,7 @@ namespace ClassicalSharp {
} }
public override Size MeasureBitmappedSize( ref DrawTextArgs args ) { public override Size MeasureBitmappedSize( ref DrawTextArgs args ) {
GetTextParts( args.Text ); return MeasureBitmappedSizeImpl( ref args );
if( parts.Count == 0 )
return Size.Empty;
float point = args.Font.Size;
Size total = new Size( 0, PtToPx( point, boxSize ) );
for( int i = 0; i < parts.Count; i++ ) {
foreach( char c in parts[i].Text ) {
int coords = ConvertToCP437( c );
total.X += PtToPx( point, widths[coords] + 1 );
}
}
if( args.Font.Style == FontStyle.Italic )
total.X += Utils.CeilDiv( total.Y, italicSize );
if( args.UseShadow ) {
int offset = ShadowOffset( args.Font.Size );
total.X += offset; total.Y += offset;
}
return total;
} }
void DisposeText() { void DisposeText() {

View File

@ -70,9 +70,6 @@ namespace ClassicalSharp {
FastBitmap bitmapWrapper = new FastBitmap(); FastBitmap bitmapWrapper = new FastBitmap();
public override void DrawBitmappedText( ref DrawTextArgs args, int x, int y ) { public override void DrawBitmappedText( ref DrawTextArgs args, int x, int y ) {
if( !args.SkipPartsCheck )
GetTextParts( args.Text );
using( bitmapWrapper ) { using( bitmapWrapper ) {
bitmapWrapper.SetData( curBmp, true, false ); bitmapWrapper.SetData( curBmp, true, false );
DrawBitmapTextImpl( bitmapWrapper, ref args, x, y ); DrawBitmapTextImpl( bitmapWrapper, ref args, x, y );
@ -97,25 +94,7 @@ namespace ClassicalSharp {
} }
public override Size MeasureBitmappedSize( ref DrawTextArgs args ) { public override Size MeasureBitmappedSize( ref DrawTextArgs args ) {
GetTextParts( args.Text ); return MeasureBitmappedSizeImpl( ref args );
if( parts.Count == 0 ) return Size.Empty;
float point = args.Font.Size;
Size total = new Size( 0, PtToPx( point, boxSize ) );
for( int i = 0; i < parts.Count; i++ ) {
foreach( char c in parts[i].Text ) {
int coords = ConvertToCP437( c );
total.Width += PtToPx( point, widths[coords] + 1 );
}
}
if( args.Font.Style == FontStyle.Italic )
total.Width += Utils.CeilDiv( total.Height, italicSize );
if( args.UseShadow ) {
int offset = ShadowOffset( args.Font.Size );
total.Width += offset; total.Height += offset;
}
return total;
} }
void DisposeText() { void DisposeText() {

View File

@ -35,52 +35,51 @@ namespace ClassicalSharp {
void MakeTile( int i, int tileX, int tileY ) { void MakeTile( int i, int tileX, int tileY ) {
// find first column (from right) where there is a solid pixel // find first column (from right) where there is a solid pixel
for( int x = boxSize - 1; x >= 0; x-- ) { for( int x = boxSize - 1; x >= 0; x-- )
for( int y = 0; y < boxSize; y++ ) { for( int y = 0; y < boxSize; y++ )
int pixel = fontPixels.GetRowPtr( tileY + y )[tileX + x]; {
byte a = (byte)(pixel >> 24); int pixel = fontPixels.GetRowPtr( tileY + y )[tileX + x];
if( a >= 127 ) { // found a solid pixel byte a = (byte)(pixel >> 24);
widths[i] = x + 1; if( a >= 127 ) { // found a solid pixel
return; widths[i] = x + 1;
} return;
} }
} }
widths[i] = 0; widths[i] = 0;
} }
protected void DrawBitmapTextImpl( FastBitmap fastBmp, ref DrawTextArgs args, int x, int y ) { protected void DrawBitmapTextImpl( FastBitmap dst, ref DrawTextArgs args, int x, int y ) {
bool underline = args.Font.Style == FontStyle.Underline; bool underline = args.Font.Style == FontStyle.Underline;
if( args.UseShadow ) { if( args.UseShadow ) {
int offset = ShadowOffset( args.Font.Size ); int offset = ShadowOffset( args.Font.Size );
int shadowX = x + offset, shadowY = y + offset; int shadowX = x + offset, shadowY = y + offset;
for( int i = 0; i < parts.Count; i++ ) { DrawPart( dst, ref args, ref shadowX, shadowY, true );
TextPart part = parts[i];
part.TextColour = FastColour.Black;
int orignX = shadowX;
DrawPart( fastBmp, args.Font, ref shadowX, shadowY, part );
if( underline )
DrawUnderline( fastBmp, part.TextColour, orignX, shadowX, 0, ref args );
}
}
for( int i = 0; i < parts.Count; i++ ) {
TextPart part = parts[i];
int orignX = x;
DrawPart( fastBmp, args.Font, ref x, y, part );
if( underline ) if( underline )
DrawUnderline( fastBmp, part.TextColour, orignX, x, -2, ref args ); DrawUnderline( dst, x + offset, 0, ref args, true );
} }
int orignX = x;
DrawPart( dst, ref args, ref x, y, false );
if( underline )
DrawUnderline( dst, orignX, -2, ref args, false );
} }
void DrawPart( FastBitmap dst, Font font, ref int x, int y, TextPart part ) { void DrawPart( FastBitmap dst, ref DrawTextArgs args, ref int x, int y, bool shadowCol ) {
string text = part.Text; FastColour textCol = FastColour.White;
FastColour textCol = part.TextColour; float point = args.Font.Size;
float point = font.Size; int xMul = args.Font.Style == FontStyle.Italic ? 1 : 0;
int xMul = font.Style == FontStyle.Italic ? 1 : 0; string text = args.Text;
foreach( char c in text ) { for( int i = 0; i < text.Length; i++ ) {
char c = text[i];
bool code = c == '&' && i < text.Length - 1;
if( code && ValidColour( text[i + 1] ) ) {
textCol = Colours[text[i + 1]];
i++; continue; // Skip over the colour code.
}
if( shadowCol ) textCol = FastColour.Black;
int coords = ConvertToCP437( c ); int coords = ConvertToCP437( c );
int srcX = (coords & 0x0F) * boxSize; int srcX = (coords & 0x0F) * boxSize;
int srcY = (coords >> 4) * boxSize; int srcY = (coords >> 4) * boxSize;
@ -94,18 +93,18 @@ namespace ClassicalSharp {
if( dstY >= dst.Height ) continue; if( dstY >= dst.Height ) continue;
int* dstRow = dst.GetRowPtr( dstY ); int* dstRow = dst.GetRowPtr( dstY );
int xOffset = xMul * ((dstHeight - 1 - yy) / italicSize); int xOffset = xMul * ((dstHeight - 1 - yy) / italicSize);
for( int xx = 0; xx < dstWidth; xx++ ) { for( int xx = 0; xx < dstWidth; xx++ ) {
int fontX = srcX + xx * srcWidth / dstWidth; int fontX = srcX + xx * srcWidth / dstWidth;
int pixel = fontRow[fontX]; int pixel = fontRow[fontX];
if( (byte)(pixel >> 24) == 0 ) continue; if( (byte)(pixel >> 24) == 0 ) continue;
int dstX = x + xx + xOffset; int dstX = x + xx + xOffset;
if( dstX >= dst.Width ) continue; if( dstX >= dst.Width ) continue;
int col = pixel & ~0xFFFFFF; int col = pixel & ~0xFFFFFF;
col |= ((pixel & 0xFF) * textCol.B / 255); col |= ((pixel & 0xFF) * textCol.B / 255);
col |= (((pixel >> 8) & 0xFF) * textCol.G / 255) << 8; col |= (((pixel >> 8) & 0xFF) * textCol.G / 255) << 8;
col |= (((pixel >> 16) & 0xFF) * textCol.R / 255) << 16; col |= (((pixel >> 16) & 0xFF) * textCol.R / 255) << 16;
dstRow[dstX] = col; dstRow[dstX] = col;
} }
} }
@ -113,21 +112,63 @@ namespace ClassicalSharp {
} }
} }
void DrawUnderline( FastBitmap fastBmp, FastColour textCol, int startX, int endX, void DrawUnderline( FastBitmap dst, int x, int yOffset, ref DrawTextArgs args, bool shadowCol ) {
int yOffset, ref DrawTextArgs args ) {
int height = PtToPx( args.Font.Size, boxSize ); int height = PtToPx( args.Font.Size, boxSize );
int offset = ShadowOffset( args.Font.Size ); int offset = ShadowOffset( args.Font.Size );
int col = textCol.ToArgb(); int col = FastColour.White.ToArgb();
if( args.UseShadow ) float point = args.Font.Size;
height += offset; string text = args.Text;
if( args.UseShadow ) height += offset;
for( int yy = height - offset; yy < height; yy++ ) { for( int yy = height - offset; yy < height; yy++ ) {
int* dstRow = fastBmp.GetRowPtr( yy + yOffset ); int* dstRow = dst.GetRowPtr( yy + yOffset );
for( int xx = startX; xx < endX; xx++ ) int startX = x;
dstRow[xx] = col;
for( int i = 0; i < text.Length; i++ ) {
char c = text[i];
bool code = c == '&' && i < text.Length - 1;
if( code && ValidColour( text[i + 1] ) ) {
col = Colours[text[i + 1]].ToArgb();
i++; continue; // Skip over the colour code.
}
if( shadowCol ) col = FastColour.Black.ToArgb();
int coords = ConvertToCP437( c );
int width = PtToPx( point, widths[coords] + 1 );
for( int xx = 0; xx < width; xx++ )
dstRow[x + xx] = col;
x += width;
}
x = startX;
col = FastColour.White.ToArgb();
} }
} }
protected Size MeasureBitmappedSizeImpl( ref DrawTextArgs args ) {
if( String.IsNullOrEmpty( args.Text ) ) return Size.Empty;
float point = args.Font.Size;
Size total = new Size( 0, PtToPx( point, boxSize ) );
for( int i = 0; i < args.Text.Length; i++ ) {
char c = args.Text[i];
bool code = c == '&' && i < args.Text.Length - 1;
if( code && ValidColour( args.Text[i + 1] ) ) {
i++; continue; // Skip over the colour code.
}
int coords = ConvertToCP437( c );
total.Width += PtToPx( point, widths[coords] + 1 );
}
if( args.Font.Style == FontStyle.Italic )
total.Width += Utils.CeilDiv( total.Height, italicSize );
if( args.UseShadow ) {
int offset = ShadowOffset( args.Font.Size );
total.Width += offset; total.Height += offset;
}
return total;
}
protected static int ConvertToCP437( char c ) { protected static int ConvertToCP437( char c ) {
if( c >= ' ' && c <= '~') if( c >= ' ' && c <= '~')
return (int)c; return (int)c;

View File

@ -114,7 +114,7 @@ namespace ClassicalSharp {
Texture MakeTextureImpl( ref DrawTextArgs args, int windowX, int windowY, bool bitmapped ) { Texture MakeTextureImpl( ref DrawTextArgs args, int windowX, int windowY, bool bitmapped ) {
Size size = bitmapped ? MeasureBitmappedSize( ref args ) : MeasureSize( ref args ); Size size = bitmapped ? MeasureBitmappedSize( ref args ) : MeasureSize( ref args );
if( parts.Count == 0 ) if( size == Size.Empty )
return new Texture( -1, windowX, windowY, 0, 0, 1, 1 ); return new Texture( -1, windowX, windowY, 0, 0, 1, 1 );
using( Bitmap bmp = CreatePow2Bitmap( size ) ) { using( Bitmap bmp = CreatePow2Bitmap( size ) ) {