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:
Jacek Caban 2021-08-19 10:25:57 +02:00 committed by Alexandre Julliard
parent bf4084b49c
commit 6616da70be
3 changed files with 198 additions and 212 deletions

View File

@ -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.@]
*

View File

@ -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;

View File

@ -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;
}