versiones software embarcadero descargar delphi delphi-xe7

delphi - software - ¿Cuáles son las implicaciones de usar Canvas.TextOut?



delphi wikipedia (1)

La diferencia observada se debe al uso de diferentes funciones de representación de texto WinAPI y su comportamiento. Especificamente kerning caracteres

En tipografía, el kerning (con menos frecuencia de mortaja) es el proceso de ajustar el espaciado entre los caracteres en una fuente proporcional, generalmente para lograr un resultado visualmente agradable. El kerning ajusta el espacio entre las formas de las letras individuales, mientras que el seguimiento (espacio entre letras) ajusta el espaciado de manera uniforme en un rango de caracteres.

  1. DrawText

La función DrawText dibuja texto con formato en el rectángulo especificado. Formatea el texto de acuerdo con el método especificado (expandiendo pestañas, justificando caracteres, rompiendo líneas, etc.).

  1. ExtTextOut (utilizado por Canvas.TextOut )

Declaración ExtTextOut :

BOOL ExtTextOut( _In_ HDC hdc, _In_ int X, _In_ int Y, _In_ UINT fuOptions, _In_ const RECT *lprc, _In_ LPCTSTR lpString, _In_ UINT cbCount, _In_ const INT *lpDx );

Si el parámetro lpDx es NULL, la función ExtTextOut usa el espaciado predeterminado entre los caracteres. Los orígenes de las celdas de caracteres y el contenido de la matriz a la que apunta el parámetro lpDx se especifican en unidades lógicas. El origen de una celda de carácter se define como la esquina superior izquierda de la celda de carácter.

Básicamente, DrawText dibujará automáticamente texto con formato y eso incluye ajustar el espaciado entre caracteres (kerning), mientras que ExtTextOut usará por defecto el espacio predeterminado entre caracteres (sin kerning). Si desea ajustar el espaciado entre caracteres, deberá calcular y proporcionar el parámetro de matriz de kerning ( lpDx ).

Esas diferencias son especialmente visibles con algunas combinaciones de caracteres como T y letras pequeñas que caben visualmente debajo de T , o AV donde una V encaja sobre A Las diferentes fuentes también tienen diferentes kernes predeterminados y es por eso que algunas fuentes tienen visualmente la misma representación con ambas funciones y otras no. Kerning también depende del tamaño de la fuente. Por ejemplo, los caracteres AV renderizados con Arial en 9 pt tendrán la misma salida con ambas funciones, mientras que Arial en 12 pt dará como resultado diferentes salidas.

La primera línea en la siguiente imagen se dibuja con no kerning usando ExtTextOut y la segunda línea con kerning automático usando DrawText .

Introducción

Mi pregunta proviene de un problema bastante interesante con el que he estado lidiando durante los últimos días. Hace poco hice una pregunta sobre Escribir un inspector de propiedades personalizadas: ¿Cómo manejar el enfoque del editor in situ al validar valores?

Desde entonces he progresado bastante bien con mi control, como agregar un divisor en el medio para separar las filas de Nombre y Valor, y lo más importante es que el divisor se puede usar para cambiar el tamaño de las dos columnas.

Aquí es donde empezaron mis problemas: tener el editor in situ visible mientras se cambia el tamaño del divisor provocó una ligera desaceleración en mi control. Así que cambié aún más el código para mostrar solo el editor in situ si no se ha cambiado el tamaño del divisor. Básicamente, usé Canvas.TextOut para dibujar mis valores como cadenas, si se selecciona una fila, el editor de Inplace se muestra arriba. El editor in situ se oculta si se cambia el tamaño del divisor, una vez que se completa la operación de cambio de tamaño, el editor in situ vuelve a ser visible.

Si bien esto resolvió el ligero problema de desaceleración que mencioné, me enfrenté a un nuevo problema, ya que el texto del editor in situ (que es básicamente un TEdit) difería ligeramente del texto que estaba dibujando con Canvas. Texto siguiente

Ejemplo 1

La diferencia es bastante sutil, pero si te fijas lo suficiente, puedes verlo:

fig.1 Canvas.TextOut

fig.2 DrawText

Es posible que necesite usar una lupa de pantalla para ver más de cerca, pero con la fila SomeText es más notorio porque el espaciado entre Some y Text y también entre la T y e en Text es ligeramente diferente.

