Como converter códigos de caracteres Unicode para índices de glifo TrueType no Windows 95

IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine Translation ou MT), não tendo sido portanto traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes ao software de tradução automática (MT). Obrigado.

Clique aqui para ver a versão em Inglês deste artigo: 241020
Este artigo foi arquivado. É oferecido "como está" e não será mais atualizado.
Sumário
Aplicativos geralmente desenhar texto Unicode, especificando códigos de caracteres em uma seqüência de palavras. Quando é usada uma fonte TrueType, o sistema operacional converte esses códigos de caracteres em índices de glifo TrueType quando ele desenha os glifos. Um aplicativo talvez precise converter códigos de caracteres para índices de glifo. Este artigo descreve, com código-fonte exemplo, como obter índices de glifo de arquivos de fonte TrueType.
Mais Informações
Desenho de um caractere em um dispositivo no Windows envolve mapear o código do caractere para um índice dependente de fonte do elemento gráfico do caractere (um glifo). Quando é usada uma fonte TrueType, esses índices são chamados de índices de glifo.

Arquivos de fonte TrueType tem um formato arquivo flexível e orientada a tabela. A flexibilidade desse formato de arquivo suporta uma variedade de caracteres codificação (ou mapeamento) de um código de caractere para glifo respectivo. Uma tal codificação pode ser de Unicode para índices de glifo.

Os sistemas operacionais Microsoft Windows utilizar arquivos de fonte TrueType que quase sempre são codificados em Unicode. Até mesmo as fontes TrueType usadas pelo Windows 95 (e suas versões predecessora para o Windows 3.1) usam o padrão Unicode como sua codificação interno. Consulte a seção Referências deste artigo para obter mais informações sobre o padrão Unicode e o arquivo de fonte TrueType.

As funções do Win32 aplicativo Programming Interface (API) são exportadas como dois pontos de entrada separada. A primeira foi a base de nome de função com um acrescentadas "A"; o segundo tem o nome função base com um "W" acrescentada. Esses pontos de entrada suporte o conjunto de caracteres (ou ANSI) seqüência de codificação e o Unicode (ou caractere largo) codificação, respectivamente. Os arquivos de cabeçalho do SDK definem o nome da função base como o "A" ou "W" variante, dependendo do uso da macro UNICODE, mas um variante pode ser referenciado diretamente.

Maioria das funções no Win32 API para Windows 95 e versões posteriores suportam apenas as versões ANSI das funções. Juntamente com a API de ANSI, também há suporte para um subconjunto limitado de funções compatíveis com Unicode, como TextOutW , lstrlenW e assim por diante. Consulte a seção referências para obter mais informações sobre o suporte Unicode no Windows 95 e seus sucessores.

Este conjunto de caracteres largos funções ou Unicode oferece suporte a escrever um aplicativo limitado compatíveis com Unicode. Assim como um aplicativo ANSI talvez precise usar índices de glifo, um aplicativo compatíveis com Unicode precisa de acesso a elas bem. Nesse caso ocorre quando o aplicativo usa alguns recursos avançados de arquivos de fonte TrueType, se o aplicativo precisa as definições de glifo, ou se ele precisa implementar uma solução alternativa ou funcionalidade caso contrário não presente no sistema operacional.

ANSI aplicativo pode usar a função GetCharacterPlacementA para converter uma seqüência de bytes de códigos de caracteres para índices de glifo. Se o aplicativo usa uma codificação de seqüência de caracteres Unicode e é executado no Windows NT, há uma versão de caractere largo da função GetCharacterPlacement . No Windows 95, a função GetCharacterPlacementW não é implementada para que não haja nenhuma API para converter de Unicode para índices de glifo.

Para converter um código de caractere Unicode em um índice de glifo TrueType, um aplicativo deve recuperar os dados da tabela para a codificação Unicode para glifo índice. Os dados em um arquivo de fonte TrueType podem ser obtidos chamando a função do Win32 GetFontData . Esta função retorna um buffer de bytes não processados, mas ele pode extrair esse buffer relativo para o início de uma tabela TrueType nomeado. A função também funciona no arquivo de fonte TrueType realizado atualmente no dispositivo contexto (DC). Esses recursos tornam a função mais úteis que a alternativa de localizar o arquivo de fonte e analisar seu diretório de tabela para buscar à tabela apropriada.

Uma codificação Unicode para glifo índice está localizada em uma tabela de um arquivo de fonte TrueType que está marcado como "cmap", que é o nome de marca para a tabela que contém os mapeamentos de caracteres para o arquivo de fonte. Esta tabela pode conter um ou mais subtabelas que são mapeamentos diferentes.

Imediatamente após os valores de curtos não assinados iniciais da tabela "cmap" é um diretório de cada codificação que o arquivo de fonte TrueType contém. Por especificação TrueType, a codificação Unicode está localizada na subtabela marcada com um valor PlatformId 3 e um valor SpecificId de 1. A especificação também define subtabela referenciada por essa codificação 3-1 seja uma subtabela Formatar 4. Uma codificação com uma PlatformId de 3 e um SpecificId 0 (zero) também é 4 de formato de codificação, mas o arquivo de fonte normalmente é interpretado como um arquivo de fonte símbolo. Por sugestão de fonte símbolo na especificação de TrueType, um esperaria esta codificação para conter códigos de caracteres da área de uso particular de Unicode.

