Thursday, 24 September 2009

Corrigiendo el aliasing del texto inclinado

Prosiguiendo los cálculos realizados sobre mi aplicación Thundax Box Manager, en éste artículo daré importancia a la corrección del Aliasing que ocurre en el momento de inclinar el texto. La propia API de windows nos permite trabajar con las fuentes modificando los parámetros básicos de éstas y definiendo así su calidad. Si observamos la siguiente imagen sacada de la aplicación, notaréis como el sistema intenta dibujar las letras orientadas con una inclinación de la manera que puede. La verdad es que no se entienden muy bien y no queda muy bonito en la aplicación.

Si consultamos los parámetros de CreateFont, podemos ver que trabaja bastante bien con fuentes Truetype y que además permite corregir el aliasing ajustando un parámetro de su función. Mediante el parámetro fdwQuality [in]:
The output quality. The output quality defines how carefully GDI must attempt to match the logical-font attributes to those of an actual physical font. It can be one of the following values.
Podemos utilizar el valor: ANTIALIASED_QUALITY.
Font is antialiased, or smoothed, if the font supports it and the size of the font is not too small or too large.
Aquí podéis ver las diferentes pruebas realizadas cambiando el tipo de fuente y el tamaño:


Como podéis ver mediante el valor seleccionado podemos mejorar el aliasing de la fuente aplicando un filtro antialiasing sobre el texto rotado. Desde la aplicación, podemos ir probando las diferentes fuentes que tenemos instaladas pero he comprobado que hay muchas fuentes que no disponen de éste comportamiento. Al principio había dejado por defecto la fuente Tahoma, pero no funciona tan bien como la Calibri que es la que utiliza Microsoft Office. Ahora en la aplicación, las fuentes tienen mejor aspecto:


Para acabar de mejorar el método de pintado del texto, he arreglado un tema pendiente sobre centrar el texto en la línea. El cálculo es como siempre bastante fácil y solo tenemos que recurrir a la trigonometría para solucionar ésto.

El problema reside en que el texto empieza a dibujarse desde el centro de la línea, ya que se calcula el punto médio entre el origen y el final de la conexión. Pero claro, tenemos que tener en cuenta la longitud del texto escrito y desplazar el centro la mitad de ésta longitud para que el texto se muestre centrado:

En la siguiente imagen describo el cálculo con un poco más de precisión:

Utilizando la función Canvas.TextWidth podemos saber la longitud actual del texto en píxels, luego solo necesitamos dividir éste valor entre 2 para obtener la mitad de la longitud. Ahora sabiendo el ángulo de inclinación tenemos que calcular los valores de a y b para calcular el nuevo punto a partir de P.

La nueva función del cálculo de la orientación queda de la siguiente manera:


procedure TAbstractLine.DrawTextOrientation(Source, Target: TPoint);

function iif(condition: boolean; resultTrue: integer; resultFalse: integer): integer;
begin
Result := resultFalse;
if condition then
Result := resultTrue
end;

var
newFont, FontSelected: integer;
angle: double;
iAngle, i: integer;
Position: TPoint;
calc : double;
begin
if FDescription.text = '' then
exit;
angle := CalcAngleTwoPoints(Source, Target);
iAngle := round(angle);

if (iAngle >= 91) and (iAngle <= 180) then
iAngle := iAngle + 180;

if (iAngle >= 181) and (iAngle <= 269) then
iAngle := iAngle - 180;

for i := 0 to FDescription.Count - 1 do
begin
Position := Point((Target.X + Source.X) div 2, (Target.Y + Source.Y) div 2);
FCanvas.Font := FFontText;
calc := (FCanvas.TextWidth(FDescription[i]) div 2) * cos(DegToRad(iAngle));
Position.x := Position.x - round(calc);
calc := (FCanvas.TextWidth(FDescription[i]) div 2) * sin(DegToRad(iAngle));
Position.y := Position.y + round(calc);

SetBkMode(FCanvas.Handle, transparent);
newFont := CreateFont(-FfontText.Size, 0, iAngle * 10, 0, iif(fsBold in FfontText.Style, FW_BOLD, FW_NORMAL), iif(fsItalic in FfontText.Style, 1, 0), iif(fsUnderline in FfontText.Style, 1, 0), iif
(fsStrikeOut in FfontText.Style, 1, 0), ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE, PChar(FfontText.Name));

Fcanvas.font.color := FfontText.color;
FontSelected := SelectObject(FCanvas.Handle, newFont);
TextOut(FCanvas.Handle, Position.X , Position.Y, PChar(FDescription[i]), Length(FDescription[i]));
SelectObject(FCanvas.Handle, FontSelected);
DeleteObject(newFont);
end;
end;


La última versión de la aplicación con éstos cambios la podéis encontrar aquí: Thundax Box Manager v1.0.0 build 159.exe.

Aquí os dejo con una imagen de la aplicación utilizando el corrector de aliasing:


  • Enlaces de interés:
Display rotated text.
Image Processing.
Graphic Algorithms.
Flicker Free TImage Delphi.
Win32 and COM Development.
Delphi DegToRad Command.


0 comments:

Post a Comment