Exibir o texto com o Uniscribe

Seus aplicativos podem usar funções da API do Uniscribe para oferecer suporte à tipografia e à exibição e edição de texto internacional. O Uniscribe usa o parágrafo como a unidade para exibição de texto, e a funcionalidade do Uniscribe deve ser usada para o parágrafo inteiro.

Ao usar Uniscribe para exibição de texto, um aplicativo deve passar por um processo de formatação ("layout"), normalmente usando Uniscribe. O aplicativo divide um parágrafo de texto em cadeias de caracteres com o mesmo estilo, chamadas de "execuções". O estilo é determinado pela implementação específica, mas normalmente inclui atributos como fonte, tamanho e cor. Ao definir execuções, o aplicativo também pode aplicar outras informações, como dados de idioma e localidade mantidos para uso com ferramentas lexicais. Por exemplo, um aplicativo pode tratar como uma execução separada uma passagem em um texto principalmente em inglês que é renderizado em francês.

Depois de determinar as execuções para todos os parágrafos, o aplicativo divide cada parágrafo em cadeias de caracteres que têm o mesmo script e a mesma direção ("itens"). O aplicativo aplica as informações do item para produzir execuções exclusivas em script e direção e que se enquadram inteiramente em um único item ("intervalos").

A divisão de um item em intervalos é um pouco arbitrária, embora um intervalo deva consistir em um ou mais agrupamentos de caracteres indivisíveis definidos por scripts consecutivos, chamados de "clusters". Para idiomas europeus, um cluster normalmente corresponde a um único caractere de página de código ou ponto de código Unicode e consiste em um único glifo. No entanto, em idiomas como o tailandês, um cluster é um agrupamento de glifos e corresponde a vários pontos de código ou caracteres consecutivos. Por exemplo, um cluster tailandês pode conter uma consoante, uma vogal e um acento. Para não quebrar clusters, o aplicativo normalmente deve usar os intervalos mais longos que puder ou usar suas próprias informações lexicais para quebrar entre intervalos em lugares que não estão no meio de um cluster.

Depois de identificar os clusters em cada intervalo, o aplicativo deve determinar o tamanho de cada cluster. Ele usa Uniscribe para somar os clusters e determinar o tamanho de cada intervalo. Em seguida, o aplicativo soma os tamanhos dos intervalos até que eles excedam uma linha, ou seja, atinjam a margem. O intervalo que excede a linha é dividido entre a linha atual e a linha seguinte. Para cada linha, o aplicativo cria um mapa da posição visual para a posição lógica de cada intervalo. Em seguida, o aplicativo molda os pontos de código de cada intervalo em glifos, os quais ele pode subsequentemente posicionar e renderizar.

Um aplicativo faz layout de texto apenas uma vez. Depois, ele salva os glifos e as posições para fins de exibição ou os gera cada vez que exibe o texto, com a compensação sendo velocidade versus memória. Um aplicativo típico implementa o processo de layout uma vez e, em seguida, gera os glifos e as posições cada vez que exibe o texto.

Um aplicativo que usa scripts complexos tem os problemas a seguir com uma abordagem simples de layout e exibição.

  • A largura de um caractere de script complexo depende de seu contexto. Não é possível salvar as larguras em tabelas simples.
  • A quebra entre palavras em scripts, como o tailandês, requer suporte a dicionários. Por exemplo, nenhum caractere separador é usado entre palavras tailandesas.
  • Árabe, hebraico, persa, urdu e outros idiomas de texto bidirecional exigem reordenação antes da exibição.
  • Alguma forma de associação de fontes é necessária com frequência para usar facilmente scripts complexos.

O fato de Uniscribe usar o parágrafo como a unidade de exibição ajuda o aplicativo a lidar adequadamente com esses problemas de script complexo.

Observação

Uniscribe deve ser usado em um parágrafo inteiro, mesmo que as seções do parágrafo não sejam scripts complexos.

 

Como mostrado na tabela a seguir, o Uniscribe versão 1.6 ou superior oferece suporte a várias funções que aproveitam as marcas OpenType. Eles podem ser substituídos pelas funções regulares correspondentes do Uniscribe. Em geral, seus aplicativos devem trabalhar inteiramente com funções de um conjunto ou outro e não devem tentar "misturar e combinar" funções.

Função do Uniscribe regular Função do OpenType equivalente
ScriptItemize ScriptItemizeOpenType
ScriptShape ScriptShapeOpenType
ScriptPlace ScriptPlaceOpenType

 

Fazer layout de texto usando o Uniscribe