Uma subtabela 4 de formato é uma matriz esparsa. Para acomodar as entradas de 64 K necessárias pelo Unicode de 16 bits padrão, subtabela Formatar 4 coleta vizinhos seqüências de caracteres em segmentos. Os segmentos são definidos pelo valor de código primeiro e último caracteres coberto por aquele intervalo de caracteres. A coleção de segmentos são armazenados na subtabela por um conjunto de matrizes paralelas: um para o caractere inicial do intervalo (startCount) e outro para o caractere final do intervalo (endCount). A matriz de segmento é uma classificação de um código de caractere potencial mapeamento, não o realmente mapeamento.

O mapeamento para um índice de glifo requer o uso de uma matriz terceiro paralela de subtabela chamada o idRangeOffset. Isso determina qual dos dois métodos são usados para calcular o índice de glifo final. O primeiro método usa um valor delta simples para calcular o índice de glifo do código de caractere. O segundo método usa uma pesquisa em uma tabela de identificação de glifo intermediário. Se o valor nesta tabela for zero, não há nenhum glifo; caso contrário, o valor é usado para o índice de glifo final do computador. A tabela de pesquisa é uma maneira eficiente do que representa uma coleção de códigos de caracteres não-contíguos que abrangem um segmento.

O saldo deste artigo aborda como obter índices de glifo TrueType de um arquivo de fonte TrueType. As seguintes suposições são feitas: a fonte TrueType está selecionada no controlador de domínio do aplicativo, a codificação de seqüência de caracteres atual é Unicode e o arquivo de fonte TrueType tem uma tabela de mapa de caracteres Unicode (subtabela "cmap" Formatar 4).

Observação : esta técnica para obter índices de glifo é aplicável ao Windows NT; no entanto, porque uma versão Unicode da função GetCharacterPlacement foi implementada, é geralmente desnecessário. Se seqüências de um aplicativo Windows 95 não são Unicode, ele pode chamar a função GetCharacterPlacementA para converter em índices de glifo em vez disso.

O código-fonte completo está no final deste artigo. Dentro do texto do artigo, são feitas várias referências ao código-fonte. Consulte o código-fonte exemplo para examinar as referências relevantes no seu contexto completo.

É provável e extremidades

Para trabalhar com os dados em um arquivo de fonte TrueType, um número de problemas de tipo de dados deve ser bem compreendido. Na especificação TrueType, todas as tabelas no arquivo de fonte são definidas como uma coleção de tipos de dados base. Os tipos de dados base também são definidos pela especificação mas eles correspondem bem para alguns tipos de dados base definidos pelo Windows Platform SDK.

O arquivo de fonte TrueType está embalados-byte, que significa que todos os tipos de dados ficam em um deslocamento de byte no arquivo. Bytes de preenchimento específicos estão incluídos no quaisquer definições de tabela onde aplicável a especificação. A maioria dos compiladores permitir e, às vezes, padrão para alinhamento de estrutura em diferentes de limites de byte. Isso significa que a definição de estruturas de linguagem "C" para imitar a definição de uma tabela pode não ser compatível.

Esse código de exemplo usa definições de estrutura sempre que possível representar tabelas. Para funcionar corretamente, o código deve ser compilado com byte alinhamento de estrutura, como é garantido pelo uso do código de exemplo de pragma pack.

Mesmo quando a remessa de byte é garantida, ler apenas as tabelas em uma estrutura está incorreto. Arquivos de fonte TrueType usam "Big Endian" ou estilo Motorola byte ordenação enquanto microprocessadores Intel usam a ordem de byte "Little Endian". Isso significa que todos os dados maiores do que um byte extraído de um arquivo de fonte TrueType deve ter os bytes trocado. A troca de bytes torna os dados compatível com microprocessadores Intel. As definições de macro SWAPWORD e SWAPLONG fornecem um recurso para fazer isso.

As definições