Ejemplo 2

Un ejemplo ligeramente mejor es tal vez comparar entre Canvas.TextOut y DrawText con el texto del editor in situ (TEdit):

fig.3 Comparación

Como se puede ver la diferencia aquí es mucho más prominente. La cadena True muestra claramente un espaciado mucho mayor entre los caracteres del texto cuando se usa Canvas.TextOut , donde el DrawText y el inplace editor representan el texto exactamente igual.

Cuando estaba usando Canvas.TextOut estaba obteniendo todo tipo de desajustes de texto horribles entre cambiar el tamaño de mi inspector divisor y mostrar y ocultar el editor in situ. Si no hubiera experimentado y probado métodos alternativos de dibujo de texto, creo que nunca me hubiera dado cuenta de la diferencia y encontrado una solución. Es importante saber que estaba usando exactamente la misma configuración de Fuente al dibujar mi texto en el lienzo como la Fuente que había definido para el editor in situ.

Ahora que estoy usando DrawText lugar de Canvas.TextOut todo funciona al unísono con el editor in situ y exactamente como lo deseo.

Pregunta

Mi pregunta es ¿qué hace que Canvas.TextOut renderice el texto de forma tan diferente a DrawText ? De mi ejemplo y de mi problema actual, está claro que Canvas.TextOut no renderiza el texto de la misma manera que lo hace un TEdit con la misma configuración de Fuente, pero DrawText hace que el texto DrawText ser el correcto.

Esto me hace cuestionar el uso de Canvas.TextOut , si no representa correctamente el texto, ¿siempre debería utilizar DrawText ?

Demo de prueba

Puedes probar esto por ti mismo con el siguiente código:

type TForm1 = class(TForm) Edit1: TEdit; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormPaint(Sender: TObject); private FFont: TFont; FRect: TRect; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin FFont := TFont.Create; FFont.Color := clNavy; FFont.Name := ''Segoe UI''; FFont.Size := 9; FFont.Style := []; FRect := Rect(10, 30, 100, 100); Canvas.Font.Assign(FFont); Edit1.Font.Assign(FFont); end; procedure TForm1.FormDestroy(Sender: TObject); begin FFont.Free; end; procedure TForm1.FormPaint(Sender: TObject); begin Canvas.TextOut(10, 10, ''Canvas.TextOut: [True]''); DrawText(Canvas.Handle, PChar(''DrawText: [True]''), Length(''DrawText: [True]''), FRect, DT_LEFT); end;

Con lo anterior ejecutándose en un proyecto VCL completamente nuevo, el resultado que obtengo es el siguiente:

Fig.4 Demo de prueba

Una vez más, note el espaciado en la cadena True al usar Canvas.TextOut , desde mi final es claramente diferente a DrawText y la forma en que el TEdit dibuja su texto.

La imagen de abajo es la misma que la de la figura 4 pero con un zoom del 400%.

Fig. 5 Demo de prueba ampliada a 400%

Se observan diferencias notables entre la T y la e en Text y también T y r en True .

fig.6 La palabra ''Texto'' se acercó al 400% con pautas

Puede ver que el kerning entre la T y la e es un píxel más cerca con DrawText que con Canvas.TextOut (que usa ExtTextOut ).

fig.7 La palabra True acercó al 700% con pautas

Puede ver que el kerning entre la T y la r es un píxel más cerca con DrawText y el Inplace Editor (TEdit) que con Canvas.TextOut (que usa ExtTextOut ).

He probado varias fuentes diferentes y aquí están mis conclusiones:

Bueno:

Arial, Cambria, Candara, Comic Sans MS, Consolas, Courier, Courier New, Fixedsys, Georgia, Lucida Console, Lucida Sans Unicode, Microsoft Sans Serif, Tahoma, Terminal y Times New Roman.

Malo:

Calibri, Corbel, Myriad Pro, Segoe UI, Trebuchet MS y Verdana.

Las buenas fuentes son las que parecen representar texto de la misma manera que DrawText y los controles Inpace Editor (TEdit) utilizan Canvas.TextOut . Los malos muestran que Canvas.TextOut reproduce el texto ligeramente diferente a los otros métodos.

Puede haber alguna pista aquí, aunque no estoy muy seguro, pero lo estoy agregando de todas formas por si acaso.