2010-12-10 29 views
6

Esta es una pregunta con respecto a una construcción muy simple - Tengo el siguiente XAML:TextBlock dentro de un Viewbox - extraña representación

<Viewbox Height="100" Stretch="Uniform"> 
     <TextBlock FontFamily="Georgia">My Cool Text</TextBlock> 
    </Viewbox> 

Esto es bastante sencillo de entender. Sin embargo, cuando comienzo el programa obtengo un extraño texto borroso (no hay ningún efecto de mapa de bits en mi proyecto). alt text

(lado izquierdo - la vista del diseñador en VS2010, lado derecho - la aplicación en ejecución)

¿alguien tiene alguna sugerencia acerca de por qué ocurre esto ??

+0

se ve perfecto en mi máquina –

+0

¡Se ve bien en mi máquina, también! ¿Qué versión de WPF estás usando? ¿Puedes probarlo en una nueva ventana con esto ya que solo es contenido? – decyclone

+0

Sí, se ve bien si creo una nueva aplicación que solo contiene este código. Lo sé :) El problema es que no tengo idea CÓMO llegué a este estiramiento borroso. Hay algo en alguna parte y no tengo idea de para empezar. Publicar todos los dictados de código/recurso tampoco es la mejor idea, simplemente es demasiado. – Jefim

Respuesta

27

Si bien Jefim ha respondido correctamente a su propia pregunta, quería explicar por qué obtienes este comportamiento cuando utilizas este conjunto particular de características. Jefim sugiere que esto es un error en WPF, pero no lo es. El problema surge como resultado de pedirle a WPF que haga algo imposible. Tiene que elegir un compromiso cuando ha pedido esta cosa imposible, y el resultado es lo que ve arriba.

La explicación es un poco larga para un comentario, y es por eso que lo estoy poniendo en una respuesta separada.

Este ejemplo utiliza dos características mutuamente contradictorias de WPF. Esas características son:

  1. La capacidad de hacer imágenes consistentemente a cualquier escala
  2. La capacidad de representar el texto de la misma manera GDI32 muestra texto

No puede utilizar ambas características a la vez. GDI32 procesa el texto de una manera que no se puede escalar de manera consistente: si un trozo de texto en particular en un determinado tamaño de fuente tiene 200 píxeles de ancho, si multiplica el tamaño de fuente por 3 y representa el mismo texto en la misma familia de fuentes en ese nuevo tamaño de fuente, en GDI32 probablemente no será de 600 píxeles; estará cerca, pero normalmente no será del todo correcto.

GDI32 se complica con la forma y el ancho de los caracteres para mejorar la claridad y la nitidez del texto. Específicamente, dobla las letras fuera de forma para que sus características se alineen mejor con los píxeles en su pantalla. Y donde sea necesario, ajustará el ancho de los caracteres individuales para que sea un número exacto de píxeles de ancho. Como esta flexión de letras se basa en píxeles reales, dobla el texto de diferentes formas con diferentes tamaños de fuente.

Si bien eso le da un bonito texto nítido, se ve absolutamente horrible si intenta cambiar la escala gradualmente. Si intenta animar el tamaño de fuente de algún texto procesado de esta manera, la cosa parecerá brillar y estremecerse, porque los ajustes realizados en el nombre de claridad terminan siendo ligeramente diferentes en cada tamaño de fuente.Incluso si no está animando, aún puede producir resultados pobres: si tiene un solo tipo de letra mostrado en varios tamaños, puede verse bastante diferente en cada tamaño; si su aplicación tiene una función de zoom, el carácter del texto puede cambiar significativamente a medida que acerca y aleja la imagen. (Y también lo puede hacer el diseño. Si usa Microsoft Word, puede haber notado que a veces obtiene extraños espacios extra amplios entre ciertas palabras. Este es el resultado de la lucha de Word con GDI32 - Word intenta mantener el diseño en pantalla lo más cerca posible de cómo se verán las cosas al imprimir, lo que significa que a veces choca con el ajuste de cuadrícula de GDI32.)

Entonces WPF ofrece un enfoque diferente para la representación de texto: puede representar el texto de la manera más fiel posible al diseño original de la fuente. Esto distorsiona menos el texto, y significa que no obtienes discontinuidades a medida que escalas.

El inconveniente es que el texto se ve borroso, en comparación con el aspecto del texto presentado por GDI32. (Las distorsiones hechas por GDI32 están todas dirigidas a mejorar la claridad.)

Por lo tanto, en WPF 4.0, Microsoft agregó la capacidad de representar texto en la forma en que lo haría GDI32. Eso es lo que hace TextOptions.TextFormattingMode="Display".

