gdi32: Move GetCharacterPlacementW to text.c.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
bf4084b49c
commit
6616da70be
|
@ -7101,187 +7101,6 @@ GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int kern_pair(const KERNINGPAIR *kern, int count, WCHAR c1, WCHAR c2)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (kern[i].wFirst == c1 && kern[i].wSecond == c2)
|
||||
return kern[i].iKernAmount;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int *kern_string(HDC hdc, const WCHAR *str, int len, int *kern_total)
|
||||
{
|
||||
int i, count;
|
||||
KERNINGPAIR *kern = NULL;
|
||||
int *ret;
|
||||
|
||||
*kern_total = 0;
|
||||
|
||||
ret = heap_alloc(len * sizeof(*ret));
|
||||
if (!ret) return NULL;
|
||||
|
||||
count = GetKerningPairsW(hdc, 0, NULL);
|
||||
if (count)
|
||||
{
|
||||
kern = heap_alloc(count * sizeof(*kern));
|
||||
if (!kern)
|
||||
{
|
||||
heap_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GetKerningPairsW(hdc, count, kern);
|
||||
}
|
||||
|
||||
for (i = 0; i < len - 1; i++)
|
||||
{
|
||||
ret[i] = kern_pair(kern, count, str[i], str[i + 1]);
|
||||
*kern_total += ret[i];
|
||||
}
|
||||
|
||||
ret[len - 1] = 0; /* no kerning for last element */
|
||||
|
||||
heap_free(kern);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* GetCharacterPlacementW [GDI32.@]
|
||||
*
|
||||
* Retrieve information about a string. This includes the width, reordering,
|
||||
* Glyphing and so on.
|
||||
*
|
||||
* RETURNS
|
||||
*
|
||||
* The width and height of the string if successful, 0 if failed.
|
||||
*
|
||||
* BUGS
|
||||
*
|
||||
* All flags except GCP_REORDER are not yet implemented.
|
||||
* Reordering is not 100% compliant to the Windows BiDi method.
|
||||
* Caret positioning is not yet implemented for BiDi.
|
||||
* Classes are not yet implemented.
|
||||
*
|
||||
*/
|
||||
DWORD WINAPI
|
||||
GetCharacterPlacementW(
|
||||
HDC hdc, /* [in] Device context for which the rendering is to be done */
|
||||
LPCWSTR lpString, /* [in] The string for which information is to be returned */
|
||||
INT uCount, /* [in] Number of WORDS in string. */
|
||||
INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
|
||||
GCP_RESULTSW *lpResults, /* [in/out] A pointer to a GCP_RESULTSW struct */
|
||||
DWORD dwFlags /* [in] Flags specifying how to process the string */
|
||||
)
|
||||
{
|
||||
DWORD ret=0;
|
||||
SIZE size;
|
||||
UINT i, nSet;
|
||||
int *kern = NULL, kern_total = 0;
|
||||
|
||||
TRACE("%s, %d, %d, 0x%08x\n",
|
||||
debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
|
||||
|
||||
if (!uCount)
|
||||
return 0;
|
||||
|
||||
if (!lpResults)
|
||||
return GetTextExtentPoint32W(hdc, lpString, uCount, &size) ? MAKELONG(size.cx, size.cy) : 0;
|
||||
|
||||
TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
|
||||
"lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
|
||||
lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
|
||||
lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
|
||||
lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
|
||||
|
||||
if (dwFlags & ~(GCP_REORDER | GCP_USEKERNING))
|
||||
FIXME("flags 0x%08x ignored\n", dwFlags);
|
||||
if (lpResults->lpClass)
|
||||
FIXME("classes not implemented\n");
|
||||
if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
|
||||
FIXME("Caret positions for complex scripts not implemented\n");
|
||||
|
||||
nSet = (UINT)uCount;
|
||||
if (nSet > lpResults->nGlyphs)
|
||||
nSet = lpResults->nGlyphs;
|
||||
|
||||
/* return number of initialized fields */
|
||||
lpResults->nGlyphs = nSet;
|
||||
|
||||
if (!(dwFlags & GCP_REORDER))
|
||||
{
|
||||
/* Treat the case where no special handling was requested in a fastpath way */
|
||||
/* copy will do if the GCP_REORDER flag is not set */
|
||||
if (lpResults->lpOutString)
|
||||
memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
|
||||
|
||||
if (lpResults->lpOrder)
|
||||
{
|
||||
for (i = 0; i < nSet; i++)
|
||||
lpResults->lpOrder[i] = i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
|
||||
nSet, lpResults->lpOrder, NULL, NULL );
|
||||
}
|
||||
|
||||
if (dwFlags & GCP_USEKERNING)
|
||||
{
|
||||
kern = kern_string(hdc, lpString, nSet, &kern_total);
|
||||
if (!kern)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: Will use the placement chars */
|
||||
if (lpResults->lpDx)
|
||||
{
|
||||
int c;
|
||||
for (i = 0; i < nSet; i++)
|
||||
{
|
||||
if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
|
||||
{
|
||||
lpResults->lpDx[i] = c;
|
||||
if (dwFlags & GCP_USEKERNING)
|
||||
lpResults->lpDx[i] += kern[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
|
||||
{
|
||||
int pos = 0;
|
||||
|
||||
lpResults->lpCaretPos[0] = 0;
|
||||
for (i = 0; i < nSet - 1; i++)
|
||||
{
|
||||
if (dwFlags & GCP_USEKERNING)
|
||||
pos += kern[i];
|
||||
|
||||
if (GetTextExtentPoint32W(hdc, &lpString[i], 1, &size))
|
||||
lpResults->lpCaretPos[i + 1] = (pos += size.cx);
|
||||
}
|
||||
}
|
||||
|
||||
if (lpResults->lpGlyphs)
|
||||
GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
|
||||
|
||||
if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
|
||||
ret = MAKELONG(size.cx + kern_total, size.cy);
|
||||
|
||||
heap_free(kern);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* GetCharABCWidthsFloatA [GDI32.@]
|
||||
*
|
||||
|
|
|
@ -159,23 +159,6 @@ static inline BOOL is_bitmapobj_dib( const BITMAPOBJ *bmp )
|
|||
return bmp->dib.dsBmih.biSize != 0;
|
||||
}
|
||||
|
||||
/* bidi.c */
|
||||
|
||||
/* Wine_GCPW Flags */
|
||||
/* Directionality -
|
||||
* LOOSE means taking the directionality of the first strong character, if there is found one.
|
||||
* FORCE means the paragraph direction is forced. (RLE/LRE)
|
||||
*/
|
||||
#define WINE_GCPW_FORCE_LTR 0
|
||||
#define WINE_GCPW_FORCE_RTL 1
|
||||
#define WINE_GCPW_LOOSE_LTR 2
|
||||
#define WINE_GCPW_LOOSE_RTL 3
|
||||
#define WINE_GCPW_DIR_MASK 3
|
||||
#define WINE_GCPW_LOOSE_MASK 2
|
||||
|
||||
extern BOOL BIDI_Reorder( HDC hDC, LPCWSTR lpString, INT uCount, DWORD dwFlags, DWORD dwWineGCP_Flags,
|
||||
LPWSTR lpOutString, INT uCountOut, UINT *lpOrder, WORD **lpGlyphs, INT* cGlyphs ) DECLSPEC_HIDDEN;
|
||||
|
||||
/* bitblt.c */
|
||||
extern DWORD convert_bits( const BITMAPINFO *src_info, struct bitblt_coords *src,
|
||||
BITMAPINFO *dst_info, struct gdi_image_bits *bits ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
/*
|
||||
* GDI text handling
|
||||
*
|
||||
* Copyright 2003 Shachar Shemesh
|
||||
* Copyright 1993 Alexandre Julliard
|
||||
* Copyright 1997 Alex Korobka
|
||||
* Copyright 2002,2003 Shachar Shemesh
|
||||
* Copyright 2007 Maarten Lankhorst
|
||||
* Copyright 2010 CodeWeavers, Aric Stewart
|
||||
*
|
||||
|
@ -42,6 +44,8 @@
|
|||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wingdi.h"
|
||||
|
@ -49,12 +53,23 @@
|
|||
#include "usp10.h"
|
||||
#include "wine/debug.h"
|
||||
#include "gdi_private.h"
|
||||
#include "ntgdi_private.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(bidi);
|
||||
|
||||
/* HELPER FUNCTIONS AND DECLARATIONS */
|
||||
|
||||
/* Wine_GCPW Flags */
|
||||
/* Directionality -
|
||||
* LOOSE means taking the directionality of the first strong character, if there is found one.
|
||||
* FORCE means the paragraph direction is forced. (RLE/LRE)
|
||||
*/
|
||||
#define WINE_GCPW_FORCE_LTR 0
|
||||
#define WINE_GCPW_FORCE_RTL 1
|
||||
#define WINE_GCPW_LOOSE_LTR 2
|
||||
#define WINE_GCPW_LOOSE_RTL 3
|
||||
#define WINE_GCPW_DIR_MASK 3
|
||||
#define WINE_GCPW_LOOSE_MASK 2
|
||||
|
||||
#define odd(x) ((x) & 1)
|
||||
|
||||
extern const unsigned short bidi_direction_table[] DECLSPEC_HIDDEN;
|
||||
|
@ -324,18 +339,16 @@ static void BidiLines(int baselevel, LPWSTR pszOutLine, LPCWSTR pszLine, const W
|
|||
*
|
||||
* Returns TRUE if reordering was required and done.
|
||||
*/
|
||||
BOOL BIDI_Reorder(
|
||||
HDC hDC, /*[in] Display DC */
|
||||
LPCWSTR lpString, /* [in] The string for which information is to be returned */
|
||||
INT uCount, /* [in] Number of WCHARs in string. */
|
||||
DWORD dwFlags, /* [in] GetCharacterPlacement compatible flags specifying how to process the string */
|
||||
DWORD dwWineGCP_Flags, /* [in] Wine internal flags - Force paragraph direction */
|
||||
LPWSTR lpOutString, /* [out] Reordered string */
|
||||
INT uCountOut, /* [in] Size of output buffer */
|
||||
UINT *lpOrder, /* [out] Logical -> Visual order map */
|
||||
WORD **lpGlyphs, /* [out] reordered, mirrored, shaped glyphs to display */
|
||||
INT *cGlyphs /* [out] number of glyphs generated */
|
||||
)
|
||||
static BOOL BIDI_Reorder( HDC hDC, /* [in] Display DC */
|
||||
LPCWSTR lpString, /* [in] The string for which information is to be returned */
|
||||
INT uCount, /* [in] Number of WCHARs in string. */
|
||||
DWORD dwFlags, /* [in] GetCharacterPlacement compatible flags */
|
||||
DWORD dwWineGCP_Flags, /* [in] Wine internal flags - Force paragraph direction */
|
||||
LPWSTR lpOutString, /* [out] Reordered string */
|
||||
INT uCountOut, /* [in] Size of output buffer */
|
||||
UINT *lpOrder, /* [out] Logical -> Visual order map */
|
||||
WORD **lpGlyphs, /* [out] reordered, mirrored, shaped glyphs to display */
|
||||
INT *cGlyphs ) /* [out] number of glyphs generated */
|
||||
{
|
||||
WORD *chartype = NULL;
|
||||
BYTE *levels = NULL;
|
||||
|
@ -697,3 +710,174 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags, const RECT *rect,
|
|||
HeapFree( GetProcessHeap(), 0, glyphs );
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kern_pair( const KERNINGPAIR *kern, int count, WCHAR c1, WCHAR c2 )
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (kern[i].wFirst == c1 && kern[i].wSecond == c2)
|
||||
return kern[i].iKernAmount;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int *kern_string( HDC hdc, const WCHAR *str, int len, int *kern_total )
|
||||
{
|
||||
unsigned int i, count;
|
||||
KERNINGPAIR *kern = NULL;
|
||||
int *ret;
|
||||
|
||||
*kern_total = 0;
|
||||
|
||||
ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(*ret) );
|
||||
if (!ret) return NULL;
|
||||
|
||||
count = GetKerningPairsW( hdc, 0, NULL );
|
||||
if (count)
|
||||
{
|
||||
kern = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*kern) );
|
||||
if (!kern)
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, ret );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GetKerningPairsW( hdc, count, kern );
|
||||
}
|
||||
|
||||
for (i = 0; i < len - 1; i++)
|
||||
{
|
||||
ret[i] = kern_pair( kern, count, str[i], str[i + 1] );
|
||||
*kern_total += ret[i];
|
||||
}
|
||||
|
||||
ret[len - 1] = 0; /* no kerning for last element */
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, kern );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* GetCharacterPlacementW (GDI32.@)
|
||||
*
|
||||
* Retrieve information about a string. This includes the width, reordering,
|
||||
* Glyphing and so on.
|
||||
*
|
||||
* RETURNS
|
||||
*
|
||||
* The width and height of the string if successful, 0 if failed.
|
||||
*
|
||||
* BUGS
|
||||
*
|
||||
* All flags except GCP_REORDER are not yet implemented.
|
||||
* Reordering is not 100% compliant to the Windows BiDi method.
|
||||
* Caret positioning is not yet implemented for BiDi.
|
||||
* Classes are not yet implemented.
|
||||
*
|
||||
*/
|
||||
DWORD WINAPI GetCharacterPlacementW( HDC hdc, const WCHAR *str, INT count, INT max_extent,
|
||||
GCP_RESULTSW *result, DWORD flags )
|
||||
{
|
||||
int *kern = NULL, kern_total = 0;
|
||||
UINT i, set_cnt;
|
||||
SIZE size;
|
||||
DWORD ret = 0;
|
||||
|
||||
TRACE("%s, %d, %d, 0x%08x\n", debugstr_wn(str, count), count, max_extent, flags);
|
||||
|
||||
if (!count)
|
||||
return 0;
|
||||
|
||||
if (!result)
|
||||
return GetTextExtentPoint32W( hdc, str, count, &size ) ? MAKELONG(size.cx, size.cy) : 0;
|
||||
|
||||
TRACE( "lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
|
||||
"lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
|
||||
result->lStructSize, result->lpOutString, result->lpOrder,
|
||||
result->lpDx, result->lpCaretPos, result->lpClass,
|
||||
result->lpGlyphs, result->nGlyphs, result->nMaxFit );
|
||||
|
||||
if (flags & ~(GCP_REORDER | GCP_USEKERNING))
|
||||
FIXME( "flags 0x%08x ignored\n", flags );
|
||||
if (result->lpClass)
|
||||
FIXME( "classes not implemented\n" );
|
||||
if (result->lpCaretPos && (flags & GCP_REORDER))
|
||||
FIXME( "Caret positions for complex scripts not implemented\n" );
|
||||
|
||||
set_cnt = (UINT)count;
|
||||
if (set_cnt > result->nGlyphs) set_cnt = result->nGlyphs;
|
||||
|
||||
/* return number of initialized fields */
|
||||
result->nGlyphs = set_cnt;
|
||||
|
||||
if (!(flags & GCP_REORDER))
|
||||
{
|
||||
/* Treat the case where no special handling was requested in a fastpath way */
|
||||
/* copy will do if the GCP_REORDER flag is not set */
|
||||
if (result->lpOutString)
|
||||
memcpy( result->lpOutString, str, set_cnt * sizeof(WCHAR) );
|
||||
|
||||
if (result->lpOrder)
|
||||
{
|
||||
for (i = 0; i < set_cnt; i++)
|
||||
result->lpOrder[i] = i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BIDI_Reorder( NULL, str, count, flags, WINE_GCPW_FORCE_LTR, result->lpOutString,
|
||||
set_cnt, result->lpOrder, NULL, NULL );
|
||||
}
|
||||
|
||||
if (flags & GCP_USEKERNING)
|
||||
{
|
||||
kern = kern_string( hdc, str, set_cnt, &kern_total );
|
||||
if (!kern)
|
||||
{
|
||||
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: Will use the placement chars */
|
||||
if (result->lpDx)
|
||||
{
|
||||
int c;
|
||||
for (i = 0; i < set_cnt; i++)
|
||||
{
|
||||
if (GetCharWidth32W( hdc, str[i], str[i], &c ))
|
||||
{
|
||||
result->lpDx[i] = c;
|
||||
if (flags & GCP_USEKERNING)
|
||||
result->lpDx[i] += kern[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result->lpCaretPos && !(flags & GCP_REORDER))
|
||||
{
|
||||
unsigned int pos = 0;
|
||||
|
||||
result->lpCaretPos[0] = 0;
|
||||
for (i = 0; i < set_cnt - 1; i++)
|
||||
{
|
||||
if (flags & GCP_USEKERNING)
|
||||
pos += kern[i];
|
||||
|
||||
if (GetTextExtentPoint32W( hdc, &str[i], 1, &size ))
|
||||
result->lpCaretPos[i + 1] = (pos += size.cx);
|
||||
}
|
||||
}
|
||||
|
||||
if (result->lpGlyphs)
|
||||
GetGlyphIndicesW( hdc, str, set_cnt, result->lpGlyphs, 0 );
|
||||
|
||||
if (GetTextExtentPoint32W( hdc, str, count, &size ))
|
||||
ret = MAKELONG( size.cx + kern_total, size.cy );
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, kern );
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue