Compare commits

...

12 Commits

Author SHA1 Message Date
Vincent Wei
0d1f1f028a update 2023-05-10 09:00:35 +08:00
Vincent Wei
d4add19e6a tune GetTickCount for threads mode 2023-05-08 20:09:23 +08:00
Vincent Wei
bfaeae0023 call GetTickCount when setting timer 2023-05-08 19:48:21 +08:00
Vincent Wei
70705c7db0 fix bug reported in Issue #116 2023-05-08 19:34:43 +08:00
Vincent Wei
517d74a2d2 update version in configure.ac 2023-05-08 08:35:10 +08:00
Vincent Wei
d68eee3c90 use buffer in stack for short text 2023-04-24 11:52:47 +08:00
Vincent Wei
e575e7c69d add new APIs: GetTabbedACharsExtentXXX 2023-04-24 11:38:02 +08:00
Vincent Wei
d059fc8de2 fix a typo: Achar2UChar 2023-04-24 11:37:35 +08:00
Vincent Wei
5d9d787dac cleanup 2023-04-23 14:02:15 +08:00
Vincent Wei
9696fbb3ba change version to 5.0.12; cleanup 2023-04-23 12:42:47 +08:00
Vincent Wei
800329086e implement new API: GetACharsExtentPointEx(); enhance GetTextExtentPoint() and GetTabbedTextExtentPoint() to support BIDI charsets 2023-04-23 12:36:55 +08:00
Vincent Wei
11be6af9d3 use Amask from real engine 2023-03-03 10:57:15 +08:00
13 changed files with 477 additions and 214 deletions

View File

@ -1,5 +1,7 @@
# Release Notes
- [Version 5.0.12](#version-5012)
+ [What's new in version 5.0.12](#whats-new-in-version-5012)
- [Version 5.0.11](#version-5011)
+ [What's new in version 5.0.11](#whats-new-in-version-5011)
- [Version 5.0.10](#version-5010)
@ -28,6 +30,26 @@
+ [Changes leading to incompatibility](#changes-leading-to-incompatibility)
+ [Deprecated APIs](#deprecated-apis)
## Version 5.0.12
On May 10, 2023, FMSoft announces the availability of MiniGUI 5.0.12,
which is an enhancement release with some minor enhancements
of MiniGUI 5.0.x.
### What's new in version 5.0.12
In this version, we made some enhancements:
* ENHANCEMENTS:
- Add new API `GetACharsExtentPointEx()`.
- Add new APIs `GetTabbedACharsExtent()`, `GetTabbedACharsExtentPoint()`,
and `GetTabbedACharsExtentPointEx()`.
- Enhance two APIs `GetTextExtentPoint()` and `GetTabbedTextExtentPoint()`
to support BIDI charsets.
- Tune management of tick count.
* BUGFIXING:
- Fix a typo: `Achar2UChar()` to `AChar2UChar()`.
## Version 5.0.11
On Dec. 31, 2022, FMSoft announces the availability of MiniGUI 5.0.11,

View File

@ -1,4 +1,4 @@
Version 5.0.11 (2022/12/31)
Version 5.0.12 (2023/04/30)
This is a minor enhancement and bugfix release of MiniGUI 5.0.x, the stable version.

View File

@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.60)
AC_INIT(libminigui, 5.0.11)
AC_INIT(libminigui, 5.0.12)
AC_CONFIG_SRCDIR(src/main/main.c)
dnl Set various version strings - taken gratefully from the SDL sources
@ -16,9 +16,9 @@ dnl Set various version strings - taken gratefully from the SDL sources
#
MINIGUI_MAJOR_VERSION=5
MINIGUI_MINOR_VERSION=0
MINIGUI_MICRO_VERSION=11
MINIGUI_INTERFACE_AGE=1
MINIGUI_BINARY_AGE=1
MINIGUI_MICRO_VERSION=12
MINIGUI_INTERFACE_AGE=0
MINIGUI_BINARY_AGE=2
MINIGUI_VERSION=$MINIGUI_MAJOR_VERSION.$MINIGUI_MINOR_VERSION.$MINIGUI_MICRO_VERSION
AC_SUBST(MINIGUI_MAJOR_VERSION)

View File

@ -12632,7 +12632,7 @@ MG_EXPORT int GUIAPI BIDIGetTextVisualAChars (LOGFONT* log_font,
* Achar32* achars, int nr_achars, int pel,
* void* extra, CB_REVERSE_ARRAY cb_reverse_extra)
* \brief Reorder the specified logical glyph string in visual order and
* reorder an extra array to reflect the visule order of the achars.
* reorder an extra array to reflect the visual order of the achars.
*
* This function reorders the logical glyph string in place to visual order.
* If \a extra and \a cb_reverse_extra are both not NULL, it also reorders
@ -12837,6 +12837,105 @@ MG_EXPORT int GUIAPI GetACharsExtent (HDC hdc, Achar32* achars, int nr_achars,
MG_EXPORT int GUIAPI GetACharsExtentPoint (HDC hdc, Achar32* achars,
int nr_achars, int max_extent, SIZE* size);
/**
* \fn int GUIAPI GetACharsExtentPointEx (HDC hdc, Achar32* achars, \
* int nr_achars, int max_extent, int* dx_chars, SIZE* size)
* \brief Get the visual extent value of an achar string.
*
* This function gets the visual extent value of a glpyh string.
* Note that this function ignore all breaks in the achar string.
*
* \param hdc The device context.
* \param achars The pointer to the achar string.
* \param nr_achars The length of the achar string len.
* \param max_extent The maximal output extent value.
* \param dx_achars The output positions of each character in the text will be
* returned through this pointer. It can be NULL.
* \param size The real extent of all visual achars in the achar string.
*
* \return The index of the last achar which can be fit to the extent.
*
* \sa GetACharsExtentPoint
*
* Since 5.0.12
*/
MG_EXPORT int GUIAPI GetACharsExtentPointEx (HDC hdc, Achar32* achars,
int nr_achars, int max_extent, int* dx_achars, SIZE* size);
/**
* \fn int GUIAPI GetTabbedACharsExtent (HDC hdc, Achar32* achars,
* int nr_achars, SIZE* size)
* \brief Get visual extent value of an achar string.
*
* This function gets the extent value of an achar string on a DC. Note that
* this function will ignore all breaks in the achar string.
*
* \param hdc The device context.
* \param achars The pointer to the achar string.
* \param nr_achars The length of the achar string.
* \param size The buffer restoring the extents of the achar strings.
*
* \return The extent of the achar string.
*
* \sa GetTabbedACharsExtentPoint
*
* Since 5.0.12
*/
MG_EXPORT int GUIAPI GetTabbedACharsExtent (HDC hdc, Achar32* achars,
int nr_achars, SIZE* size);
/**
* \fn int GUIAPI GetTabbedACharsExtentPoint (HDC hdc, Achar32* achars,
* int nr_achars, int max_extent, SIZE* size)
* \brief Get the visual extent value of an achar string.
*
* This function gets the visual extent value of a glpyh string.
* Note that this function ignore all breaks in the achar string.
*
* \param hdc The device context.
* \param achars The pointer to the achar string.
* \param nr_achars The length of the achar string len.
* \param max_extent The maximal output extent value.
* \param size The real extent of all visual achars in the achar string.
*
* \return The the index of the last achar which can be fit to the extent.
*
* \sa GetTabbedACharsExtentPointEx
*
* Since 5.0.12
*/
MG_EXPORT int GUIAPI GetTabbedACharsExtentPoint (HDC hdc, Achar32* achars,
int nr_achars, int max_extent, SIZE* size);
/**
* \fn int GUIAPI GetTabbedACharsExtentPointEx (HDC hdc,
* Achar32* achars, int nr_achars, int max_extent,
* int* dx_chars, int* dy_chars, SIZE* size)
* \brief Get the visual extent value of an achar string.
*
* This function gets the visual extent value of a glpyh string.
* Note that this function ignore all breaks in the achar string.
*
* \param hdc The device context.
* \param achars The pointer to the achar string.
* \param nr_achars The length of the achar string len.
* \param max_extent The maximal output extent value.
* \param dx_achars The output x-positions of each character in the text
* will be returned through this pointer. It can be NULL.
* \param dy_achars The output y-positions of each character in the text
* will be returned through this pointer. It can be NULL.
* \param size The real extent of all visual achars in the achar string.
*
* \return The index of the last achar which can be fit to the extent.
*
* \sa GetTabbedACharsExtentPoint
*
* Since 5.0.12
*/
MG_EXPORT int GUIAPI GetTabbedACharsExtentPointEx (HDC hdc,
Achar32* achars, int nr_achars, int max_extent,
int* dx_achars, int* dy_achars, SIZE* size);
/**
* \fn Glyph32 GUIAPI GetGlyphValue (LOGFONT* logfont, const char* mchar, \
* int mchar_len, const char* pre_mchar, int pre_len)

View File

@ -735,8 +735,7 @@ Achar32* __mg_legacy_bidi_map_reorder (const CHARSETOPS* charset_ops,
run_pos = node_p->pos;
run_len = node_p->len;
for (i=0; i<run_len; i++)
{
for (i=0; i<run_len; i++) {
(map+run_pos+i)->is_rtol = (node_p)->level & 1;
}
}

View File

@ -141,6 +141,14 @@ BOOL mg_InitDesktop (void)
#include "debug.h"
static IDLEHANDLER std_idle_handler;
static BOOL idle_handler_for_desktop_thread (MSGQUEUE *msg_queue, BOOL wait)
{
__mg_update_tick_count (NULL);
return std_idle_handler (msg_queue, wait);
}
void* __kernel_desktop_main (void* data)
{
MSG Msg;
@ -152,8 +160,10 @@ void* __kernel_desktop_main (void* data)
return NULL;
}
/* for threads mode, the idle handler for desktop thread is NULL */
__mg_dsk_msg_queue->OnIdle = NULL;
/* For bug reported in Issue #116, under threads mode, the idle handler
for the desktop thread should call __mg_update_tick_count () */
std_idle_handler = __mg_dsk_msg_queue->OnIdle;
__mg_dsk_msg_queue->OnIdle = idle_handler_for_desktop_thread;
/* init desktop window */
init_desktop_win ();

View File

@ -391,14 +391,6 @@ static BOOL InstallSEGVHandler (void)
#include <locale.h>
#endif
static IDLEHANDLER std_idle_handler;
static BOOL idle_handler_for_main_thread (MSGQUEUE *msg_queue, BOOL wait)
{
__mg_update_tick_count (NULL);
return std_idle_handler (msg_queue, wait);
}
int GUIAPI InitGUI (int args, const char *agr[])
{
char engine [LEN_ENGINE_NAME + 1];
@ -583,11 +575,6 @@ int GUIAPI InitGUI (int args, const char *agr[])
goto failure;
}
/* for threads mode, the idle handler for the main threads should
call __mg_update_tick_count () */
std_idle_handler = msg_queue->OnIdle;
msg_queue->OnIdle = idle_handler_for_main_thread;
/* init timer for tick counter */
step++;
if (!mg_InitTimer (FALSE)) {

View File

@ -293,6 +293,11 @@ BOOL GUIAPI SetTimerEx (HWND hWnd, LINT id, DWORD interv,
TIMER** timer_slots;
PMSGQUEUE pMsgQueue;
#ifndef _MGRM_THREADS
/* Force to update tick count */
GetTickCount();
#endif
if (id == 0) {
_WRN_PRINTF ("bad identifier (%ld).\n", id);
return FALSE;
@ -415,7 +420,12 @@ int GUIAPI KillTimer (HWND hWnd, LINT id)
int i;
int killed = 0;
MSGQUEUE* msg_queue;
#ifndef _MGRM_THREADS
/* Force to update tick count */
GetTickCount();
#endif
msg_queue = getMsgQueueForThisThread ();
if (msg_queue) {
@ -447,7 +457,12 @@ BOOL GUIAPI ResetTimerEx (HWND hWnd, LINT id, DWORD interv,
{
int i;
MSGQUEUE* msg_queue;
#ifndef _MGRM_THREADS
/* Force to update tick count */
GetTickCount();
#endif
if (id == 0)
return FALSE;
@ -482,6 +497,11 @@ BOOL GUIAPI IsTimerInstalled (HWND hWnd, LINT id)
int i;
TIMER** timer_slots;
#ifndef _MGRM_THREADS
/* Force to update tick count */
GetTickCount();
#endif
if (id == 0)
return FALSE;
@ -507,6 +527,11 @@ BOOL GUIAPI HaveFreeTimer (void)
int i;
TIMER** timer_slots;
#ifndef _MGRM_THREADS
/* Force to update tick count */
GetTickCount();
#endif
timer_slots = getTimerSlotsForThisThread (NULL);
if (timer_slots) {
for (i = 0; i < DEF_NR_TIMERS; i++) {
@ -531,179 +556,12 @@ DWORD GUIAPI GetTickCount (void)
else {
__mg_tick_counter = SHAREDRES_TIMER_COUNTER;
}
#else /* defined _MGRM_PROCESSES */
#elif defined(_MGRM_STANDALONE)
__mg_tick_counter = __mg_os_get_time_ticks ();
#endif /* not defined _MGRM_PROCESSES */
#else /* not defined _MGRM_PROCESSES and _MGRM_PROCESSES */
/* do nothing here because the desktop thread updates the tick count */
#endif /* not defined _MGRM_PROCESSES and _MGRM_PROCESSES */
return __mg_tick_counter;
}
#if 0 /* deprecated code */
/* Since 5.0.0, we no longer use the timer thread for MiniGUI-Threads runmode */
in message queue */
/* timer entry for thread version */
#ifdef _MGRM_THREADS
#ifdef __AOS__
#include "os_api.h"
static OS_TIMER_ID __mg_os_timer = 0;
#else /* __AOS__ */
static void* TimerEntry (void* data)
{
sem_post ((sem_t*)data);
while (__mg_quiting_stage > _MG_QUITING_STAGE_TIMER) {
__mg_os_time_delay (10);
__mg_update_tick_count (NULL);
}
/* printf("quit from TimerEntry()\n"); */
return NULL;
}
#endif /* !__AOS__ */
int __mg_timer_init (void)
{
if (!mg_InitTimer ()) {
fprintf (stderr, "KERNEL>timer: Init Timer failure.\n");
return -1;
}
#ifdef __AOS__
__mg_os_timer = tp_os_timer_create ("mgtimer", __mg_update_tick_count,
NULL, AOS_TIMER_TICKT,
OS_AUTO_ACTIVATE | OS_AUTO_LOAD);
#else /* __AOS__ */
{
sem_t wait;
sem_init (&wait, 0, 0);
pthread_create (&__mg_timer, NULL, TimerEntry, &wait);
sem_wait (&wait);
sem_destroy (&wait);
}
#endif /* !__AOS__ */
return 0;
}
void mg_TerminateTimer (void)
{
#ifdef __AOS__
tp_os_timer_delete (__mg_os_timer);
#endif
#ifdef __WINBOND_SWLINUX__
pthread_detach (__mg_timer); /* XXX: Can we pthread_join()? */
#else
pthread_join (__mg_timer, NULL);
#endif /* __WINBOND_SWLINUX__ */
#ifdef _MGHAVE_VIRTUAL_WINDOW
pthread_mutex_destroy (&timerLock);
#endif
#if 0 /* deprecated code */
/* Since 5.0.0, we allocate timer slots per thread, and manage the time slots
in message queue */
for (i = 0; i < DEF_NR_TIMERS; i++) {
if (timerstr[i] != NULL)
free ( timerstr[i] );
timerstr[i] = NULL;
}
#ifdef _MGHAVE_VIRTUAL_WINDOW
pthread_mutex_destroy (&timerLock);
#endif
#endif /* deprecated code */
}
#else /* defined _MGRM_THREADS */
#endif /* defined _MGRM_THREADS */
/* Since 5.0.0, we use timer slots per thread, and manage the time slots
in message queue */
static TIMER *timerstr[DEF_NR_TIMERS];
#ifdef _MGHAVE_VIRTUAL_WINDOW
/* lock for protecting timerstr */
static pthread_mutex_t timerLock;
#define TIMER_LOCK() pthread_mutex_lock(&timerLock)
#define TIMER_UNLOCK() pthread_mutex_unlock(&timerLock)
#else
#define TIMER_LOCK()
#define TIMER_UNLOCK()
#endif
int __mg_get_timer_slot (HWND hWnd, int id)
{
int i;
int slot = -1;
TIMER_LOCK ();
for (i = 0; i < DEF_NR_TIMERS; i++) {
if (timerstr[i] != NULL) {
if (timerstr[i]->hWnd == hWnd && timerstr[i]->id == id) {
slot = i;
break;
}
}
}
TIMER_UNLOCK ();
return slot;
}
void __mg_move_timer_last (TIMER* timer, int slot)
{
if (slot < 0 || slot >= DEF_NR_TIMERS)
return;
TIMER_LOCK ();
if (timer && timer->msg_queue) {
/* The following code is already called in message.c...
* timer->ticks_current = 0;
* timer->msg_queue->expired_timer_mask &= ~(0x01UL << slot);
*/
if (slot != (DEF_NR_TIMERS - 1)) {
TIMER* t;
if (timer->msg_queue->expired_timer_mask & (0x01UL << (DEF_NR_TIMERS -1))) {
timer->msg_queue->expired_timer_mask |= (0x01UL << slot);
timer->msg_queue->expired_timer_mask &= ~(0x01UL << (DEF_NR_TIMERS -1));
}
t = timerstr [DEF_NR_TIMERS - 1];
timerstr [DEF_NR_TIMERS - 1] = timerstr [slot];
timerstr [slot] = t;
}
}
TIMER_UNLOCK ();
return;
}
TIMER* __mg_get_timer (int slot)
{
TIMER** timer_slots;
if (slot < 0 || slot >= DEF_NR_TIMERS)
return NULL;
timer_slots = getTimerSlotsForThisThread (NULL);
if (timer_slots) {
return timer_slots[slot];
}
_WRN_PRINTF ("called for non message thread\n");
return NULL;
}
#endif /* deprecated code */

View File

@ -307,7 +307,7 @@ static int RealEngine_GetInfo (RealFBInfo * realfb_info)
real_device->screen = GAL_CreateRGBSurface (GAL_SWSURFACE,
0, 0, real_vformat.BitsPerPixel, real_vformat.Rmask,
real_vformat.Gmask, real_vformat.Bmask, 0);
real_vformat.Gmask, real_vformat.Bmask, real_vformat.Amask);
if (real_device->screen == NULL)
_ERR_PRINTF ("NEWGAL>SHADOW: can't create screen of real engine.\n");

View File

@ -200,7 +200,7 @@ Uint16 GUIAPI GetACharBidiType (LOGFONT* log_font, Achar32 chv)
#include "unicode-ops.h"
Uchar32 GUIAPI Achar2UChar(LOGFONT* logfont, Achar32 chv)
Uchar32 GUIAPI AChar2UChar(LOGFONT* logfont, Achar32 chv)
{
Uchar32 uc;
DEVFONT* devfont = SELECT_DEVFONT_BY_ACHAR(logfont, chv);

View File

@ -612,8 +612,7 @@ int _gdi_reorder_text (PDC pdc, const unsigned char* text, int text_len,
(NULL, 0, text + i, 1)))
return (text_len-i-1);
char_type = sbc_devfont->charset_ops->char_type
(chv);
char_type = sbc_devfont->charset_ops->char_type (chv);
gv = GetGlyphValueAlt (pdc->pLogFont, chv);
if (gv == INV_GLYPH_VALUE)

View File

@ -533,6 +533,113 @@ int GUIAPI TabbedTextOutEx (HDC hdc, int x, int y, const char* spText,
return advance;
}
#define SZ_BUFF_IN_STACK 256
static int get_tabbed_text_extent_point_for_bidi(HDC hdc,
const char* text, int len, int max_extent,
int* fit_chars, int* pos_chars, int* dx_chars, SIZE* size)
{
PDC pdc = dc_HDC2PDC(hdc);
LOGFONT *log_font = pdc->pLogFont;
DEVFONT* sbc_devfont = log_font->devfonts[0];
Achar32 achars_buff[SZ_BUFF_IN_STACK];
ACHARMAPINFO achars_map_buff[SZ_BUFF_IN_STACK];
Achar32 *achars;
ACHARMAPINFO* achars_map;
if (len < 0)
len = strlen(text);
if (len <= SZ_BUFF_IN_STACK) {
achars = achars_buff;
achars_map = achars_map_buff;
}
else {
achars = NULL;
achars_map = NULL;
}
int nr_fit_achars = 0;
int nr_achars = BIDIGetTextVisualAChars(log_font, text, len,
&achars, &achars_map);
if (nr_achars <= 0) {
goto done;
}
_gdi_start_new_line(pdc);
int tab_width = sbc_devfont->font_ops->get_ave_width(log_font, sbc_devfont)
* pdc->tabstop;
int line_height = log_font->size + pdc->alExtra + pdc->blExtra;
size->cx = 0;
size->cy = line_height;
int left_achars = nr_achars;
int last_line_width = 0;
while (left_achars > 0) {
if (pos_chars)
pos_chars[nr_fit_achars] = achars_map[nr_fit_achars].byte_index;
if (dx_chars)
dx_chars[nr_fit_achars] = last_line_width;
size->cx = last_line_width;
Uint32 achar_type = GetACharType(log_font, achars[nr_fit_achars]);
Glyph32 gv = GetGlyphValueAlt(log_font, achars[nr_fit_achars]);
int adv_x = 0, adv_y = 0;
switch (achar_type & ACHARTYPE_BASIC_MASK) {
case ACHAR_BASIC_ZEROWIDTH:
adv_x = adv_y = 0;
break;
case ACHAR_BASIC_LF:
adv_y = line_height;
case ACHAR_BASIC_CR:
adv_x = 0;
if (last_line_width > size->cx) {
size->cx = last_line_width;
}
last_line_width = 0;
_gdi_start_new_line(pdc);
break;
case ACHAR_BASIC_HT:
adv_x = tab_width;
last_line_width += tab_width;
_gdi_start_new_line(pdc);
break;
default:
last_line_width += _gdi_get_glyph_advance (pdc, gv,
(pdc->ta_flags & TA_X_MASK) != TA_RIGHT,
0, 0, &adv_x, &adv_y, NULL);
last_line_width += pdc->cExtra;
break;
}
if (max_extent > 0 && last_line_width > max_extent) {
break;
}
size->cx += adv_x;
size->cy += adv_y;
if (last_line_width > size->cx)
size->cx = last_line_width;
left_achars--;
nr_fit_achars++;
}
if (fit_chars)
*fit_chars = nr_fit_achars;
done:
if (achars != NULL && achars != achars_buff)
free(achars);
if (achars_map != NULL && achars_map != achars_map_buff)
free(achars_map);
return nr_fit_achars;
}
int GUIAPI GetTabbedTextExtentPoint (HDC hdc, const char* text,
int len, int max_extent,
int* fit_chars, int* pos_chars, int* dx_chars, SIZE* size)
@ -553,9 +660,11 @@ int GUIAPI GetTabbedTextExtentPoint (HDC hdc, const char* text,
/* set size to zero first */
size->cx = size->cy = 0;
/* This function does not support BIDI */
if (mbc_devfont && pdc->bidi_flags && mbc_devfont->charset_ops->bidi_char_type)
return -1;
if (mbc_devfont && pdc->bidi_flags &&
mbc_devfont->charset_ops->bidi_char_type) {
return get_tabbed_text_extent_point_for_bidi(hdc, text, len,
max_extent, fit_chars, pos_chars, dx_chars, size);
}
_gdi_start_new_line (pdc);
@ -569,6 +678,7 @@ int GUIAPI GetTabbedTextExtentPoint (HDC hdc, const char* text,
pos_chars [char_count] = len - left_bytes;
if (dx_chars)
dx_chars [char_count] = last_line_width;
size->cx = last_line_width;
devfont = NULL;
len_cur_char = 0;
@ -599,7 +709,6 @@ int GUIAPI GetTabbedTextExtentPoint (HDC hdc, const char* text,
switch (char_type & ACHARTYPE_BASIC_MASK) {
case ACHAR_BASIC_ZEROWIDTH:
case ACHAR_BASIC_VOWEL:
break;
case ACHAR_BASIC_LF:
size->cy += line_height;
@ -642,3 +751,94 @@ ret:
return len - left_bytes;
}
int GUIAPI GetTabbedACharsExtentPointEx(HDC hdc,
Achar32* achars, int nr_achars, int max_extent,
int* dx_achars, int* dy_achars, SIZE* size)
{
PDC pdc = dc_HDC2PDC(hdc);
LOGFONT *log_font = pdc->pLogFont;
DEVFONT* sbc_devfont = log_font->devfonts[0];
int nr_fit_achars = 0;
_gdi_start_new_line(pdc);
int tab_width = sbc_devfont->font_ops->get_ave_width(log_font, sbc_devfont)
* pdc->tabstop;
int line_height = log_font->size + pdc->alExtra + pdc->blExtra;
size->cx = 0;
size->cy = 0;
int left_achars = nr_achars;
int last_line_width = 0;
while (left_achars > 0) {
if (dx_achars)
dx_achars[nr_fit_achars] = last_line_width;
if (dy_achars)
dy_achars[nr_fit_achars] = size->cy;
size->cx = last_line_width;
Uint32 achar_type = GetACharType(log_font, achars[nr_fit_achars]);
Glyph32 gv = GetGlyphValueAlt(log_font, achars[nr_fit_achars]);
int adv_x = 0, adv_y = 0;
switch (achar_type & ACHARTYPE_BASIC_MASK) {
case ACHAR_BASIC_ZEROWIDTH:
adv_x = adv_y = 0;
break;
case ACHAR_BASIC_LF:
adv_y = line_height;
case ACHAR_BASIC_CR:
adv_x = 0;
if (last_line_width > size->cx) {
size->cx = last_line_width;
}
last_line_width = 0;
_gdi_start_new_line(pdc);
break;
case ACHAR_BASIC_HT:
adv_x = tab_width;
last_line_width += tab_width;
_gdi_start_new_line(pdc);
break;
default:
last_line_width += _gdi_get_glyph_advance (pdc, gv,
(pdc->ta_flags & TA_X_MASK) != TA_RIGHT,
0, 0, &adv_x, &adv_y, NULL);
last_line_width += pdc->cExtra;
break;
}
if (max_extent > 0 && last_line_width > max_extent) {
break;
}
size->cx += adv_x;
size->cy += adv_y;
if (last_line_width > size->cx)
size->cx = last_line_width;
left_achars--;
nr_fit_achars++;
}
size->cy += line_height;
return nr_fit_achars;
}
int GUIAPI GetTabbedACharsExtentPoint(HDC hdc, Achar32* achars,
int nr_achars, int max_extent, SIZE* size)
{
return GetTabbedACharsExtentPointEx(hdc,
achars, nr_achars, max_extent, NULL, NULL, size);
}
int GUIAPI GetTabbedACharsExtent(HDC hdc, Achar32* achars,
int nr_achars, SIZE* size)
{
GetTabbedACharsExtentPointEx(hdc,
achars, nr_achars, -1, NULL, NULL, size);
return size->cx;
}

View File

@ -319,7 +319,8 @@ typedef struct _TEXTOUTOMITTED_CTXT
Uint32 max_extent;
} TEXTOUTOMITTED_CTXT;
static BOOL cb_textout_omitted (void* context, Glyph32 glyph_value, unsigned int char_type)
static BOOL
cb_textout_omitted (void* context, Glyph32 glyph_value, unsigned int char_type)
{
TEXTOUTOMITTED_CTXT* ctxt = (TEXTOUTOMITTED_CTXT*)context;
int adv_x, adv_y;
@ -441,9 +442,82 @@ int GUIAPI TextOutOmitted (HDC hdc, int x, int y,
#undef STRDOT_LEN
int GUIAPI GetTextExtentPoint (HDC hdc, const char* text, int len,
int max_extent,
int* fit_chars, int* pos_chars, int* dx_chars, SIZE* size)
#define SZ_BUFF_IN_STACK 256
static int get_text_extent_point_for_bidi(HDC hdc,
const char* text, int len, int max_extent,
int* fit_chars, int* pos_chars, int* dx_chars, SIZE* size)
{
PDC pdc = dc_HDC2PDC(hdc);
LOGFONT *log_font = pdc->pLogFont;
Achar32 achars_buff[SZ_BUFF_IN_STACK];
ACHARMAPINFO achars_map_buff[SZ_BUFF_IN_STACK];
int dx_achars_buff[SZ_BUFF_IN_STACK];
Achar32 *achars;
ACHARMAPINFO* achars_map;
int *dx_achars = NULL;
if (len < 0)
len = strlen(text);
if (len <= SZ_BUFF_IN_STACK) {
achars = achars_buff;
achars_map = achars_map_buff;
}
else {
achars = NULL;
achars_map = NULL;
}
int nr_fit_achars = 0;
int nr_achars = BIDIGetTextVisualAChars(log_font, text, len,
&achars, &achars_map);
if (nr_achars <= 0) {
goto done;
}
if (nr_achars <= SZ_BUFF_IN_STACK) {
dx_achars = dx_achars_buff;
}
else {
dx_achars = malloc(sizeof(int) * nr_achars);
}
if (dx_chars == NULL || achars == NULL || achars_map == NULL)
goto done;
nr_fit_achars = GetACharsExtentPointEx(hdc, achars, nr_achars,
max_extent, dx_achars, size);
if (fit_chars) {
*fit_chars = nr_fit_achars;
}
if (pos_chars || dx_chars) {
for (int i = 0; i < nr_fit_achars; i++) {
if (pos_chars) {
pos_chars[i] = achars_map[i].byte_index;
}
if (dx_chars) {
dx_chars[i] = dx_achars[i];
}
}
}
done:
if (achars != NULL && achars != achars_buff)
free(achars);
if (achars_map != NULL && achars_map != achars_map_buff)
free(achars_map);
if (dx_achars != NULL && dx_achars != dx_achars_buff)
free(dx_achars);
return nr_fit_achars;
}
int GUIAPI GetTextExtentPoint (HDC hdc,
const char* text, int len, int max_extent,
int* fit_chars, int* pos_chars, int* dx_chars, SIZE* size)
{
PDC pdc = dc_HDC2PDC (hdc);
LOGFONT* log_font = pdc->pLogFont;
@ -459,8 +533,12 @@ int GUIAPI GetTextExtentPoint (HDC hdc, const char* text, int len,
size->cx = size->cy = 0;
/* This function does not support BIDI */
if (mbc_devfont && pdc->bidi_flags && mbc_devfont->charset_ops->bidi_char_type)
if (mbc_devfont && pdc->bidi_flags &&
mbc_devfont->charset_ops->bidi_char_type) {
get_text_extent_point_for_bidi(pdc, text, len, max_extent,
fit_chars, pos_chars, dx_chars, size);
return -1;
}
_gdi_start_new_line(pdc);
@ -538,8 +616,8 @@ int GUIAPI DrawACharString (HDC hdc, int startx, int starty,
return ctxt.advance;
}
int GUIAPI GetACharsExtentPoint(HDC hdc, Achar32* achars, int nr_achars,
int max_extent, SIZE* size)
int GUIAPI GetACharsExtentPointEx (HDC hdc, Achar32* achars, int nr_achars,
int max_extent, int *dx_achars, SIZE* size)
{
int i = 0;
int advance = 0;
@ -552,11 +630,15 @@ int GUIAPI GetACharsExtentPoint(HDC hdc, Achar32* achars, int nr_achars,
size->cx = 0;
size->cy = 0;
while(i < nr_achars){
while (i < nr_achars){
if (dx_achars) {
dx_achars[i] = advance;
}
devfont = SELECT_DEVFONT_BY_ACHAR(log_font, achars[i]);
char_type = devfont->charset_ops->char_type(achars[i]);
if (check_zero_width (char_type)) {
if (check_zero_width(char_type)) {
adv_x = adv_y = 0;
}
else {
@ -578,7 +660,7 @@ int GUIAPI GetACharsExtentPoint(HDC hdc, Achar32* achars, int nr_achars,
size->cx += adv_x;
size->cy += adv_y;
i ++;
i++;
}
_gdi_calc_glyphs_size_from_two_points (pdc, 0, 0,
@ -587,6 +669,13 @@ int GUIAPI GetACharsExtentPoint(HDC hdc, Achar32* achars, int nr_achars,
return i;
}
int GUIAPI GetACharsExtentPoint(HDC hdc, Achar32* achars, int nr_achars,
int max_extent, SIZE* size)
{
return GetACharsExtentPointEx(hdc, achars, nr_achars, max_extent,
NULL, size);
}
int GUIAPI GetACharsExtent(HDC hdc, Achar32* achars, int nr_achars, SIZE* size)
{
int i = 0;