A tabela "cmap" de um arquivo de fonte TrueType consiste em subtabelas; cada um deles define uma codificação diferente. Para localizar as subtabelas, o código de exemplo definiu uma macro conveniente chamada CMAPHEADERSIZE. A macro é conveniente para cálculos de deslocamento para o início do diretório subtabela. Essa macro retorna o tamanho dos dois tipos de dados curto não assinado usado para armazenar a versão da tabela "cmap" e o número de subtabelas na tabela "cmap":
/*  CMAP table Data    From the TrueType Spec revision 1.66    USHORT  Table Version #    USHORT  Number of encoding tables*/ #define     CMAPHEADERSIZE  (sizeof(USHORT)*2)				
cada codificação subtabela tem uma entrada de diretório na tabela principal "cmap". Isso é representado no código-fonte por _CMapEncoding de definição de estrutura. Essa estrutura contém dois campos de identificação usados para distinguir cada subtabela e o offset do início da tabela "cmap" onde está a subtabela:
typedef struct _CMapEncoding{    USHORT  PlatformId;    USHORT  EncodingId;    ULONG   Offset;} CMAPENCODING;				
a função GetFontData na API Win32 leva um argumento DWORD único como o nome de tabela. Isso funciona porque a especificação de TrueType define um nome de tabela como uma seqüência de marca de quatro bytes. Para compactar corretamente o nome da tabela para o parâmetro DWORD da chamada de função GetFontData , o código de exemplo define uma macro chamada MAKETABLENAME. A macro funciona pela mudança seqüencialmente os quatro valores de bytes individuais da marca de nome de tabela em um tipo de dados DWORD:
// Macro to pack a TrueType table name into a DWORD.#define     MAKETABLENAME(ch1, ch2, ch3, ch4) (\     (((DWORD)(ch4)) << 24) | \     (((DWORD)(ch3)) << 16) | \     (((DWORD)(ch2)) << 8) | \     ((DWORD)(ch1)) \     )				
codificação Unicode A subtabela é marcada por um PlatformId de 3 e um SpecificId de 1. Essa codificação "3-1" é uma subtabela 4 de formato de acordo com a especificação TrueType. Definida no código fonte é uma estrutura, _CMap4, que corresponde a tipos de sete primeiras dados do subtabela Formatar 4 mais uma matriz simbólica de um unsigned short. A matriz representa o saldo da definição de subtabela que consiste em várias matrizes curtos não assinados. Incluindo o símbolo de matriz na definição de estrutura, um endereço conveniente para o início das matrizes curtos não assinados é definido. O símbolo de matriz, em seguida, pode ser usado para calcular os outros endereços de início de matriz, usando os deslocamentos da primeira matriz. Isso é útil quando converter um buffer de memória maior que contém uma subtabela completa para eliminar referência a uma das matrizes curtas não assinadas:
typedef struct _CMap4   // From the TrueType Spec. revision 1.66.{    USHORT format;          // Format number is set to 4.     USHORT length;          // Length in bytes.     USHORT version;         // Version number (starts at 0).    USHORT segCountX2;      // 2 x segCount    USHORT searchRange;     // 2 x (2**floor(log2(segCount)))    USHORT entrySelector;   // log2(searchRange/2)    USHORT rangeShift;      // 2 x segCount - searchRange    USHORT Arrays[1];       // Placeholder symbol for address of arrays. following.} CMAP4, *LPCMAP4;				

O processo

O código de exemplo implementa duas tarefas básicas: recuperação de uma subtabela Unicode "cmap" o arquivo de fonte e uma pesquisa de subtabela para encontrar um índice de glifo TrueType para um código de caractere Unicode.

Para recuperar dados da tabela de um arquivo de fonte TrueType fornecido um controlador de domínio, o código usa a função GetFontData . Esta função exige que o arquivo de fonte TrueType ser selecionado para o controlador de domínio. Para recuperar dados da tabela indexados por uma tabela de TrueType nomeada, o nome da marca de tabela de quatro bytes deve ser embalado em uma DWORD. Como só estamos interessados em obter dados da tabela "cmap", o código de exemplo define um DWORD global, dwCmapName, que vem com a marca "cmap". Todas as chamadas para a função GetFontData são codificadas para usar a variável global dwCmapName.