Seu aplicativo pode usar as etapas a seguir para fazer o layout de um parágrafo de texto com o Uniscribe. Esse procedimento pressupõe que o aplicativo já dividiu o parágrafo em execuções.

  1. Chame ScriptRecordDigitSubstitution somente ao iniciar ou receber uma mensagem WM_SETTINGCHANGE.

  2. (Opcional) Chame ScriptIsComplex para determinar se o parágrafo requer processamento complexo.

  3. (Opcional) Se estiver usando o Uniscribe para manipular texto bidirecional e/ou substituição de dígitos, chame ScriptApplyDigitSubstitution para preparar as estruturas SCRIPT_CONTROL e SCRIPT_STATE como entradas para ScriptItemize. Se pular esta etapa, mas ainda exigir a substituição de dígitos, substitua os dígitos nacionais por Unicode U+0030 a U+0039 (dígitos europeus). Para obter informações sobre substituição de dígitos, consulte Formas de dígitos.

  4. Chame ScriptItemize para dividir o parágrafo em itens. Se não estiver usando o Uniscribe para a substituição de dígitos e a ordem bidirecional for conhecida, por exemplo, devido ao layout de teclado usado para inserir o caractere, chame ScriptItemize. Na chamada, forneça ponteiros nulos para as estruturas SCRIPT_CONTROL e SCRIPT_STATE. Essa técnica gera itens apenas pelo mecanismo de moldagem, e os itens podem ser reordenados usando as informações do mecanismo.

    Observação

    Normalmente, os aplicativos que funcionam apenas com scripts da esquerda para a direita e sem qualquer substituição de dígitos devem passar ponteiros nulos para as estruturas SCRIPT_CONTROL e SCRIPT_STATE.

     

  5. Mescle as informações do item com as informações de execução para produzir intervalos.

  6. Chame ScriptShape para identificar clusters e gerar glifos.

  7. Se ScriptShape retornar o código USP_E_SCRIPT_NOT_IN_FONT ou S_OK com a saída que contém glifos ausentes, selecione caracteres de uma fonte diferente. Substitua outra fonte ou desabilite a modelagem definindo o membro eScript da estrutura SCRIPT_ANALYSIS passada para ScriptShape como SCRIPT_UNDEFINED. Para obter mais informações, consulte Usar fallback de fonte.

  8. Chame ScriptPlace para gerar larguras avançadas e as posições x e y para os glifos em cada intervalo sucessivo. Este é o primeiro passo no qual o tamanho do texto se torna uma consideração.

  9. Some os tamanhos dos intervalos até que a linha exceda.

  10. Quebre o intervalo em um limite de palavra usando os membros fSoftBreak e fWhiteSpace nos atributos lógicos. Para interromper a execução de um único cluster de caracteres, use as informações retornadas chamando ScriptBreak.

    Observação

    Decida se o primeiro ponto de código de um intervalo deve ser um ponto de quebra de palavra porque o último caractere do intervalo anterior o exige. Por exemplo, se um intervalo terminar em vírgula, considere o primeiro caractere do próximo intervalo como um ponto de quebra de palavra.

     

  11. Repita as etapas de 6 a 10 para cada linha no parágrafo. No entanto, se quebrar a última execução na linha, chame ScriptShape para remodelar a parte restante da execução como a primeira execução na próxima linha.

Exibir o texto usando o Uniscribe

Seu aplicativo pode usar as etapas a seguir para exibir um parágrafo de texto. Esse procedimento pressupõe que o aplicativo já definiu o layout do texto e não salvou os glifos e as posições no processo de layout. Se a velocidade for uma preocupação, o aplicativo poderá salvar os glifos e as posições do procedimento de layout e começar na etapa 2 no procedimento de exibição.

Observação

O aplicativo poderá omitir a etapa 2 se o texto não contiver caracteres de scripts da direita para a esquerda, não contiver caracteres de controles bidirecionais e usar um nível de incorporação base da esquerda para a direita.

 

  1. Para cada arquivo, faça o seguinte:

    1. Se o estilo foi alterado desde a última execução, atualize o identificador para o contexto do dispositivo liberando-o e obtendo-o novamente.
    2. Chame ScriptShape para gerar glifos para a execução.
    3. Chame ScriptPlace para gerar uma largura avançada e um deslocamento x,y para cada glifo.
  2. Faça o seguinte para estabelecer a ordem visual correta para as execuções na linha:

    1. Extraia uma matriz de níveis de incorporação bidirecionais, um por intervalo. O nível de incorporação é dado por (SCRIPT_ITEM) si. (SCRIPT_ANALYSIS) a. (SCRIPT_STATE) s.uBidiLevel.
    2. Passe essa matriz para ScriptLayout para gerar um mapa de posições visuais para posições lógicas.
  3. (Opcional) Para justificar o texto, chame ScriptJustify ou use conhecimento especializado do texto.

  4. Use o mapa visual para lógico para exibir as execuções em ordem visual. Começando na extremidade esquerda da linha, chame ScriptTextOut para exibir a execução dada pela primeira entrada no mapa. Para cada entrada subsequente no mapa, chame ScriptTextOut para exibir a execução indicada à direita da execução exibida anteriormente.

    Se omitir a etapa 2, inicie na extremidade esquerda da linha e chame ScriptTextOut para exibir a primeira execução lógica e, em seguida, para exibir cada execução lógica à direita da execução anterior.

  5. Repita as etapas acima para todas as linhas do parágrafo.

Usar o Uniscribe