2011-10-10 9 views
7

He estado luchando con la medición de texto y lienzos escalados.midiendo texto en lienzo a escala

Cuando el lienzo no tiene escala, getTextBounds y measureText brindan resultados precisos. Sin embargo, cuando el lienzo se escala, ambos métodos no ofrecen resultados que coincidan con el tamaño real de un texto impreso.

Para las pruebas que he creado una subclase de vista con el siguiente método onDraw:

final float scaling = 0.51f; 
final int fontSize = 50; 

canvas.scale(scaling, scaling); 
font = Typeface.create("Arial", Typeface.NORMAL); 

Paint paint = new Paint(); 
paint.setColor(0xff4444ff); 
paint.setTypeface(font); 
paint.setTextSize(fontSize); 
paint.setAntiAlias(true); 

int x = 10; 
int y = 100; 
final String text = "Lorem ipsum dolor sit amet, consectetur adipisici elit..."; 
canvas.drawText(text, x, y, paint); 

// draw border using getTextBounds 

paint.setColor(0xffff0000); 
paint.setStyle(Paint.Style.STROKE); 
paint.setTypeface(font); 
paint.setTextSize(fontSize); 
Rect bounds = new Rect(); 
paint.getTextBounds(text, 0, text.length(), bounds); 
bounds.offset(x, y); 
paint.setColor(0x80ffff00); 
canvas.drawRect(bounds, paint); 

// draw border using measureText 

float w = paint.measureText(text); 
bounds.left = x; 
bounds.right = (int) Math.ceil(bounds.left + w); 
bounds.top -= 10; 
bounds.bottom += 10; 
paint.setColor(0x8000ffff); 
paint.setPathEffect(new DashPathEffect(new float[] { 10, 10 }, 0)); 
canvas.drawRect(bounds, paint); 

para escalar = 0.5 me sale el siguiente resultado: canvas scaling 0.5

para escalar = 0,51 el siguiente resultado se muestra: canvas scaling 0.51

El borde amarillo sólido marca el rect entregado desde getTextBounds, el cian rect de trazos se representa utilizando el ancho entregado fr om measureText.

Como puede ver, el texto con escala = 0.5 es más pequeño que las dimensiones medidas y con escala = 0.51 el texto dibujado es mucho más grande que la dimensión medida.

¡Se agradece cualquier ayuda!

Respuesta

4

Ok, descubrí cómo eludir el problema.

El problema es que la pintura no sabe acerca de la escala del lienzo. Por lo tanto, measureText y getTextBounds entregan el resultado sin escalar. Pero dado que el tamaño de la fuente no escala linealmente (sin embargo, el rect dibujado sí lo hace), debe compensar ese efecto manualmente.

Así que la solución sería:

// paint the text as usual 
Paint paint = new Paint(); 
paint.setTypeface(font); 
paint.setTextSize(fontSize); 
canvas.drawText(text, x, y, paint); 


// measure the text using scaled font size and correct the scaled value afterwards 
Paint paint = new Paint(); 
paint.setTypeface(font); 
paint.setTextSize(fontSize * scaling); 
float w = paint.measureText(text)/scaling; 
0

Usando Mono for Android tuve que usar las métricas de pantalla como se muestra aquí:

public override System.Drawing.SizeF MeasureString(MyFont f, string text) 
{ 
    Rect r = new Rect(); 

    f.DrawingFont.GetTextBounds(text, 0, text.Length, r); 

    //Manual scaling using DisplayMetrics due to Android 
    //issues for compatibility with older versions 
    Android.Util.DisplayMetrics metrics = new Android.Util.DisplayMetrics(); 
    GetDisplay.GetMetrics(metrics); 

    return new System.Drawing.SizeF(r.Width(), r.Height() * metrics.Density); 
} 

Dónde f.DrawingFont es un Androdid.Text.TextPaint getDisplay es:

private Display GetDisplay() 
{ 
    return this.GetSystemService(Android.Content.Context.WindowService).JavaCast<Android.Views.IWindowManager>().DefaultDisplay; 
} 

Y el mismo método en Java es:

private Display getDisplay() { 
    return ((WindowManager) getContext().getSystemService(
      Context.WINDOW_SERVICE)).getDefaultDisplay(); 
} 
+0

que eres corrección se aplica siempre y no compensa por un valor de escala en el lienzo, no? De hecho, no creo que el cálculo de la recta de delimitación sea incorrecto, sino que el código de representación de la fuente no selecciona el tamaño de fuente correcto según la escala de lienzo ... –

+0

Sí, siempre se calcula que las dimensiones de texto son necesarias sin escalar el lienzo. –

+0

Olvidé mencionar que esto se usa sobre todo para posicionar el texto en el lienzo, ya que es necesario conocer las dimensiones exactas y la posición. –