2011-04-05 9 views
11

Estoy implementando un editor de texto en C++ simplemente usando la API Win32 vainilla y estoy tratando de encontrar la mejor manera de implementar el resaltado de sintaxis. Sé que existen controles existentes como el scintilla, pero lo hago por diversión, así que quiero hacer la mayor parte del trabajo yo mismo. También quiero que sea rápido y ligero.¿Cuál es la forma más rápida de dibujar texto formateado en la API de Win32?

Según lo que he aprendido hasta ahora, parece que la opción de bajo nivel para dibujar texto en GDI es la función TextOut. Sin embargo, si necesito seguir cambiando el color de la fuente, entonces tendré que hacer muchas llamadas al TextOut para dibujar un cuerpo de texto con formato mixto. ¿Esto es ineficiente? Cuando se implementan el resaltado de sintaxis y los controles de texto enriquecido, ¿es probable que usen TextOut detrás de escena o hay alguna otra manera? ¿Cada otro método de dibujar texto en GDI es solo un envoltorio de mayor nivel alrededor del TextOut?

+1

Conseguirlo correctamente ya es un desafío. [Mostrar texto con Uniscribe] (http://msdn.microsoft.com/en-us/library/dd317792.aspx) es una buena introducción a los problemas que deberá resolver. – MSalters

Respuesta

13

Tanto DrawText como TextOut son envoltorios para ExtTextOut, por lo que ExtTextOut es la API de bajo nivel. En mi experiencia, ExtTextOut es bastante rápido, así que dudo que veas problemas de rendimiento con ExtTextOut. Sin embargo, la creación/selección de fuentes puede ser una fuente de problemas de rendimiento, por lo que si cambia de una fuente a otra, puede obtener importantes ganancias de rendimiento almacenando en caché y reutilizando fuentes (HFONT) en lugar de CreateFont/SelectObject/DeleteObject cada vez. Básicamente, la primera vez que llame a SelectObject después de crear una nueva fuente, Windows realizará un proceso de coincidencia de fuentes para encontrar la mejor fuente física para la fuente lógica que ha solicitado. Este es un proceso bastante complejo, por lo que desea minimizar la cantidad de veces que ocurre en situaciones donde el rendimiento es importante.

Desarrollé un control de edición rico hace muchos años que era esencialmente una mini versión de Microsoft Word. Utilicé ExtTextOut como el caballo de batalla principal para todo el texto de salida. El control mantendría un caché de fuente de las fuentes utilizadas más recientemente (el tamaño de caché predeterminado era de 10 fuentes). Admitía el diseño WYSIWYG, por lo que en realidad estaba haciendo todo el diseño usando una impresora DC y fuentes, luego renderizaba una versión compatible con una pantalla DC y fuentes similares, por lo que había mucho trabajo adicional que probablemente no sea aplicable a tu situación. Aún así, el rendimiento fue excelente en el hardware típico del día (por ejemplo, 266 mhz Pentium).

+2

No es del todo exacto. Por ejemplo, 'ExtTextOut' a su vez utiliza API como Uniscribe. Y eso a su vez puede hacer la sustitución de fuentes para usted. Entonces, si está buscando "la" API de bajo nivel, Uniscribe puede ser mejor. Tiene primitivos como ['ScriptItemize'] (http://msdn.microsoft.com/en-us/library/dd368556.aspx) "Rompe una cadena Unicode en elementos individualmente configurables". – MSalters

+4

@MSalters: es cierto que ExtTextOut puede usar las API de Uniscribe, pero Uniscribe termina llamando de nuevo a ExtTextOut para hacer el renderizado real, por lo que todavía diría que ExtTextOut es "la" API de bajo nivel (consulte este enlace para obtener más detalles: [ www.catch22.net/tuts/neatpad/11](http://www.catch22.net/tuts/neatpad/11)). Dicho esto, Uniscribe podría ser una mejor opción en términos de funcionalidad, pero la "forma más rápida" de dibujar texto es ExtTextOut. – cbranch

+0

"DrawText y TextOut son contenedores para ExtTextOut": esto es correcto para Windows 7, pero no se aplica a Windows XP. Además de eso, PolyTextOut es la única API de dibujo de texto que no llama a ExtTextOut. Puede ser interesante probar la velocidad de PolyTextOut. – Elmue

1

Para uso complejo, probablemente desee DrawText, ya que le da más control que TextOut. Tiene un soporte de formato básico, pero menos de lo que necesitará para un editor. El siguiente paso es el editor de texto enriquecido de la biblioteca de controles comunes, que prácticamente se ocupa de todo eso por usted.

+1

¿'DrawText' es solo una función de conveniencia que actúa como un contenedor alrededor de' TextOut' o está completamente separado? Hice algunas pruebas muy simples y descubrí que 'TextOut' es notablemente más rápido. Soy consciente de los ricos controles de edición como la clase de ventana RICHEDIT de Riched32.dll, pero quiero implementar el control de texto enriquecido si es posible usando funciones de bajo nivel. –

+1

Las API Win32 son en su mayoría una "caja negra", pero si graba llamadas 'DrawText' en un metarchivo e inspecciona, verá una secuencia de llamadas a' ExtTextOutW'. –

7

En lugar de considerar qué función de "dibujar texto" es la más rápida, probablemente sea mucho más ventajoso considerar "¿Cómo puedo minimizar la cantidad de texto que tengo que renderizar en total?" volver a dibujar/invalidar a medida que cambia el texto, o cómo se puede almacenar en caché el texto renderizado para desplazarse.

+0

Punto de interés. No había mirado en el almacenamiento en caché. Gracias por la idea –

+2

Esta no es una respuesta a la pregunta. Si, por ejemplo, está dibujando un gran resultado de registro en una ventana o en un ListBox, no hay nada que pueda reutilizarse u omitirse. – Elmue

Cuestiones relacionadas