Al activar esa opción, dices "No necesito una escala uniforme, y prefiero la claridad, así que genera los mismos píxeles que habrías hecho en GDI32". Si luego aplica la escala, habiéndole dicho a WPF que no necesita escalabilidad, obtendrá resultados repugnantes. WPF generó cuidadosamente una representación de mapa de bits del texto exactamente según sus especificaciones, y luego le dijo que renderizara ese texto en una escala diferente. Y entonces parece lo que es: un mapa de bits escalado de algún texto que se generó para una resolución diferente.

Podría argumentar que WPF podría hacer algo diferente aquí: si aplica una transformación de escala en GDI32 vería un comportamiento diferente: vería la inconsistencia a diferentes escalas descritas anteriormente. Si realmente quieres ese efecto en WPF, puedes obtenerlo modificando el tamaño de la fuente directamente. Pero WPF no prioriza obtener el mismo efecto; sus objetivos son posibilitar la obtención de texto nítido al estilo GDI32 cuando realmente lo necesite y proporcionar una escala uniforme de forma predeterminada.

Y lo que te encuentras aquí es la "escala constante". Activar la renderización de texto estilo GDI32 no interrumpe el escalamiento coherente: la aplicación de un factor de escala (ya sea directamente, a través de ScaleTransform o indirectamente a través de Viewbox) cambiará las dimensiones de la imagen visual exactamente por el factor de escala especificado. Si fuera a volver a generar las imágenes de texto ajustando la cuadrícula al tamaño recién escalado, el texto saldría con un ancho diferente. Eso realmente causaría los problemas Viewbox: aplica un factor de escala basado en el tamaño natural del contenido, diseñado para que se ajuste al espacio disponible. Pero si vuelve a encajar la cuadrícula después de escalar, eso realmente cambiaría el ancho. Debido a las incoherencias inherentes a la forma en que funciona el renderizado de texto GDI32, es posible que ViewBox ni siquiera sea posible encontrar una escala adecuada; es posible obtener una pieza de texto que, cuando se procesa en una fuente determinada, nunca saldrá a 200 píxeles de ancho. Para algunos tamaños de fuente, el redondeo inherente al ajuste de la grilla puede reducir el tamaño a, por ejemplo, 198, y puede seguir así a medida que realiza pequeños incrementos en el tamaño de la fuente, hasta que pasa un umbral en el que puede saltar a 202 píxeles.

Para un Viewbox intentando forzar que el texto encaje exactamente en 200 píxeles, eso sería un problema. Pero Viewbox no funciona de esa manera: utiliza la escala constante de WPF, en sentido descendente desde el punto en el que se elige el tamaño de letra con el que funciona la representación de texto de estilo GDI32. Así que Viewbox siempre podrá hacer lo que está diseñado para hacer, pero esa es una tarea que es fundamentalmente incompatible con el procesamiento de texto estilo GDI32.

En resumen, WPF representa el texto del tamaño de fuente que solicitó y luego ajusta el resultado.

Así que debe elegir una sola característica: no puede tener ambas porque es simplemente imposible. No intente procesar texto en un contexto en el que se pueda aplicar un factor de escala arbitrario (por ejemplo, Viewbox) o no active el procesamiento de texto al estilo GDI32. De lo contrario, obtienes ese texto pixelado extraño que has encontrado.

+0

Gracias por este "comentario" - es bastante interesante de leer. Lo estoy marcando como la respuesta, ya que solo lo vale. En cuanto a mi formulación de un "error", tu explicación me ha aclarado algunas cosas. Ahora solo voy a decir: esto debería estar en los documentos de MSDN. Realmente, porque esto no es tan obvio (al menos para mí) y tuve que pasar algunas horas antes de llegar a la causa del problema. De todos modos, gracias de nuevo por la respuesta. – Jefim

+0

@lan Griffiths thx, quiero saber si puedo obtener el elemento que en viewBox ha cambiado su tamaño real? El tamaño real es el elemento mostrar en pantalla no en Tamaño real. Y publico en http://stackoverflow.com/questions/42411455/how-to-know-the-element-actual-size-have-change-by-other-control?noredirect – lindexi

8

Bien, error encontrado. Mi estilo de ventana tiene la siguiente colocador:

<Setter Property="TextOptions.TextFormattingMode" Value="Display"/> 

Si fijo de nuevo a "ideal" (que es el valor por defecto), entonces se vierte el texto dentro del rectángulo de visualización correctamente. Diría que esto es un error dentro de WPF. Básicamente, si prueba esto:

<Viewbox Height="100" Stretch="Uniform" TextOptions.TextFormattingMode="Display"> 
    <TextBlock FontFamily="Georgia">My Cool Text</TextBlock> 
</Viewbox> 

Obtendrá el mismo resultado que en mi imagen inicial.

Cuestiones relacionadas