A função GetTTUnicodeCoverage é o código fonte para recuperar a Unicode "cmap" subtabela. Ele é declarado como:
BOOL GetTTUnicodeCoverage (     HDC hdc,            // DC with TT font.    LPCMAP4 pBuffer,    // Properly allocated buffer.    DWORD cbSize,       // Size of properly allocated buffer.    DWORD *pcbNeeded    // Size of buffer needed.    )
esta função recupera a subtabela Unicode completa da tabela de "cmap" do TrueType. Se chamado com um buffer é muito pequeno (isto é, tamanho de zero) como declarado por cbSize ou com um parâmetro NULL para o parâmetro pBuffer, ele falhar e retorna FALSO. Quando falhar dessa maneira, ela calcula e retorna o tamanho do buffer necessário no parâmetro pcbNeeded. Quando a função obtiver êxito, o parâmetro pBuffer é preenchido e o número de bytes copiados é colocado no parâmetro pcbNeeded.

Essa função primeiro procura por uma subtabela que pode conter um codificação, Unicode em uma codificação de "3-1" ou uma codificação de "0-3". Esses são Formatar 4 subtabelas conforme definido no capítulo de tipo de dados "cmap" da especificação TrueType.

Se a função localizar uma codificação Unicode, ele recupera os sete primeiras elementos de subtabela Formatar 4 usando a função GetFontFormat4Header . O código, em seguida, calcula o tamanho do buffer que é necessário para retornar a subtabela Unicode inteira. Se o buffer é muito pequeno ou não fornecido, o tamanho é retornado ao chamador, de modo que eles possam alocar um buffer apropriadamente dimensionado e lembre-se a função.

Se o buffer fornecido pelo chamador for grande o suficiente, o código de exemplo, em seguida, usa a função GetFontFormat4Subtable para recuperar subtabela inteira. Esta função adequadamente reordena os bytes para acomodar microprocessadores Intel. Se a recuperação subtabela foi bem-sucedida, o resultado será copiado para o buffer do chamador. Se não foi bem-sucedida, o código não tiver modificado o buffer do usuário e pode retornar com segurança falha. Definindo o parâmetro necessário de bytes para zero, o código de exemplo pode indicar que ele não copiar bytes para o buffer e pode distinguir essa falha da falta de espaço em buffer.

Depois que tenha sido obtida subtabela Unicode, ele pode ser usado para recuperar os índices de glifo para um código de caractere ou para implementar um número de outras funções úteis.

Converter um código de caractere Unicode em um índice de glifo é realizada na função de GetTTUnicodeGlyphIndex dos códigos de exemplo:
USHORT GetTTUnicodeGlyphIndex (    HDC hdc,        // DC with a TrueType font selected.    USHORT ch       // Unicode character to convert to Index.    )
esta função tem uma interface mais simples, exigindo somente o identificador para um controlador de domínio, hdc, que contém a fonte TrueType e o código do caractere Unicode converter ch. A função retorna o índice de glifo para ch quando for bem-sucedida. Se o código de caractere Unicode não está localizado na codificação (ou seja, se houver nenhum glifo) o valor de índice de glifo ausente de zero será retornado.

Primeiro, ele recupera subtabela Unicode alocar um buffer e chamando a função GetTTUnicodeCoverage . Se ocorrer um erro, o código de exemplo falhará a chamada retornando o índice de glifo ausente. Neste ponto, falha pode significar que o controlador de domínio não contém uma fonte TrueType, ou a fonte TrueType não contém uma subtabela Unicode adequada.

Em seguida, o código tenta localizar o código do caractere Unicode na codificação. A pesquisa é realizada pela referência subtabela Formatar 4 o capítulo de tipo de dados "cmap" da especificação de TrueType. Os segmentos de código da subtabela linearmente são pesquisados pela função FindFormat4Segment . Se nenhum segmento de código colchetes esse código de caractere, em seguida, o arquivo de fonte não contém uma codificação e, portanto, não há nenhum glifo. O código, em seguida, retorna o índice de glifo ausente.

A pesquisa do índice de glifo ocorre na última metade da função GetTTUnicodeGlyphIndex . Há dois métodos de pesquisar o índice de glifo de um glifo específico. Ambos os casos usam a matriz idRangeOffset examinando o valor no índice ordinal do segmento em que o código do caractere foi encontrado.

No primeiro caso, se o valor localizado no índice de segmento da matriz idRangeOffset for zero, o código dereferences a matriz idDelta com o mesmo índice de matriz e converte o índice de glifo usando módulo aritmética:
// Per TT spec, if the RangeOffset is zero,    if ( idRangeOffset[iSegment] == 0)    {        // calculate the glyph index directly.        GlyphIndex = (idDelta[iSegment] + ch) % 65536;    }    else    {     ...    }				
no segundo caso, o valor localizado no índice de segmento ordinal é parte de um índice em uma tabela de pesquisa para índices de glifo. Com base no pedido e na localização de matrizes a subtabelas, um truque de indexação obscuro usando o endereço do valor no elemento idRangeOffset retorna um valor de identificação intermediário. O mecanismo de indexação é explicado com Formatar 4 subtabela capítulo a especificação TrueType. Se diferente de zero, esse valor é, em seguida, adicionado ao valor idDelta e convertido com módulo aritmética; caso contrário, não há nenhum glifo e o índice de glifo ausente é retornado:
// Per TT spec, if the RangeOffset is zero,    if ( idRangeOffset[iSegment] == 0)    {     ...    }    else    {        // otherwise, use the glyph ID array to get the index.        USHORT idResult;    //Intermediate ID calc.        idResult = *(            idRangeOffset[iSegment]/2 +             (ch - startCount[iSegment]) +             &idRangeOffset[iSegment]            );  // Indexing equation from TT spec.        if (idResult)            // Per TT spec, nonzero means there is a glyph.            GlyphIndex = (idDelta[iSegment] + idResult) % 65536;        else            // Otherwise, return the missing glyph.            GlyphIndex = 0;    }				
algumas outras funções úteis podem ser derivadas de decodificação de subtabela Unicode. Por exemplo este código de exemplo implementa uma função chamada:
USHORT GetTTUnicodeCharCount (     HDC hdc    )
esta função soma os caracteres cobertos por cada segmento na subtabela formato 4 para encontrar o número total de códigos de caracteres Unicode representadas no arquivo de fonte TrueType. No entanto, observe que esta função deve testar cada código de caractere individual para um mapeamento se um segmento em questão usa a matriz de identificação de glifo em vez de sendo contínua.

Também é instrutivo Observe que a contagem de códigos de caracteres Unicode que são mapeados para um glifo não é necessariamente equivalente ao número de glifos contidas no arquivo de fonte. Pode haver glifos menos se a codificação Unicode mapeia vários códigos de caracteres para o mesmo glifo. Também pode haver mais glifos no arquivo de fonte que sugere o mapeamento. Por exemplo: tabelas de TrueType abrir (agora chamado OpenType Layout) definem as substituições de índice de glifo para vários, glifos alternativos.

A função GetTTUnicodeGlyphIndex também pode ser usada para implementar uma função para determinar se uma determinada fonte TrueType contém um glifo para um determinado código de caractere Unicode. Basta chamar a função GetTTUnicodeGlyphIndex com o código do caractere e testar o retorno para equivalência com o índice de glifo ausente (um valor igual a zero).

Uma palavra sobre implementação

Este código de exemplo foi escrito para maior clareza de explicação. Ela não é otimizada para uso repetido porque aloca e recupera TrueType tabelas sempre que uma função pública for chamada. Reais de aplicativos, uma boa otimização seria armazenar em cache a codificação Unicode para o arquivo de fonte TrueType, desde que ele permanece no controlador de domínio. Um aplicativo pode comparar para ver se a fonte selecionada em um controlador de domínio é o mesmo arquivo de fonte TrueType armazenando em cache e comparando o valor de soma de verificação do arquivo de fonte. Essa soma de verificação está localizada no diretório de tabela do arquivo de fonte TrueType no início do arquivo e pode ser recuperada usando a função GetFontData . Consulte discussão a especificação TrueType de "A tabela Directory" no capítulo de tipos de dados para localizar a soma de verificação de um arquivo de fonte.

Código-fonte concluído

#pragma pack(1)     // for byte alignment// We need byte alignment to be structure compatible with the// contents of a TrueType font file// Macros to swap from Big Endian to Little Endian#define SWAPWORD(x) MAKEWORD( \     HIBYTE(x), \     LOBYTE(x) \     )#define SWAPLONG(x) MAKELONG( \     SWAPWORD(HIWORD(x)), \     SWAPWORD(LOWORD(x)) \     )typedef struct _CMap4   // From the TrueType Spec. revision 1.66{    USHORT format;          // Format number is set to 4.     USHORT length;          // Length in bytes.     USHORT version;         // Version number (starts at 0).    USHORT segCountX2;      // 2 x segCount.    USHORT searchRange;     // 2 x (2**floor(log2(segCount)))    USHORT entrySelector;   // log2(searchRange/2)    USHORT rangeShift;      // 2 x segCount - searchRange    USHORT Arrays[1];       // Placeholder symbol for address of arrays following} CMAP4, *LPCMAP4;/*  CMAP table Data    From the TrueType Spec revision 1.66    USHORT  Table Version #    USHORT  Number of encoding tables*/ #define     CMAPHEADERSIZE  (sizeof(USHORT)*2)/*  ENCODING entry Data aka CMAPENCODING    From the TrueType Spec revision 1.66    USHORT  Platform Id    USHORT  Platform Specific Encoding Id    ULONG   Byte Offset from beginning of table*/ #define     ENCODINGSIZE    (sizeof(USHORT)*2 + sizeof(ULONG))typedef struct _CMapEncoding{    USHORT  PlatformId;    USHORT  EncodingId;    ULONG   Offset;} CMAPENCODING;// Macro to pack a TrueType table name into a DWORD#define     MAKETABLENAME(ch1, ch2, ch3, ch4) (\     (((DWORD)(ch4)) << 24) | \     (((DWORD)(ch3)) << 16) | \     (((DWORD)(ch2)) << 8) | \     ((DWORD)(ch1)) \     )/* public functions */ USHORT GetTTUnicodeGlyphIndex(HDC hdc, USHORT ch);USHORT GetTTUnicodeCharCount(HDC hdc);// DWORD packed four letter table name for each GetFontData()// function call when working with the CMAP TrueType tableDWORD dwCmapName = MAKETABLENAME( 'c','m','a','p' );USHORT *GetEndCountArray(LPBYTE pBuff){    return (USHORT *)(pBuff + 7 * sizeof(USHORT));  // Per TT spec}USHORT *GetStartCountArray(LPBYTE pBuff){    DWORD   segCount = ((LPCMAP4)pBuff)->segCountX2/2;    return (USHORT *)( pBuff +         8 * sizeof(USHORT) +        // 7 header + 1 reserved USHORT        segCount*sizeof(USHORT) );  // Per TT spec}USHORT *GetIdDeltaArray(LPBYTE pBuff){    DWORD   segCount = ((LPCMAP4)pBuff)->segCountX2/2;    return (USHORT *)( pBuff +         8 * sizeof(USHORT) +        // 7 header + 1 reserved USHORT        segCount * 2 * sizeof(USHORT) );    // Per TT spec}USHORT *GetIdRangeOffsetArray(LPBYTE pBuff){    DWORD   segCount = ((LPCMAP4)pBuff)->segCountX2/2;    return (USHORT *)( pBuff +         8 * sizeof(USHORT) +        // 7 header + 1 reserved USHORT        segCount * 3 * sizeof(USHORT) );    // Per TT spec}void SwapArrays( LPCMAP4 pFormat4 ){    DWORD   segCount = pFormat4->segCountX2/2;  // Per TT Spec    DWORD   i;    USHORT  *pGlyphId,             *pEndOfBuffer,             *pstartCount    = GetStartCountArray( (LPBYTE)pFormat4 ),             *pidDelta       = GetIdDeltaArray( (LPBYTE)pFormat4 ),             *pidRangeOffset = GetIdRangeOffsetArray( (LPBYTE)pFormat4 ),             *pendCount      = GetEndCountArray( (LPBYTE)pFormat4 );    // Swap the array elements for Intel.    for (i=0; i < segCount; i++)    {        pendCount[i] = SWAPWORD(pendCount[i]);        pstartCount[i] = SWAPWORD(pstartCount[i]);        pidDelta[i] = SWAPWORD(pidDelta[i]);        pidRangeOffset[i] = SWAPWORD(pidRangeOffset[i]);    }    // Swap the Glyph Id array    pGlyphId = pidRangeOffset + segCount;   // Per TT spec    pEndOfBuffer = (USHORT*)((LPBYTE)pFormat4 + pFormat4->length);    for (;pGlyphId < pEndOfBuffer; pGlyphId++)    {        *pGlyphId = SWAPWORD(*pGlyphId);    }} /* end of function SwapArrays */ BOOL GetFontEncoding (     HDC hdc,     CMAPENCODING * pEncoding,     int iEncoding     )/*    Note for this function to work correctly, structures must     have byte alignment.*/ {    DWORD   dwResult;    BOOL    fSuccess = TRUE;    // Get the structure data from the TrueType font    dwResult = GetFontData (         hdc,         dwCmapName,         CMAPHEADERSIZE + ENCODINGSIZE*iEncoding,         pEncoding,         sizeof(CMAPENCODING) );    fSuccess = (dwResult == sizeof(CMAPENCODING));    // swap the Platform Id for Intel    pEncoding->PlatformId = SWAPWORD(pEncoding->PlatformId);    // swap the Specific Id for Intel    pEncoding->EncodingId = SWAPWORD(pEncoding->EncodingId);    // swap the subtable offset for Intel    pEncoding->Offset = SWAPLONG(pEncoding->Offset);    return fSuccess;} /* end of function GetFontEncoding */ BOOL GetFontFormat4Header (     HDC hdc,     LPCMAP4 pFormat4,     DWORD dwOffset     )/*    Note for this function to work correctly, structures must     have byte alignment.*/ {    BOOL    fSuccess = TRUE;    DWORD   dwResult;    int     i;    USHORT  *pField;    // Loop and Alias a writeable pointer to the field of interest    pField = (USHORT *)pFormat4;    for (i=0; i < 7; i++)    {        // Get the field from the subtable        dwResult = GetFontData (             hdc,             dwCmapName,             dwOffset + sizeof(USHORT)*i,             pField,             sizeof(USHORT) );                // swap it to make it right for Intel.        *pField = SWAPWORD(*pField);        // move on to the next        pField++;        // accumulate our success        fSuccess = (dwResult == sizeof(USHORT)) && fSuccess;    }    return fSuccess;} /* end of function GetFontFormat4Header */ BOOL GetFontFormat4Subtable (     HDC hdc,                    // DC with TrueType font    LPCMAP4 pFormat4Subtable,   // destination buffer    DWORD   dwOffset            // Offset within font    ){    DWORD   dwResult;    USHORT  length;        // Retrieve the header values in swapped order    if (!GetFontFormat4Header ( hdc,         pFormat4Subtable,         dwOffset ))    {        return FALSE;    }    // Get the rest of the table    length = pFormat4Subtable->length - (7 * sizeof(USHORT));    dwResult = GetFontData( hdc,         dwCmapName,        dwOffset + 7 * sizeof(USHORT),      // pos of arrays        (LPBYTE)pFormat4Subtable->Arrays,   // destination        length );           if ( dwResult != length)    {        // We really shouldn't ever get here        return FALSE;    }        // Swamp the arrays    SwapArrays( pFormat4Subtable );    return TRUE;}USHORT GetFontFormat4CharCount (    LPCMAP4 pFormat4    // pointer to a valid Format4 subtable    ){    USHORT  i,            *pendCount = GetEndCountArray((LPBYTE) pFormat4),            *pstartCount = GetStartCountArray((LPBYTE) pFormat4),            *idRangeOffset = GetIdRangeOffsetArray( (LPBYTE) pFormat4 );    // Count the # of glyphs    USHORT nGlyphs = 0;    if ( pFormat4 == NULL )        return 0;    // by adding up the coverage of each segment    for (i=0; i < (pFormat4->segCountX2/2); i++)    {        if ( idRangeOffset[i] == 0)        {            // if per the TT spec, the idRangeOffset element is zero,            // all of the characters in this segment exist.            nGlyphs += pendCount[i] - pstartCount[i] +1;        }        else        {            // otherwise we have to test for glyph existence for            // each character in the segment.            USHORT idResult;    //Intermediate id calc.            USHORT ch;            for (ch = pstartCount[i]; ch <= pendCount[i]; ch++)            {                // determine if a glyph exists                idResult = *(                    idRangeOffset[i]/2 +                     (ch - pstartCount[i]) +                     &idRangeOffset[i]                    );  // indexing equation from TT spec                if (idResult != 0)                    // Yep, count it.                    nGlyphs++;            }        }    }    return nGlyphs;} /* end of function GetFontFormat4CharCount */ BOOL GetTTUnicodeCoverage (     HDC hdc,            // DC with TT font    LPCMAP4 pBuffer,    // Properly allocated buffer    DWORD cbSize,       // Size of properly allocated buffer    DWORD *pcbNeeded    // size of buffer needed    )/*    if cbSize is to small or zero, or if pBuffer is NULL the function    will fail and return the required buffer size in *pcbNeeded.    if another error occurs, the function will fail and *pcbNeeded will    be zero.    When the function succeeds, *pcbNeeded contains the number of bytes     copied to pBuffer.*/ {    USHORT          nEncodings;     // # of encoding in the TT font    CMAPENCODING    Encoding;       // The current encoding    DWORD           dwResult;    DWORD           i,                     iUnicode;       // The Unicode encoding    CMAP4           Format4;        // Unicode subtable format    LPCMAP4         pFormat4Subtable;   // Working buffer for subtable    // Get the number of subtables in the CMAP table from the CMAP header    // The # of subtables is the second USHORT in the CMAP table, per the TT Spec.    dwResult = GetFontData ( hdc, dwCmapName, sizeof(USHORT), &nEncodings, sizeof(USHORT) );    nEncodings = SWAPWORD(nEncodings);        if ( dwResult != sizeof(USHORT) )    {        // Something is wrong, we probably got GDI_ERROR back        // Probably this means that the Device Context does not have        // a TrueType font selected into it.        return FALSE;    }    // Get the encodings and look for a Unicode Encoding    iUnicode = nEncodings;    for (i=0; i < nEncodings; i++)    {        // Get the encoding entry for each encoding        if (!GetFontEncoding ( hdc, &Encoding, i ))        {            *pcbNeeded = 0;            return FALSE;        }                // Take note of the Unicode encoding.        //         // A Unicode encoding per the TrueType specification has a        // Platform Id of 3 and a Platform specific encoding id of 1        // Note that Symbol fonts are supposed to have a Platform Id of 3         // and a specific id of 0. If the TrueType spec. suggestions were        // followed then the Symbol font's Format 4 encoding could also        // be considered Unicode because the mapping would be in the        // Private Use Area of Unicode. We assume this here and allow         // Symbol fonts to be interpreted. If they do not contain a         // Format 4, we bail later. If they do not have a Unicode         // character mapping, we'll get wrong results.        // Code could infer from the coverage whether 3-0 fonts are         // Unicode or not by examining the segments for placement within        // the Private Use Area Subrange.        if (Encoding.PlatformId == 3 &&             (Encoding.EncodingId == 1 || Encoding.EncodingId == 0) )        {            iUnicode = i;       // Set the index to the Unicode encoding        }    }    // index out of range means failure to find a Unicode mapping    if (iUnicode >= nEncodings)    {        // No Unicode encoding found.        *pcbNeeded = 0;        return FALSE;    }    // Get the header entries(first 7 USHORTs) for the Unicode encoding.    if ( !GetFontFormat4Header ( hdc, &Format4, Encoding.Offset ) )    {        *pcbNeeded = 0;        return FALSE;    }    // Check to see if we retrieved a Format 4 table     if ( Format4.format != 4 )    {        // Bad, subtable is not format 4, bail.        // This could happen if the font is corrupt        // It could also happen if there is a new font format we        // don't understand.        *pcbNeeded = 0;        return FALSE;    }    // Figure buffer size and tell caller if buffer to small    *pcbNeeded = Format4.length;        if (*pcbNeeded > cbSize || pBuffer == NULL)    {        // Either test indicates caller needs to know        // the buffer size and the parameters are not setup        // to continue.        return FALSE;    }    // allocate a full working buffer    pFormat4Subtable = (LPCMAP4)malloc ( Format4.length );    if ( pFormat4Subtable == NULL)    {        // Bad things happening if we can't allocate memory        *pcbNeeded = 0;        return FALSE;    }    // get the entire subtable    if (!GetFontFormat4Subtable ( hdc, pFormat4Subtable, Encoding.Offset ))    {        // Bad things happening if we can't allocate memory        *pcbNeeded = 0;        return FALSE;    }    // Copy the retrieved table into the buffer    CopyMemory( pBuffer,         pFormat4Subtable,         pFormat4Subtable->length );    free ( pFormat4Subtable );    return TRUE;} /* end of function GetTTUnicodeCoverage */ BOOL FindFormat4Segment (    LPCMAP4 pTable,     // a valid Format4 subtable buffer    USHORT ch,          // Unicode character to search for    USHORT *piSeg       // out: index of segment containing ch    )/*    if the Unicode character ch is not contained in one of the     segments the function returns FALSE.    if the Unicode character ch is found in a segment, the index    of the segment is placed in*piSeg and the function returns    TRUE.*/ {    USHORT  i,             segCount = pTable->segCountX2/2;    USHORT  *pendCount = GetEndCountArray((LPBYTE) pTable);    USHORT  *pstartCount = GetStartCountArray((LPBYTE) pTable);    // Find segment that could contain the Unicode character code    for (i=0; i < segCount && pendCount[i] < ch; i++);    // We looked in them all, ch not there    if (i >= segCount)        return FALSE;        // character code not within the range of the segment    if (pstartCount[i] > ch)        return FALSE;    // this segment contains the character code    *piSeg = i;    return TRUE;} /* end of function FindFormat4Segment */ USHORT GetTTUnicodeCharCount (     HDC hdc    )/*    Returns the number of Unicode character glyphs that     are in the TrueType font that is selected into the hdc.*/ {    LPCMAP4 pUnicodeCMapTable;    USHORT  cChar;    DWORD   dwSize;    // Get the Unicode CMAP table from the TT font    GetTTUnicodeCoverage( hdc, NULL, 0, &dwSize );    pUnicodeCMapTable = (LPCMAP4)malloc( dwSize );    if (!GetTTUnicodeCoverage( hdc, pUnicodeCMapTable, dwSize, &dwSize ))    {        // possibly no Unicode cmap, not a TT font selected,...        free( pUnicodeCMapTable );        return 0;    }    cChar = GetFontFormat4CharCount( pUnicodeCMapTable );    free( pUnicodeCMapTable );    return cChar;} /* end of function GetTTUnicodeCharCount */ USHORT GetTTUnicodeGlyphIndex (    HDC hdc,        // DC with a TrueType font selected    USHORT ch       // Unicode character to convert to Index    )/*    When the TrueType font contains a glyph for ch, the    function returns the glyph index for that character.    If an error occurs, or there is no glyph for ch, the    function will return the missing glyph index of zero.*/ {    LPCMAP4 pUnicodeCMapTable;    DWORD   dwSize;    USHORT  iSegment;    USHORT  *idRangeOffset;    USHORT  *idDelta;    USHORT  *startCount;    USHORT  GlyphIndex = 0;     // Initialize to missing glyph    // How big a buffer do we need for Unicode CMAP?    GetTTUnicodeCoverage( hdc, NULL, 0, &dwSize );    pUnicodeCMapTable = (LPCMAP4)malloc( dwSize );    if (!GetTTUnicodeCoverage( hdc, pUnicodeCMapTable, dwSize, &dwSize ))    {        // Either no Unicode cmap, or some other error occurred        // like font in DC is not TT.        free( pUnicodeCMapTable );        return 0;       // return missing glyph on error    }    // Find the cmap segment that has the character code.    if (!FindFormat4Segment( pUnicodeCMapTable, ch, &iSegment ))    {        free( pUnicodeCMapTable );        return 0;       // ch not in cmap, return missing glyph    }    // Get pointers to the cmap data    idRangeOffset = GetIdRangeOffsetArray( (LPBYTE) pUnicodeCMapTable );    idDelta = GetIdDeltaArray( (LPBYTE) pUnicodeCMapTable );    startCount = GetStartCountArray( (LPBYTE) pUnicodeCMapTable );        // Per TT spec, if the RangeOffset is zero,    if ( idRangeOffset[iSegment] == 0)    {        // calculate the glyph index directly        GlyphIndex = (idDelta[iSegment] + ch) % 65536;    }    else    {        // otherwise, use the glyph id array to get the index        USHORT idResult;    //Intermediate id calc.        idResult = *(            idRangeOffset[iSegment]/2 +             (ch - startCount[iSegment]) +             &idRangeOffset[iSegment]            );  // indexing equation from TT spec        if (idResult)            // Per TT spec, nonzero means there is a glyph            GlyphIndex = (idDelta[iSegment] + idResult) % 65536;        else            // otherwise, return the missing glyph            GlyphIndex = 0;    }    free( pUnicodeCMapTable );    return GlyphIndex;} /* end of function GetTTUnicodeGlyphIndex */ 				
Referências
Para obter mais informações sobre o padrão Unicode consulte:
O Unicode Consortium. O padrão Unicode, versão 2.0. Leitura, MA, Addison-Wesley Developers pressione, 1996. ISBN 0-201-48345-9.

Na internet: The Unicode Consortium (http://www.unicode.org)
Para obter informações adicionais, clique no número abaixo para ler o artigo na Base de dados de Conhecimento da Microsoft:
210341INFO: Suporte a Unicode no Windows 95 e Windows 98
Para obter mais informações sobre a especificação de TrueType consulte:
Microsoft TrueType Specifications (http://www.microsoft.com/typography/tt/tt.htm)

Também disponível do CD do Microsoft Developer Network Library em especificações.

Aviso: este artigo foi traduzido automaticamente

Propriedades

ID do Artigo: 241020 - Última Revisão: 12/05/2015 15:46:34 - Revisão: 2.5

Microsoft Windows 95, Microsoft Windows 98 Standard Edition, Microsoft Windows 98 Second Edition

  • kbnosurvey kbarchive kbmt kbdswgdi2003swept kbfont kbgdi kbhowto KB241020 KbMtpt
Comentários