1993-09-04 12:09:32 +02:00
|
|
|
/*
|
|
|
|
* GDI font objects
|
|
|
|
*
|
|
|
|
* Copyright 1993 Alexandre Julliard
|
1997-06-16 19:43:53 +02:00
|
|
|
* 1997 Alex Korobka
|
2003-06-27 22:47:16 +02:00
|
|
|
* Copyright 2002,2003 Shachar Shemesh
|
2002-03-10 00:29:33 +01:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
2006-05-18 14:49:52 +02:00
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
Release 960131
Wed Jan 31 10:58:00 1996 Alexandre Julliard <julliard@sunsite.unc.edu>
* [configure.in]
Added --with-dll option to build libwine.so.
* [controls/listbox.c]
Fixed ListBoxDirectory(), DlgDirSelect() and
DlgDirList(). Hopefully their behavior is correct now.
* [controls/menu.c]
Use SEGPTRs in ChangeMenu(), InsertMenu(), AppendMenu() and
ModifyMenu() for the item data, to avoid corrupting the pointer
for owner-drawn items.
* [controls/static.c]
Attempt to load OEM icons for SS_ICON controls. Probably not
entirely correct.
Don't clip the text output.
* [files/directory.c]
Add temp dir and Windows dir to environment.
* [files/dos_fs.c]
Fixed a few path handling bugs in DOSFS_GetUnixFileName().
Cache last used directory in DOSFS_FindNext() to avoid quadratic
search time.
* [files/drive.c]
New format for drives configuration in wine.conf; allows
specifying the type, label and serial number of a drive.
* [files/file.c]
New function FILE_OpenUnixFile to make sure we don't open a
directory instead of a file.
Fixed DOSFS_GetUnixFileName() check_last flag in FILE_MakeDir().
* [files/profile.c]
Rewrote profile handling. Should be closer to Windows behavior now.
New function PROFILE_GetWineIniString() to get a string from wine.conf.
Support environment variables in wine.conf.
* [loader/task.c]
Fixed the order of deletion in TASK_DeleteTask() to avoid memory
corruption.
* [memory/global.c]
Create a discarded block on GlobalAlloc() if the size is 0; thanks
to John Harvey for noticing this.
* [memory/local.c]
LOCAL_GetHeap: make sure the pointer is valid before checking
magic number.
* [misc/main.c]
Moved profile and registry saving to ExitWindows(), so we don't
try to save them in case of a crash.
* [miscemu/int21.c]
INT21_GetFreeDiskSpace: try to compute the cluster size from the
filesystem size instead of hard-coding it to 64.
Fixed functions 0x3f and 0x40 to use _hread and _hwrite to allow
reading or writing 65535 bytes (thanks to Bruce Milner for this one).
* [windows/message.c]
Fixed bug in linked-list handling in MSG_DeleteQueue().
Simplified SetMessageQueue().
* [wine.ini] [wine.man]
Updated for new drives configuration format.
Tue Jan 30 11:24:46 1996 William Magro <wmagro@tc.cornell.edu>
* [controls/edit.c]
Implemented ES_PASSWORD style, EM_SETPASSWORDCHAR and
EM_GETPASSWORDCHAR messages.
* [controls/widgets.c]
Adjusted class creation flags to better match values Windows uses.
* [include/windows.h]
Fixed ES_NOHIDESEL typo.
* [loader/ne_image.c]
Added detection for zero offset in RADDR fixups. Quicken
was in an infinite loop here.
Mon Jan 29 20:12:22 1996 Albrecht Kleine <kleine@ak.sax.de>
* [files/dos_fs.c]
Bugfix: range error in month value (0..11 set to 1..12).
* [windows/caret.c]
Changed ROP2-mode to R2_NOTXORPEN in CARET_Callback for pulsed
appearance of the caret.
* [windows/mdi.c] [include/mdi.h]
Changed MDITile(): added a new parameter WORD wParam for
WM_MDITILE second tiling method (MDITILE_HORIZONTAL in wParam) as
used in Win3.1
Sun Jan 28 14:20:00 1996 Cameron Heide <heide@ee.ualberta.ca>
* [miscemu/int2f.c]
Added a small bit of MSCDEX emulation.
* [windows/alias.c]
ALIAS_RegisterAlias was returning the hash value when it should
have been returning the record number.
Sat Jan 27 10:53:51 1996 Jim Peterson <jspeter@birch.ee.vt.edu>
* [include/shell.h] [include/wintypes.h]
Moved definition of HKEY and LPHKEY types to include/wintypes.h.
Declared FONTENUMPROC in wintypes.h.
* [include/windows.h]
Added definition of KERNINGPAIR and LPKERNINGPAIR types. Added
declarations for CopyCursor(), CopyIcon(), EnumFontFamilies(),
ExtractIcon(), FatalAppExit(), FindExecutable(), GetClipCursor(),
GetKerningPairs(), GetQueueStatus(), GetRasterizerCaps(),
IsGDIObject(), IsMenu(), IsTask(), RegCloseKey(), RegCreateKey(),
RegDeleteKey(), RegEnumKey(), RegOpenKey(), RegQueryValue(),
RegSetValue(), ResetDC(), ShellExecute(), SystemParametersInfo(),
and wsprintf().
* [tools/makehtml.pl] [documentation/apiw.index]
New files that scan windows.h, commdlg.h, and toolhelp.h and output
an HTML sorted list with optional links to www.willows.com and a
tally of unimplemented APIW functions.
* [objects/cursoricon.c]
Added Win32 versions of CopyIcon() and CopyCursor() for use in
libwine.
* [win32/resource.c] [win32/winprocs.c]
Added '#include "libres.h"' and explicit declarations of windows
procs in order to avoid warnings.
* [windows/utility.c]
Added Win32 version of MulDiv() for libwine.
* [*/*] [include/windows.h]
Changed several function declarations to comply more strictly to
the windows API (without, hopefully, altering their functionality).
* [controls/menu.c]
Made the return value of CheckMenuItem be the previous state of
the menu item if it was found, otherwise -1 as specified in the
SDK. This conflicts with the APIW specification, which says it
should return TRUE if successful, otherwise FALSE.
* [include/windows.h]
Added obsolete WM_SIZE message wParam names for compatibility.
Added WinHelp() command constants, even though they are not yet
supported.
* [rc/winerc.c]
Tidied up transform_binary_file(). In argument checking, flattened
any invalid characters specified with the prefix argument.
* [library/libres.c]
Made FindResource() case-insensitive when parameter 'name' is a string.
Sat Jan 27 02:30 1996 Uwe Bonnes <bon@elektron.ikp.physik.th-darmstadt.de
* [files/drive.c]
If root "/" is given in wine.conf, use it as last resort.
* [files/file.c]
Report ER_AccessDenied it disk ist not writable
More Debug Output
* [miscemu/int21.c]
Squeezed some bugs in ExtendedOpenCreateFile
* [windows/winpos.c]
Some windows may not be moved or resized. We are missing some
structures to be exact, but the approach should help in some cases
and make things worse in much fewer.
Fri Jan 26 10:24:00 1996 Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>
* [loader/pe_image.c]
fixup_imports: Find builtins for Borland style entries, too
Fri Jan 26 10:24:00 1996 Martin von Loewis <loewis@informatik.hu-berlin.de>
* [controls/menu.c]
LoadMenu: branch to Win32 for PE modules
* [if1632/gdi.spec][if1632/kernel32.spec][if1632/user32.spec]
DeleteObject, GetPixel, SetPixel,WritePrivateProfileStringA,
WriteProfileStringA, EmptyClipboard, EnableMenuItem, EnableScrollBar,
EnableWindow, InvalidateRect, SetWindowTextA, WinHelpA: new relays
DrawTextA, MoveToEx, GetClientRect, InvalidateRect, LoadBitmapA/W,
LoadAcceleratorsA/W, LoadMenu[Indirect]A/W, LoadStringA/W: changed
to convert parameters or naming convention
* [include/kernel32.h][include/wintypes.h]
moved WCHAR, defined LPWSTR
* [include/string32.h][win32/string32.c][include/struct32.h]
New files
* [loader/module.h]
LoadModule: exit after returning from PE_LoadModule
* [loader/pe_image.c]
my_wcstombs: isascii does not work on Linux for Unicode
PE_LoadImage: Handle directories
* [misc/user32.c]
USER32_RECT32to16, USER32_RECT16to32: new functions
implemented new user32 relays
* [misc/newfns.c]
WIN32_WinHelpA: new function
* [win32/param32.c]
New file
* [win32/resource.c]
GetResDirEntry: added support for named entries
WIN32_LoadAcceleratorsW: invoke *32 resource functions
WIN32_LoadBitmapA: convert name to unicode if appropriate
WIN32_ParseMenu: new function
implemented new resource functions from user32.spec
Wed Jan 24 18:09:00 1996 Alex Korobka <alex@phm30.pharm.sunysb.edu>
* [objects/cursoricon.c]
GetIconId() and LoadIconHandler() functions.
* [windows/mdi.c]
Better maximization support, TranslateMDISysAccel() function,
misc improvements.
* [windows/defwnd.c]
Fix for WM_WINDOWPOSCHANGED message handler.
* [windows/winpos.c]
Rewrote WindowFromPoint() function.
Sun Jan 21 1996 17:05:09 Marcus Meissner <msmeissn@faui01.informatik.uni-erlangen.de>
* [include/toolhelp.h] [misc/toolhelp.c]
Added Notify(Un)Register, but no callbacks yet.
Fri Jan 19 01:43:37 1996 Victor Schneider <root@tailor.roman.org>
* [Makefile.in]
Added target for libwine.so.1.0.
* [library/winmain.c]
For WINELIBDLL, _WinMain just returns hInstance instead of calling
WinMain().
* [misc/main.c]
For WINELIBDLL, renamed main() to _wine_main() for calling from the
stub main function.
* [library/winestub.c] (new file)
Provides a stub main() function for using libwine.so.
Tue Jan 16 11:04:34 1996 Anand Kumria <akumria@ozemail.com.au>
* [winsocket.c]
Fix EPERM problem.
* [global.c]
Attempt to do some sanity checking in MemManInfo().
* [Changelog]
Fix changelog oversight for previous entry.
1996-01-31 20:02:28 +01:00
|
|
|
*/
|
1993-09-04 12:09:32 +02:00
|
|
|
|
2011-11-17 16:55:16 +01:00
|
|
|
#include <limits.h>
|
2003-09-06 01:08:26 +02:00
|
|
|
#include <stdarg.h>
|
1993-09-04 12:09:32 +02:00
|
|
|
#include <stdlib.h>
|
Release 940405
Tue Apr 5 14:36:59 1994 Bob Amstadt (bob@pooh)
* [include/mdi.h] [windows/mdi.c]
Use WM_PARENTNOTIFY messages to activate children.
Generate WM_CHILDACTIVATE messages.
Beginnings handler for maxmized child window.
Clean up when children are destroyed.
* [windows/message.c] [windows/nonclient.c] [windows/winpos.c]
Removed code add 94/03/26.
Apr 4, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
* [control/menu.c]
Make mouse menu navigation working again. :-))
(be carefull, clicking outside menus (ie.: clientrect)
not resolved yet)
* [windows/nonclient.c] [controls/scroll.c]
Bugs fix in NCTrackScrollBars().
* [misc/dos_fs.c]
Bug fix in 'ToDos()' in conversion for '/',
(example: '/window/' was translated to 'WINDOWs').
* [miscemu/int21.c]
Function ChangeDir() extract possible drive before DOS_ChangeDir().
* [loader/library.c] [loader/wine.c]
Playing around moving function GetProcAddress() and put some code in.
Mon Apr 4 21:39:07 1994 Alexandre Julliard (julliard@lamisun.epfl.ch)
* [misc/main.c]
Better explanation of command-line options.
* [objects/dib.c]
Implemented SetDIBitsToDevice().
* [windows/dc.c]
Bug fix in SetDCState().
* [windows/event.c]
Removed WS_DISABLED handling (now done in message.c).
* [windows/message.c]
Added sending a WM_PARENTNOTIFY message in MSG_TranslateMouseMsg().
Use WindowFromPoint() to find the window for mouse events, taking
into account disabled windows.
* [windows/painting.c]
Bug fix in BeginPaint() to allow calling it at other times than
on WM_PAINT (Solitaire needs it...)
* [windows/win.c]
Implemented FindWindow().
Rewritten EnableWindow() to behave more like Windows.
* [windows/winpos.c]
Rewritten WindowFromPoint() to also search child windows.
Mon Apr 4 17:36:32 1994 Erik Bos (erik@trashcan.hacktic.nl)
* [include/int21.h] -> [msdos.h]
renamed.
* [miscemu/int10.h] [miscemu/int25.h] [miscemu/int26.h]
new, added for int 10, 25 and 26.
* [miscemu/ioports.c]
new, added to allow win apps to use ioports.
* [loader/signal.c]
Added support for in, inb, out, outb instructions.
Sun Mar 27 13:40:25 1994 Bob Amstadt (bob@pooh)
* controls/menu.c (InsertMenu): Changed to use FindMenuItem().
Sat Mar 26 21:23:55 1994 Bob Amstadt (bob@pooh)
* [windows/mdi.c]
Window list properly updated.
* [windows/message.c]
Call WINPOS_ChildActivate() when mouse pressed.
* [windows/nonclient.c]
Use WINPOS_IsAnActiveWindow() instead of GetActiveWindow() in
NC_HandleNCPaint().
* [windows/winpos.c]
Created functions WINPOS_IsAnActiveWindow() and WINPOS_ActivateChild()
Thu Mar 24 14:49:17 1994 Bob Amstadt (bob@pooh)
* controls/menu.c (DeleteMenu): Changed to use FindMenuItem
(DeleteMenu): Many bug fixes.
* [controls/menu.c]
Created function FindMenuItem().
Thu Mar 24 14:17:24 1994 Bob Amstadt (bob@pooh)
* [windows/win.c]
Removed incorrect MDI handling code from CreateWindowEx().
* [controls/menu.c]
MF_STRING items needed to allocate a private copy of string.
* [controls/menu.c]
Fixed buggy calls to GlobalFree().
* [memory/global.c]
Eliminated some redundant code with function call.
Wed Mar 23 1994 Pentti Moilanen (pentti.moilanen@ntc.nokia.com)
* [windows/timer.c]
timer list pointers looped in InsertTimer
Tue Mar 29 13:32:08 MET DST 1994 julliard@di.epfl.ch (Alexandre Julliard)
* [misc/cursor.c]
A few changes for desktop window support.
* [misc/main.c]
Added -depth option.
* [misc/rect.c]
Yet another bug fix in SubtractRect().
* [objects/bitmap.c]
Changes to use only one depth (specified with -depth)
for color bitmaps.
* [objects/brush.c]
Added support for dithered solid brushes.
* [objects/color.c]
Use the same 20 system colors as in Windows.
System palette initialisation now done in COLOR_InitPalette().
Added support for a color mapping table to map logical color
indexes to X colormap entries.
Implemented GetNearestColor() and RealizeDefaultPalette().
* [objects/dib.c]
Added support for color mapping table.
* [objects/dither.c] (New file)
Implemented solid color dithering.
* [objects/palette.c]
Implemented GetSystemPaletteEntries() and SelectPalette().
* [windows/class.c]
Make a copy of the menu name in RegisterClass().
* [windows/dc.c]
Fixed device caps when using a desktop window.
Added support for the color mapping table in DCs.
* [windows/event.c]
Added ConfigureNotify handler on desktop window.
* [windows/message.c]
Removed call to XTranslateCoordinates() on every mouse motion
New function MSG_Synchronize() to synchronize with the X server.
* [windows/syscolor.c]
Rewritten SYSCOLOR_Init() to read the system colors from WIN.INI.
* [windows/winpos.c]
Added synchronization on window mapping. Solves the double redraw
problem when starting Solitaire.
Mar 27, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
* [control/menu.c] * [windows/defwnd.c]
Make keyboard navigation working with menubar,
but temporarely inserted a bug in menubar mouse handling ... :-((
(it will be fix next week !)
* [windows/defwnd.c]
Connect VK_MENU to menubar navigation.
* [loader/library.c]
GetModuleHandle() return 'fictive 0xF000+ handles' for built-in DLLs.
Sun Mar 20 22:32:13 1994 Erik Bos (erik@trashcan.hacktic.nl)
* [misc/main.c]
Added Copy(). Added a check for `-h' to show usage.
* [misc/dos_fs.c]
Fixed bug in FindFile(), to load directories as dlls.
* [misc/dos_fs.c]
Fixed ToUnix() and ToDos() again, as my previous patch
didn't make it.
* [misc/dos_fs.c] [miscemu/int21.c]
Bug fixes, should be able to handle all winfile and progman int21
requests now except for a few small things.
Tue Mar 29 06:25:54 1994 crw@harris.mlb.semi.harris.com (Carl Williams)
* [memory/heap.c]
Implemented GetFreeSystemResources().
Mon Mar 21 17:32:25 1994 Bob Amstadt (bob@pooh)
* controls/menu.c (GetSubMenu): Function did not return correct value
* [windows/mdi.c]
Beginnings of menu handling.
Thu Mar 10 11:32:06 1994 Stefan (SAM) Muenzel (muenzel@tat.physik.uni-tuebingen.de)
* [objects/font.c]
if font.width equals zero use asterix instead.
Mon Mar 21 17:23:37 MET 1994 julliard@di.epfl.ch (Alexandre Julliard)
* [objects/bitmap.c]
Rewritten bitmap code to use exclusively X pixmaps; *much* faster.
* [objects/brush.c]
Some changes with pattern brushes because of the new bitmap code.
* [objects/color.c]
Added function COLOR_ToPhysical for better color mapping.
* [objects/dib.c]
Heavily optimized SetDIBits().
* [windows/dc.c]
Opimized SetDCState() and DC_SetupGC*() functions.
Added stub for CreateIC().
Mar 20, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
* [misc/message.c]
Call SetFocus() after closing box to give back focus to previous owner.
* [misc/files.c]
Small bug fix in GetTempFilename() : replace a '\' to '\\'.
* [control/scroll.c]
Calls to BitBlt() replace by StretchBlt().
* [control/menu.c]
Call SetFocus() to previous owner after closing Popups.
Fill stub DeleteMenu().
* [control/listbox.c]
* [control/combo.c]
Use SetFocus() in WM_LBUTTONDOWN.
Close ComboBox List upon WM_KILLFOCUS.
Early development of WM_MEASUREITEM mecanism.
* [windows/defwnd.c]
Early development of WM_MEASUREITEM mecanism.
Tue Mar 22 10:44:57 1994 Miguel de Icaza (miguel@xochitl)
* [misc/atom.c]
Fixed sintaxis problem when building the library.
Tue Mar 15 13:11:56 1994 Bob Amstadt (bob@pooh)
* [include/windows.h]
Added message types and structures for MDI
* [include/mdi.h]
Created internal structures for handling MDI
* [windows/mdi.c]
Began creating MDI support
Thu Mar 10 16:51:46 1994 Bob Amstadt (bob@pooh)
* [loader/wine.c] [include/wine.h]
Added new field to "struct w_files" to hold the "name table"
resource for Windows 3.0 programs
* [loader/resource.c]
Added code to handle programs with a "name table" resource.
LoadResourceByName() modified to check for the existence of
this resource.
Mon Mar 14 22:31:42 MET 1994 julliard@di.epfl.ch (Alexandre Julliard)
* [objects/color.c]
Added installing the private colormap on the desktop window.
* [windows/event.c]
Cleaned up focus event handling (see focus.c).
Use GetFocus() to direct key events to the correct window.
* [windows/focus.c]
Rewritten SetFocus() to:
- only set X focus on top-level windows
- send WM_SETFOCUS and WM_KILLFOCUS messages (was done in event.c)
- prevent setting focus to disabled windows
- install private colormap so -privatemap option works again
* [windows/message.c] [windows/timer.c]
Changed timer management to no longer use PostMessage(), but
to generate timer messages on the fly. Also fixed a related bug
in GetMessage() which could cause busy-waiting.
* [windows/win.c]
Only select focus events on top-level windows.
* [windows/winpos.c]
Added some sanity checks for desktop window.
Fri Mar 4 20:42:01 1994 Erik Bos (erik@trashcan.hacktic.nl)
* [misc/dos_fs.c]
bug fixes in ToUnix(), WinIniFileName(), GetUnixFileName().
Support for tilde symbol added for rootdirectories in [drives]
section of wine's configfile.
* [misc/file.c]
hread(), hwrite() added.
* [misc/main.c]
hmemcpy() added.
* [if1632/stress.spec] [include/stress.h] [misc/stress.c]
Added STRESS.DLL, an useless dll used to stress a windows system.
* [*/*]
Added missing #includes, fixed prototypes for prototype checking.
* [include/prototypes.h]
Added prototypes for loader/*c, if1632/*c.
Tue Mar 8 09:54:34 1994 Bob Amstadt (bob@pooh)
* [Configure]
Added reminder to set WINEPATH, if it is not set.
* [Imakefile]
Removed #elif's
* [controls/button.c]
Added BN_CLICKED notification for owner-draw buttons.
* [if1632/kernel.spec] [memory/heap.c]
Changed Local* functions to WIN16_Local* to prevent unconcious use
of these functions.
* [if1632/relay.c]
Push old Stack16Frame on stack before setting.
* [include/atom.h] [misc/atom.c] [include/heap.h] [memory/local.c]
Added multiple local heap handling in Atom* functions.
* [include/regfunc.h] [miscemu/int21.c]
Rewrote DOS3Call() use context frame that is already on the stack.
* [misc/profile.c]
Fixed to allow leading ";" to mark comments.
* [misc/spy.c]
Fixed bugs and added support for "include" and "exclude" filters.
* [misc/user.c]
Rearranged calls in InitApp().
* [misc/font.c]
Fixed font handling to create system fonts, if they are used.
* [windows/dc.c]
If text drawn on window with no font specified, then default the
font to the system font.
Mon Mar 7 20:32:09 MET 1994 julliard@di.epfl.ch (Alexandre Julliard)
* [controls/desktop.c]
Added handling of WM_NCCREATE and WM_ERASEBKGND functions.
Implemented SetDeskPattern().
* [misc/main.c]
Added -desktop option to get a large desktop window with
everything inside it.
Added -name option.
* [misc/rect.c]
Bug fix in SubtractRect().
* [objects/*.c]
Replaced the DefaultRootWindow() macro by the rootWindow variable.
* [windows/event.c] [windows/message.c]
[windows/nonclient.c] [windows/win.c]
A few changes to accomodate the new desktop window.
Tue Mar 8 11:13:03 1994 Miguel de Icaza (miguel@xochitl.nuclecu.unam.mx)
* [toolkit/arch.c] --New file--
Routines for converting little endian data structures to
big-endian data structures, currently only BITMAP structures are
converted.
* [misc/atom.c]
When used as part of the WineLib, the code is much simpler.
Doesn't depend on alignement.
* [loader/wine.c]
Ifdefed Emulator dependent code if compiling WineLib.
* [loader/resource.c]
Moved misc/resource.c to loader/resource.c.
* [loader/dump.c,ldt.c,ldtlib.c,library,c,selector.c,signal.c]
Ifdefed whole code if compiling WINELIB.
* [include/winsock.h]
Added compilation define to allow compilation on SunOS.
* [include/wine.h]
Removed load_typeinfo and load_nameinfo prototypes, they belong
to neexe.h
* [include/neexe.h]
Added load_typeinfo and load_nameinfo prototypes.
* [include/arch.h]
Fixed some bugs in the conversion routines.
Added macros for Bitmap loading.
Tue Mar 8 12:52:05 1994 crw@maniac.mlb.semi.harris.com (Carl Williams)
* [if1632/kernel.spec] [memory/global.c]
Implemented GetFreeSpace()
* [if1632/user.spec] [loader/resource.c]
Implemented CreateIcon()
1994-04-05 23:42:43 +02:00
|
|
|
#include <string.h>
|
2001-09-12 22:21:06 +02:00
|
|
|
#include <assert.h>
|
2000-11-28 23:40:56 +01:00
|
|
|
#include "winerror.h"
|
2003-09-06 01:08:26 +02:00
|
|
|
#include "windef.h"
|
2003-08-20 20:22:31 +02:00
|
|
|
#include "winbase.h"
|
2000-11-28 23:40:56 +01:00
|
|
|
#include "winnls.h"
|
2011-12-02 15:11:51 +01:00
|
|
|
#include "winternl.h"
|
2012-10-30 14:22:16 +01:00
|
|
|
#include "winreg.h"
|
2021-07-09 15:28:26 +02:00
|
|
|
#include "ntgdi_private.h"
|
2010-08-02 08:35:04 +02:00
|
|
|
#include "wine/exception.h"
|
2019-09-26 16:17:03 +02:00
|
|
|
#include "wine/heap.h"
|
2020-11-03 11:28:20 +01:00
|
|
|
#include "wine/rbtree.h"
|
2002-03-10 00:29:33 +01:00
|
|
|
#include "wine/debug.h"
|
1993-09-04 12:09:32 +02:00
|
|
|
|
2002-03-10 00:29:33 +01:00
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(font);
|
1999-04-19 16:56:29 +02:00
|
|
|
|
2020-09-30 16:08:21 +02:00
|
|
|
static HKEY wine_fonts_key;
|
2020-11-03 11:26:39 +01:00
|
|
|
static HKEY wine_fonts_cache_key;
|
2020-09-30 16:08:21 +02:00
|
|
|
|
2020-10-20 22:05:37 +02:00
|
|
|
struct font_physdev
|
|
|
|
{
|
|
|
|
struct gdi_physdev dev;
|
|
|
|
struct gdi_font *font;
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline struct font_physdev *get_font_dev( PHYSDEV dev )
|
|
|
|
{
|
|
|
|
return (struct font_physdev *)dev;
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:20:50 +01:00
|
|
|
struct gdi_font_family
|
|
|
|
{
|
2020-11-13 10:05:55 +01:00
|
|
|
struct wine_rb_entry name_entry;
|
|
|
|
struct wine_rb_entry second_name_entry;
|
2020-11-04 09:20:50 +01:00
|
|
|
unsigned int refcount;
|
|
|
|
WCHAR family_name[LF_FACESIZE];
|
|
|
|
WCHAR second_name[LF_FACESIZE];
|
|
|
|
struct list faces;
|
|
|
|
struct gdi_font_family *replacement;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct gdi_font_face
|
|
|
|
{
|
|
|
|
struct list entry;
|
|
|
|
unsigned int refcount;
|
|
|
|
WCHAR *style_name;
|
|
|
|
WCHAR *full_name;
|
|
|
|
WCHAR *file;
|
|
|
|
void *data_ptr;
|
|
|
|
SIZE_T data_size;
|
|
|
|
UINT face_index;
|
|
|
|
FONTSIGNATURE fs;
|
|
|
|
DWORD ntmFlags;
|
|
|
|
DWORD version;
|
|
|
|
DWORD flags; /* ADDFONT flags */
|
|
|
|
BOOL scalable;
|
|
|
|
struct bitmap_font_size size; /* set if face is a bitmap */
|
|
|
|
struct gdi_font_family *family;
|
|
|
|
struct gdi_font_enum_data *cached_enum_data;
|
2020-11-27 15:38:02 +01:00
|
|
|
struct wine_rb_entry full_name_entry;
|
2020-11-04 09:20:50 +01:00
|
|
|
};
|
|
|
|
|
2020-10-20 22:05:37 +02:00
|
|
|
static const struct font_backend_funcs *font_funcs;
|
|
|
|
|
2020-10-22 11:56:47 +02:00
|
|
|
static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
|
|
|
|
|
2020-11-03 11:25:30 +01:00
|
|
|
static UINT font_smoothing = GGO_BITMAP;
|
|
|
|
static UINT subpixel_orientation = GGO_GRAY4_BITMAP;
|
|
|
|
static BOOL antialias_fakes = TRUE;
|
2020-11-06 12:10:54 +01:00
|
|
|
static struct font_gamma_ramp font_gamma_ramp;
|
2020-11-03 11:25:30 +01:00
|
|
|
|
2020-11-03 11:27:21 +01:00
|
|
|
static void add_face_to_cache( struct gdi_font_face *face );
|
2020-11-03 11:26:39 +01:00
|
|
|
static void remove_face_from_cache( struct gdi_font_face *face );
|
|
|
|
|
2020-11-23 13:20:50 +01:00
|
|
|
static inline WCHAR facename_tolower( WCHAR c )
|
|
|
|
{
|
|
|
|
if (c >= 'A' && c <= 'Z') return c - 'A' + 'a';
|
|
|
|
else if (c > 127) return RtlDowncaseUnicodeChar( c );
|
|
|
|
else return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int facename_compare( const WCHAR *str1, const WCHAR *str2, SIZE_T len )
|
|
|
|
{
|
|
|
|
while (len--)
|
|
|
|
{
|
|
|
|
WCHAR c1 = facename_tolower( *str1++ ), c2 = facename_tolower( *str2++ );
|
|
|
|
if (c1 != c2) return c1 - c2;
|
|
|
|
else if (!c1) return 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-01-15 01:35:38 +01:00
|
|
|
/* Device -> World size conversion */
|
|
|
|
|
|
|
|
/* Performs a device to world transformation on the specified width (which
|
|
|
|
* is in integer format).
|
|
|
|
*/
|
|
|
|
static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
|
|
|
|
{
|
2008-05-22 17:43:01 +02:00
|
|
|
double floatWidth;
|
2004-01-15 01:35:38 +01:00
|
|
|
|
|
|
|
/* Perform operation with floating point */
|
2008-05-22 17:43:01 +02:00
|
|
|
floatWidth = (double)width * dc->xformVport2World.eM11;
|
2004-01-15 01:35:38 +01:00
|
|
|
/* Round to integers */
|
|
|
|
return GDI_ROUND(floatWidth);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Performs a device to world transformation on the specified size (which
|
|
|
|
* is in integer format).
|
|
|
|
*/
|
|
|
|
static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
|
|
|
|
{
|
2008-05-22 17:43:01 +02:00
|
|
|
double floatHeight;
|
2004-01-15 01:35:38 +01:00
|
|
|
|
|
|
|
/* Perform operation with floating point */
|
2008-05-22 17:43:01 +02:00
|
|
|
floatHeight = (double)height * dc->xformVport2World.eM22;
|
2004-01-15 01:35:38 +01:00
|
|
|
/* Round to integers */
|
|
|
|
return GDI_ROUND(floatHeight);
|
|
|
|
}
|
|
|
|
|
2013-09-11 18:31:01 +02:00
|
|
|
/* scale width and height but don't mirror them */
|
|
|
|
|
|
|
|
static inline INT width_to_LP( DC *dc, INT width )
|
|
|
|
{
|
|
|
|
return GDI_ROUND( (double)width * fabs( dc->xformVport2World.eM11 ));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline INT height_to_LP( DC *dc, INT height )
|
|
|
|
{
|
|
|
|
return GDI_ROUND( (double)height * fabs( dc->xformVport2World.eM22 ));
|
|
|
|
}
|
|
|
|
|
2005-08-23 11:38:58 +02:00
|
|
|
static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
|
|
|
|
{
|
|
|
|
POINT pt[2];
|
|
|
|
pt[0].x = pt[0].y = 0;
|
|
|
|
pt[1].x = 0;
|
|
|
|
pt[1].y = height;
|
2016-07-18 12:32:56 +02:00
|
|
|
lp_to_dp(dc, pt, 2);
|
2005-08-23 11:38:58 +02:00
|
|
|
return pt[1].y - pt[0].y;
|
|
|
|
}
|
2004-01-15 01:35:38 +01:00
|
|
|
|
2020-10-27 10:27:20 +01:00
|
|
|
static inline BOOL is_win9x(void)
|
|
|
|
{
|
|
|
|
return GetVersion() & 0x80000000;
|
|
|
|
}
|
|
|
|
|
2020-10-21 11:03:51 +02:00
|
|
|
static inline WCHAR *strdupW( const WCHAR *p )
|
|
|
|
{
|
|
|
|
WCHAR *ret;
|
2020-11-05 10:44:16 +01:00
|
|
|
DWORD len = (lstrlenW(p) + 1) * sizeof(WCHAR);
|
2020-10-21 11:03:51 +02:00
|
|
|
ret = HeapAlloc(GetProcessHeap(), 0, len);
|
|
|
|
memcpy(ret, p, len);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-01-27 16:30:43 +01:00
|
|
|
static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
|
2009-01-27 16:19:37 +01:00
|
|
|
static BOOL FONT_DeleteObject( HGDIOBJ handle );
|
2002-05-31 20:43:22 +02:00
|
|
|
|
2020-10-20 22:05:37 +02:00
|
|
|
static const struct gdi_obj_funcs fontobj_funcs =
|
2002-05-31 20:43:22 +02:00
|
|
|
{
|
|
|
|
FONT_GetObjectW, /* pGetObjectW */
|
|
|
|
NULL, /* pUnrealizeObject */
|
|
|
|
FONT_DeleteObject /* pDeleteObject */
|
|
|
|
};
|
|
|
|
|
2002-06-04 03:02:51 +02:00
|
|
|
typedef struct
|
|
|
|
{
|
2021-06-30 17:36:19 +02:00
|
|
|
struct gdi_obj_header obj;
|
|
|
|
LOGFONTW logfont;
|
2002-06-04 03:02:51 +02:00
|
|
|
} FONTOBJ;
|
|
|
|
|
2021-09-01 14:09:04 +02:00
|
|
|
/* for translate_charset_info */
|
|
|
|
static const CHARSETINFO charset_info[] = {
|
1999-01-01 19:41:22 +01:00
|
|
|
/* ANSI */
|
2008-01-14 12:38:59 +01:00
|
|
|
{ ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
|
|
|
|
{ EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
|
|
|
|
{ RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
|
|
|
|
{ GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
|
|
|
|
{ TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
|
|
|
|
{ HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
|
|
|
|
{ ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
|
|
|
|
{ BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
|
|
|
|
{ VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
|
1999-01-01 19:41:22 +01:00
|
|
|
/* reserved by ANSI */
|
2008-01-14 12:38:59 +01:00
|
|
|
{ DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
|
|
|
|
{ DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
|
|
|
|
{ DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
|
|
|
|
{ DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
|
|
|
|
{ DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
|
|
|
|
{ DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
|
|
|
|
{ DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
|
1999-01-01 19:41:22 +01:00
|
|
|
/* ANSI and OEM */
|
2008-01-14 12:38:59 +01:00
|
|
|
{ THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
|
|
|
|
{ SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
|
|
|
|
{ GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
|
|
|
|
{ HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
|
|
|
|
{ CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
|
|
|
|
{ JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
|
1999-01-01 19:41:22 +01:00
|
|
|
/* reserved for alternate ANSI and OEM */
|
2008-01-14 12:38:59 +01:00
|
|
|
{ DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
|
|
|
|
{ DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
|
|
|
|
{ DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
|
|
|
|
{ DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
|
|
|
|
{ DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
|
|
|
|
{ DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
|
|
|
|
{ DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
|
|
|
|
{ DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
|
1999-01-01 19:41:22 +01:00
|
|
|
/* reserved for system */
|
2008-01-14 12:38:59 +01:00
|
|
|
{ DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
|
|
|
|
{ SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
|
1999-01-01 19:41:22 +01:00
|
|
|
};
|
|
|
|
|
2020-11-04 09:16:19 +01:00
|
|
|
static const WCHAR * const default_serif_list[3] =
|
2020-11-03 11:25:47 +01:00
|
|
|
{
|
2020-11-06 12:08:16 +01:00
|
|
|
L"Times New Roman",
|
|
|
|
L"Liberation Serif",
|
|
|
|
L"Bitstream Vera Serif"
|
2020-11-03 11:25:47 +01:00
|
|
|
};
|
2020-11-04 09:16:19 +01:00
|
|
|
static const WCHAR * const default_fixed_list[3] =
|
2020-11-03 11:25:47 +01:00
|
|
|
{
|
2020-11-06 12:08:16 +01:00
|
|
|
L"Courier New",
|
|
|
|
L"Liberation Mono",
|
|
|
|
L"Bitstream Vera Sans Mono"
|
2020-11-03 11:25:47 +01:00
|
|
|
};
|
2020-11-04 09:16:19 +01:00
|
|
|
static const WCHAR * const default_sans_list[3] =
|
2020-11-03 11:25:47 +01:00
|
|
|
{
|
2020-11-06 12:08:16 +01:00
|
|
|
L"Arial",
|
|
|
|
L"Liberation Sans",
|
|
|
|
L"Bitstream Vera Sans"
|
2020-11-03 11:25:47 +01:00
|
|
|
};
|
2020-11-13 10:05:55 +01:00
|
|
|
static WCHAR ff_roman_default[LF_FACESIZE];
|
|
|
|
static WCHAR ff_modern_default[LF_FACESIZE];
|
|
|
|
static WCHAR ff_swiss_default[LF_FACESIZE];
|
2020-11-03 11:25:47 +01:00
|
|
|
|
2020-09-30 16:08:21 +02:00
|
|
|
static const struct nls_update_font_list
|
|
|
|
{
|
|
|
|
UINT ansi_cp, oem_cp;
|
|
|
|
const char *oem, *fixed, *system;
|
|
|
|
const char *courier, *serif, *small, *sserif_96, *sserif_120;
|
|
|
|
/* these are for font substitutes */
|
|
|
|
const char *shelldlg, *tmsrmn;
|
|
|
|
const char *fixed_0, *system_0, *courier_0, *serif_0, *small_0, *sserif_0, *helv_0, *tmsrmn_0;
|
|
|
|
struct subst { const char *from, *to; } arial_0, courier_new_0, times_new_roman_0;
|
|
|
|
} nls_update_font_list[] =
|
|
|
|
{
|
|
|
|
/* Latin 1 (United States) */
|
|
|
|
{ 1252, 437, "vgaoem.fon", "vgafix.fon", "vgasys.fon",
|
|
|
|
"coure.fon", "serife.fon", "smalle.fon", "sserife.fon", "sseriff.fon",
|
|
|
|
"Tahoma","Times New Roman"
|
|
|
|
},
|
|
|
|
/* Latin 1 (Multilingual) */
|
|
|
|
{ 1252, 850, "vga850.fon", "vgafix.fon", "vgasys.fon",
|
|
|
|
"coure.fon", "serife.fon", "smalle.fon", "sserife.fon", "sseriff.fon",
|
|
|
|
"Tahoma","Times New Roman" /* FIXME unverified */
|
|
|
|
},
|
|
|
|
/* Eastern Europe */
|
|
|
|
{ 1250, 852, "vga852.fon", "vgafixe.fon", "vgasyse.fon",
|
|
|
|
"couree.fon", "serifee.fon", "smallee.fon", "sserifee.fon", "sseriffe.fon",
|
|
|
|
"Tahoma","Times New Roman", /* FIXME unverified */
|
|
|
|
"Fixedsys,238", "System,238",
|
|
|
|
"Courier New,238", "MS Serif,238", "Small Fonts,238",
|
|
|
|
"MS Sans Serif,238", "MS Sans Serif,238", "MS Serif,238",
|
|
|
|
{ "Arial CE,0", "Arial,238" },
|
|
|
|
{ "Courier New CE,0", "Courier New,238" },
|
|
|
|
{ "Times New Roman CE,0", "Times New Roman,238" }
|
|
|
|
},
|
|
|
|
/* Cyrillic */
|
|
|
|
{ 1251, 866, "vga866.fon", "vgafixr.fon", "vgasysr.fon",
|
|
|
|
"courer.fon", "serifer.fon", "smaller.fon", "sserifer.fon", "sseriffr.fon",
|
|
|
|
"Tahoma","Times New Roman", /* FIXME unverified */
|
|
|
|
"Fixedsys,204", "System,204",
|
|
|
|
"Courier New,204", "MS Serif,204", "Small Fonts,204",
|
|
|
|
"MS Sans Serif,204", "MS Sans Serif,204", "MS Serif,204",
|
|
|
|
{ "Arial Cyr,0", "Arial,204" },
|
|
|
|
{ "Courier New Cyr,0", "Courier New,204" },
|
|
|
|
{ "Times New Roman Cyr,0", "Times New Roman,204" }
|
|
|
|
},
|
|
|
|
/* Greek */
|
|
|
|
{ 1253, 737, "vga869.fon", "vgafixg.fon", "vgasysg.fon",
|
|
|
|
"coureg.fon", "serifeg.fon", "smalleg.fon", "sserifeg.fon", "sseriffg.fon",
|
|
|
|
"Tahoma","Times New Roman", /* FIXME unverified */
|
|
|
|
"Fixedsys,161", "System,161",
|
|
|
|
"Courier New,161", "MS Serif,161", "Small Fonts,161",
|
|
|
|
"MS Sans Serif,161", "MS Sans Serif,161", "MS Serif,161",
|
|
|
|
{ "Arial Greek,0", "Arial,161" },
|
|
|
|
{ "Courier New Greek,0", "Courier New,161" },
|
|
|
|
{ "Times New Roman Greek,0", "Times New Roman,161" }
|
|
|
|
},
|
|
|
|
/* Turkish */
|
|
|
|
{ 1254, 857, "vga857.fon", "vgafixt.fon", "vgasyst.fon",
|
|
|
|
"couret.fon", "serifet.fon", "smallet.fon", "sserifet.fon", "sserifft.fon",
|
|
|
|
"Tahoma","Times New Roman", /* FIXME unverified */
|
|
|
|
"Fixedsys,162", "System,162",
|
|
|
|
"Courier New,162", "MS Serif,162", "Small Fonts,162",
|
|
|
|
"MS Sans Serif,162", "MS Sans Serif,162", "MS Serif,162",
|
|
|
|
{ "Arial Tur,0", "Arial,162" },
|
|
|
|
{ "Courier New Tur,0", "Courier New,162" },
|
|
|
|
{ "Times New Roman Tur,0", "Times New Roman,162" }
|
|
|
|
},
|
|
|
|
/* Hebrew */
|
|
|
|
{ 1255, 862, "vgaoem.fon", "vgaf1255.fon", "vgas1255.fon",
|
|
|
|
"coue1255.fon", "sere1255.fon", "smae1255.fon", "ssee1255.fon", "ssef1255.fon",
|
|
|
|
"Tahoma","Times New Roman", /* FIXME unverified */
|
|
|
|
"Fixedsys,177", "System,177",
|
|
|
|
"Courier New,177", "MS Serif,177", "Small Fonts,177",
|
|
|
|
"MS Sans Serif,177", "MS Sans Serif,177", "MS Serif,177"
|
|
|
|
},
|
|
|
|
/* Arabic */
|
|
|
|
{ 1256, 720, "vgaoem.fon", "vgaf1256.fon", "vgas1256.fon",
|
|
|
|
"coue1256.fon", "sere1256.fon", "smae1256.fon", "ssee1256.fon", "ssef1256.fon",
|
|
|
|
"Microsoft Sans Serif","Times New Roman",
|
|
|
|
"Fixedsys,178", "System,178",
|
|
|
|
"Courier New,178", "MS Serif,178", "Small Fonts,178",
|
|
|
|
"MS Sans Serif,178", "MS Sans Serif,178", "MS Serif,178"
|
|
|
|
},
|
|
|
|
/* Baltic */
|
|
|
|
{ 1257, 775, "vga775.fon", "vgaf1257.fon", "vgas1257.fon",
|
|
|
|
"coue1257.fon", "sere1257.fon", "smae1257.fon", "ssee1257.fon", "ssef1257.fon",
|
|
|
|
"Tahoma","Times New Roman", /* FIXME unverified */
|
|
|
|
"Fixedsys,186", "System,186",
|
|
|
|
"Courier New,186", "MS Serif,186", "Small Fonts,186",
|
|
|
|
"MS Sans Serif,186", "MS Sans Serif,186", "MS Serif,186",
|
|
|
|
{ "Arial Baltic,0", "Arial,186" },
|
|
|
|
{ "Courier New Baltic,0", "Courier New,186" },
|
|
|
|
{ "Times New Roman Baltic,0", "Times New Roman,186" }
|
|
|
|
},
|
|
|
|
/* Vietnamese */
|
|
|
|
{ 1258, 1258, "vga850.fon", "vgafix.fon", "vgasys.fon",
|
|
|
|
"coure.fon", "serife.fon", "smalle.fon", "sserife.fon", "sseriff.fon",
|
|
|
|
"Tahoma","Times New Roman" /* FIXME unverified */
|
|
|
|
},
|
|
|
|
/* Thai */
|
|
|
|
{ 874, 874, "vga850.fon", "vgaf874.fon", "vgas874.fon",
|
|
|
|
"coure.fon", "serife.fon", "smalle.fon", "ssee874.fon", "ssef874.fon",
|
|
|
|
"Tahoma","Times New Roman" /* FIXME unverified */
|
|
|
|
},
|
|
|
|
/* Japanese */
|
|
|
|
{ 932, 932, "vga932.fon", "jvgafix.fon", "jvgasys.fon",
|
|
|
|
"coure.fon", "serife.fon", "jsmalle.fon", "sserife.fon", "sseriff.fon",
|
|
|
|
"MS UI Gothic","MS Serif"
|
|
|
|
},
|
|
|
|
/* Chinese Simplified */
|
|
|
|
{ 936, 936, "vga936.fon", "svgafix.fon", "svgasys.fon",
|
|
|
|
"coure.fon", "serife.fon", "smalle.fon", "sserife.fon", "sseriff.fon",
|
|
|
|
"SimSun", "NSimSun"
|
|
|
|
},
|
|
|
|
/* Korean */
|
|
|
|
{ 949, 949, "vga949.fon", "hvgafix.fon", "hvgasys.fon",
|
|
|
|
"coure.fon", "serife.fon", "smalle.fon", "sserife.fon", "sseriff.fon",
|
|
|
|
"Gulim", "Batang"
|
|
|
|
},
|
|
|
|
/* Chinese Traditional */
|
|
|
|
{ 950, 950, "vga950.fon", "cvgafix.fon", "cvgasys.fon",
|
|
|
|
"coure.fon", "serife.fon", "smalle.fon", "sserife.fon", "sseriff.fon",
|
|
|
|
"PMingLiU", "MingLiU"
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline BOOL is_dbcs_ansi_cp(UINT ansi_cp)
|
|
|
|
{
|
|
|
|
return ( ansi_cp == 932 /* CP932 for Japanese */
|
|
|
|
|| ansi_cp == 936 /* CP936 for Chinese Simplified */
|
|
|
|
|| ansi_cp == 949 /* CP949 for Korean */
|
|
|
|
|| ansi_cp == 950 ); /* CP950 for Chinese Traditional */
|
|
|
|
}
|
|
|
|
|
2020-10-31 16:13:33 +01:00
|
|
|
static CRITICAL_SECTION font_cs;
|
2020-10-22 11:54:35 +02:00
|
|
|
static CRITICAL_SECTION_DEBUG critsect_debug =
|
|
|
|
{
|
|
|
|
0, 0, &font_cs,
|
|
|
|
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
|
|
|
|
0, 0, { (DWORD_PTR)(__FILE__ ": font_cs") }
|
|
|
|
};
|
2020-10-31 16:13:33 +01:00
|
|
|
static CRITICAL_SECTION font_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
|
2020-10-22 11:54:35 +02:00
|
|
|
|
2020-10-26 12:03:21 +01:00
|
|
|
#ifndef WINE_FONT_DIR
|
|
|
|
#define WINE_FONT_DIR "fonts"
|
|
|
|
#endif
|
|
|
|
|
2020-10-29 11:10:30 +01:00
|
|
|
#ifdef WORDS_BIGENDIAN
|
|
|
|
#define GET_BE_WORD(x) (x)
|
|
|
|
#define GET_BE_DWORD(x) (x)
|
|
|
|
#else
|
|
|
|
#define GET_BE_WORD(x) RtlUshortByteSwap(x)
|
|
|
|
#define GET_BE_DWORD(x) RtlUlongByteSwap(x)
|
|
|
|
#endif
|
|
|
|
|
2020-10-27 10:27:32 +01:00
|
|
|
static void get_fonts_data_dir_path( const WCHAR *file, WCHAR *path )
|
2020-10-26 12:03:21 +01:00
|
|
|
{
|
2020-11-06 12:08:16 +01:00
|
|
|
if (GetEnvironmentVariableW( L"WINEDATADIR", path, MAX_PATH ))
|
|
|
|
lstrcatW( path, L"\\" WINE_FONT_DIR "\\" );
|
|
|
|
else if (GetEnvironmentVariableW( L"WINEBUILDDIR", path, MAX_PATH ))
|
|
|
|
lstrcatW( path, L"\\fonts\\" );
|
2020-10-26 12:03:21 +01:00
|
|
|
|
2020-11-05 10:44:16 +01:00
|
|
|
lstrcatW( path, file );
|
|
|
|
if (path[5] == ':') memmove( path, path + 4, (lstrlenW(path) - 3) * sizeof(WCHAR) );
|
2020-10-26 12:03:21 +01:00
|
|
|
else path[1] = '\\'; /* change \??\ to \\?\ */
|
|
|
|
}
|
|
|
|
|
2020-10-27 10:27:20 +01:00
|
|
|
static void get_fonts_win_dir_path( const WCHAR *file, WCHAR *path )
|
2020-10-26 12:03:21 +01:00
|
|
|
{
|
|
|
|
GetWindowsDirectoryW( path, MAX_PATH );
|
2020-11-06 12:08:16 +01:00
|
|
|
lstrcatW( path, L"\\fonts\\" );
|
2020-11-05 10:44:16 +01:00
|
|
|
lstrcatW( path, file );
|
2020-10-26 12:03:21 +01:00
|
|
|
}
|
|
|
|
|
2020-10-30 14:15:34 +01:00
|
|
|
/* font substitutions */
|
|
|
|
|
|
|
|
struct gdi_font_subst
|
|
|
|
{
|
|
|
|
struct list entry;
|
|
|
|
int from_charset;
|
|
|
|
int to_charset;
|
|
|
|
WCHAR names[1];
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct list font_subst_list = LIST_INIT(font_subst_list);
|
|
|
|
|
|
|
|
static inline WCHAR *get_subst_to_name( struct gdi_font_subst *subst )
|
|
|
|
{
|
2020-11-05 10:44:16 +01:00
|
|
|
return subst->names + lstrlenW( subst->names ) + 1;
|
2020-10-30 14:15:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void dump_gdi_font_subst(void)
|
|
|
|
{
|
|
|
|
struct gdi_font_subst *subst;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY( subst, &font_subst_list, struct gdi_font_subst, entry )
|
|
|
|
{
|
|
|
|
if (subst->from_charset != -1 || subst->to_charset != -1)
|
|
|
|
TRACE("%s,%d -> %s,%d\n", debugstr_w(subst->names),
|
|
|
|
subst->from_charset, debugstr_w(get_subst_to_name(subst)), subst->to_charset);
|
|
|
|
else
|
|
|
|
TRACE("%s -> %s\n", debugstr_w(subst->names), debugstr_w(get_subst_to_name(subst)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:20:26 +01:00
|
|
|
static const WCHAR *get_gdi_font_subst( const WCHAR *from_name, int from_charset, int *to_charset )
|
2020-10-30 14:15:34 +01:00
|
|
|
{
|
|
|
|
struct gdi_font_subst *subst;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY( subst, &font_subst_list, struct gdi_font_subst, entry )
|
|
|
|
{
|
2020-11-23 13:20:50 +01:00
|
|
|
if (!facename_compare( subst->names, from_name, -1 ) &&
|
2020-10-30 14:15:34 +01:00
|
|
|
(subst->from_charset == from_charset || subst->from_charset == -1))
|
|
|
|
{
|
|
|
|
if (to_charset) *to_charset = subst->to_charset;
|
|
|
|
return get_subst_to_name( subst );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-10-30 14:22:51 +01:00
|
|
|
static BOOL add_gdi_font_subst( const WCHAR *from_name, int from_charset, const WCHAR *to_name, int to_charset )
|
2020-10-30 14:15:34 +01:00
|
|
|
{
|
|
|
|
struct gdi_font_subst *subst;
|
2020-11-05 10:44:16 +01:00
|
|
|
int len = lstrlenW( from_name ) + lstrlenW( to_name ) + 2;
|
2020-10-30 14:15:34 +01:00
|
|
|
|
|
|
|
if (get_gdi_font_subst( from_name, from_charset, NULL )) return FALSE; /* already exists */
|
|
|
|
|
|
|
|
if (!(subst = HeapAlloc( GetProcessHeap(), 0,
|
|
|
|
offsetof( struct gdi_font_subst, names[len] ))))
|
|
|
|
return FALSE;
|
2020-11-05 10:44:16 +01:00
|
|
|
lstrcpyW( subst->names, from_name );
|
|
|
|
lstrcpyW( get_subst_to_name(subst), to_name );
|
2020-10-30 14:15:34 +01:00
|
|
|
subst->from_charset = from_charset;
|
|
|
|
subst->to_charset = to_charset;
|
|
|
|
list_add_tail( &font_subst_list, &subst->entry );
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2020-10-31 10:19:08 +01:00
|
|
|
static void load_gdi_font_subst(void)
|
2020-10-30 14:15:34 +01:00
|
|
|
{
|
|
|
|
HKEY hkey;
|
|
|
|
DWORD i = 0, type, dlen, vlen;
|
|
|
|
WCHAR value[64], data[64], *p;
|
|
|
|
|
2020-11-06 12:08:16 +01:00
|
|
|
if (RegOpenKeyW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes",
|
2020-10-30 14:15:34 +01:00
|
|
|
&hkey)) return;
|
|
|
|
|
|
|
|
dlen = sizeof(data);
|
|
|
|
vlen = ARRAY_SIZE(value);
|
|
|
|
while (!RegEnumValueW( hkey, i++, value, &vlen, NULL, &type, (BYTE *)data, &dlen ))
|
|
|
|
{
|
|
|
|
int from_charset = -1, to_charset = -1;
|
|
|
|
|
|
|
|
TRACE("Got %s=%s\n", debugstr_w(value), debugstr_w(data));
|
2020-11-05 10:44:16 +01:00
|
|
|
if ((p = wcsrchr( value, ',' )) && p[1])
|
2020-10-30 14:15:34 +01:00
|
|
|
{
|
|
|
|
*p++ = 0;
|
2020-11-05 10:44:16 +01:00
|
|
|
from_charset = wcstol( p, NULL, 10 );
|
2020-10-30 14:15:34 +01:00
|
|
|
}
|
2020-11-05 10:44:16 +01:00
|
|
|
if ((p = wcsrchr( data, ',' )) && p[1])
|
2020-10-30 14:15:34 +01:00
|
|
|
{
|
|
|
|
*p++ = 0;
|
2020-11-05 10:44:16 +01:00
|
|
|
to_charset = wcstol( p, NULL, 10 );
|
2020-10-30 14:15:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Win 2000 doesn't allow mapping between different charsets
|
|
|
|
or mapping of DEFAULT_CHARSET */
|
|
|
|
if ((!from_charset || to_charset == from_charset) && to_charset != DEFAULT_CHARSET)
|
|
|
|
add_gdi_font_subst( value, from_charset, data, to_charset );
|
|
|
|
|
|
|
|
/* reset dlen and vlen */
|
|
|
|
dlen = sizeof(data);
|
|
|
|
vlen = ARRAY_SIZE(value);
|
|
|
|
}
|
|
|
|
RegCloseKey( hkey );
|
|
|
|
}
|
|
|
|
|
2020-10-30 14:22:51 +01:00
|
|
|
/* font families */
|
|
|
|
|
2020-11-13 10:05:55 +01:00
|
|
|
static int family_namecmp( const WCHAR *str1, const WCHAR *str2 )
|
|
|
|
{
|
|
|
|
int prio1, prio2, vert1 = (str1[0] == '@' ? 1 : 0), vert2 = (str2[0] == '@' ? 1 : 0);
|
|
|
|
|
2020-11-23 13:20:50 +01:00
|
|
|
if (!facename_compare( str1, ff_swiss_default, LF_FACESIZE - 1 )) prio1 = 0;
|
|
|
|
else if (!facename_compare( str1, ff_modern_default, LF_FACESIZE - 1 )) prio1 = 1;
|
|
|
|
else if (!facename_compare( str1, ff_roman_default, LF_FACESIZE - 1 )) prio1 = 2;
|
2020-11-13 10:05:55 +01:00
|
|
|
else prio1 = 3;
|
|
|
|
|
2020-11-23 13:20:50 +01:00
|
|
|
if (!facename_compare( str2, ff_swiss_default, LF_FACESIZE - 1 )) prio2 = 0;
|
|
|
|
else if (!facename_compare( str2, ff_modern_default, LF_FACESIZE - 1 )) prio2 = 1;
|
|
|
|
else if (!facename_compare( str2, ff_roman_default, LF_FACESIZE - 1 )) prio2 = 2;
|
2020-11-13 10:05:55 +01:00
|
|
|
else prio2 = 3;
|
|
|
|
|
|
|
|
if (prio1 != prio2) return prio1 - prio2;
|
|
|
|
if (vert1 != vert2) return vert1 - vert2;
|
2020-11-23 13:20:50 +01:00
|
|
|
return facename_compare( str1 + vert1, str2 + vert2, LF_FACESIZE - 1 );
|
2020-11-13 10:05:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static int family_name_compare( const void *key, const struct wine_rb_entry *entry )
|
|
|
|
{
|
|
|
|
const struct gdi_font_family *family = WINE_RB_ENTRY_VALUE( entry, const struct gdi_font_family, name_entry );
|
|
|
|
return family_namecmp( (const WCHAR *)key, family->family_name );
|
|
|
|
}
|
|
|
|
|
|
|
|
static int family_second_name_compare( const void *key, const struct wine_rb_entry *entry )
|
|
|
|
{
|
|
|
|
const struct gdi_font_family *family = WINE_RB_ENTRY_VALUE( entry, const struct gdi_font_family, second_name_entry );
|
|
|
|
return family_namecmp( (const WCHAR *)key, family->second_name );
|
|
|
|
}
|
|
|
|
|
2020-11-27 15:38:02 +01:00
|
|
|
static int face_full_name_compare( const void *key, const struct wine_rb_entry *entry )
|
|
|
|
{
|
|
|
|
const struct gdi_font_face *face = WINE_RB_ENTRY_VALUE( entry, const struct gdi_font_face, full_name_entry );
|
|
|
|
return facename_compare( (const WCHAR *)key, face->full_name, LF_FULLFACESIZE - 1 );
|
|
|
|
}
|
|
|
|
|
2020-11-13 10:05:55 +01:00
|
|
|
static struct wine_rb_tree family_name_tree = { family_name_compare };
|
|
|
|
static struct wine_rb_tree family_second_name_tree = { family_second_name_compare };
|
2020-11-27 15:38:02 +01:00
|
|
|
static struct wine_rb_tree face_full_name_tree = { face_full_name_compare };
|
|
|
|
|
|
|
|
static int face_is_in_full_name_tree( const struct gdi_font_face *face )
|
|
|
|
{
|
|
|
|
return face->full_name_entry.parent || face_full_name_tree.root == &face->full_name_entry;
|
|
|
|
}
|
2020-10-30 14:22:51 +01:00
|
|
|
|
2020-11-03 11:27:21 +01:00
|
|
|
static struct gdi_font_family *create_family( const WCHAR *name, const WCHAR *second_name )
|
2020-10-30 14:22:51 +01:00
|
|
|
{
|
|
|
|
struct gdi_font_family *family = HeapAlloc( GetProcessHeap(), 0, sizeof(*family) );
|
|
|
|
|
|
|
|
family->refcount = 1;
|
|
|
|
lstrcpynW( family->family_name, name, LF_FACESIZE );
|
2020-12-14 16:54:55 +01:00
|
|
|
if (second_name && second_name[0] && wcsicmp( name, second_name ))
|
2020-10-30 14:22:51 +01:00
|
|
|
{
|
|
|
|
lstrcpynW( family->second_name, second_name, LF_FACESIZE );
|
|
|
|
add_gdi_font_subst( second_name, -1, name, -1 );
|
|
|
|
}
|
|
|
|
else family->second_name[0] = 0;
|
|
|
|
list_init( &family->faces );
|
2020-10-30 14:39:07 +01:00
|
|
|
family->replacement = NULL;
|
2020-11-13 10:05:55 +01:00
|
|
|
wine_rb_put( &family_name_tree, family->family_name, &family->name_entry );
|
|
|
|
if (family->second_name[0]) wine_rb_put( &family_second_name_tree, family->second_name, &family->second_name_entry );
|
2020-10-30 14:22:51 +01:00
|
|
|
return family;
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:12:24 +01:00
|
|
|
static void release_family( struct gdi_font_family *family )
|
2020-10-30 14:22:51 +01:00
|
|
|
{
|
|
|
|
if (--family->refcount) return;
|
|
|
|
assert( list_empty( &family->faces ));
|
2020-11-13 10:05:55 +01:00
|
|
|
wine_rb_remove( &family_name_tree, &family->name_entry );
|
|
|
|
if (family->second_name[0]) wine_rb_remove( &family_second_name_tree, &family->second_name_entry );
|
2020-10-30 14:39:07 +01:00
|
|
|
if (family->replacement) release_family( family->replacement );
|
2020-10-30 14:22:51 +01:00
|
|
|
HeapFree( GetProcessHeap(), 0, family );
|
|
|
|
}
|
|
|
|
|
2020-11-03 11:27:21 +01:00
|
|
|
static struct gdi_font_family *find_family_from_name( const WCHAR *name )
|
2020-10-30 14:22:51 +01:00
|
|
|
{
|
2020-11-13 10:05:55 +01:00
|
|
|
struct wine_rb_entry *entry;
|
|
|
|
if (!(entry = wine_rb_get( &family_name_tree, name ))) return NULL;
|
|
|
|
return WINE_RB_ENTRY_VALUE( entry, struct gdi_font_family, name_entry );
|
2020-10-30 14:22:51 +01:00
|
|
|
}
|
|
|
|
|
2020-11-04 09:15:06 +01:00
|
|
|
static struct gdi_font_family *find_family_from_any_name( const WCHAR *name )
|
2020-10-30 14:22:51 +01:00
|
|
|
{
|
2020-11-13 10:05:55 +01:00
|
|
|
struct wine_rb_entry *entry;
|
2020-10-30 14:22:51 +01:00
|
|
|
struct gdi_font_family *family;
|
2020-11-13 10:05:55 +01:00
|
|
|
if ((family = find_family_from_name( name ))) return family;
|
|
|
|
if (!(entry = wine_rb_get( &family_second_name_tree, name ))) return NULL;
|
|
|
|
return WINE_RB_ENTRY_VALUE( entry, struct gdi_font_family, second_name_entry );
|
2020-10-30 14:22:51 +01:00
|
|
|
}
|
|
|
|
|
2020-11-27 15:38:02 +01:00
|
|
|
static struct gdi_font_face *find_face_from_full_name( const WCHAR *full_name )
|
|
|
|
{
|
|
|
|
struct wine_rb_entry *entry;
|
|
|
|
if (!(entry = wine_rb_get( &face_full_name_tree, full_name ))) return NULL;
|
|
|
|
return WINE_RB_ENTRY_VALUE( entry, struct gdi_font_face, full_name_entry );
|
|
|
|
}
|
|
|
|
|
2020-10-31 10:19:08 +01:00
|
|
|
static const struct list *get_family_face_list( const struct gdi_font_family *family )
|
|
|
|
{
|
|
|
|
return family->replacement ? &family->replacement->faces : &family->faces;
|
|
|
|
}
|
|
|
|
|
2020-11-13 10:05:56 +01:00
|
|
|
static struct gdi_font_face *family_find_face_from_filename( struct gdi_font_family *family, const WCHAR *file_name )
|
|
|
|
{
|
|
|
|
struct gdi_font_face *face;
|
|
|
|
const WCHAR *file;
|
|
|
|
LIST_FOR_EACH_ENTRY( face, get_family_face_list(family), struct gdi_font_face, entry )
|
|
|
|
{
|
|
|
|
if (!face->file) continue;
|
|
|
|
file = wcsrchr(face->file, '\\');
|
|
|
|
if (!file) file = face->file;
|
|
|
|
else file++;
|
|
|
|
if (wcsicmp( file, file_name )) continue;
|
|
|
|
face->refcount++;
|
|
|
|
return face;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-10-31 10:19:08 +01:00
|
|
|
static struct gdi_font_face *find_face_from_filename( const WCHAR *file_name, const WCHAR *family_name )
|
|
|
|
{
|
|
|
|
struct gdi_font_family *family;
|
|
|
|
struct gdi_font_face *face;
|
|
|
|
|
|
|
|
TRACE( "looking for file %s name %s\n", debugstr_w(file_name), debugstr_w(family_name) );
|
|
|
|
|
2020-11-13 10:05:56 +01:00
|
|
|
if (!family_name)
|
2020-10-31 10:19:08 +01:00
|
|
|
{
|
2020-11-13 10:05:56 +01:00
|
|
|
WINE_RB_FOR_EACH_ENTRY( family, &family_name_tree, struct gdi_font_family, name_entry )
|
|
|
|
if ((face = family_find_face_from_filename( family, file_name ))) return face;
|
|
|
|
return NULL;
|
2020-10-31 10:19:08 +01:00
|
|
|
}
|
2020-11-13 10:05:56 +01:00
|
|
|
|
|
|
|
if (!(family = find_family_from_name( family_name ))) return NULL;
|
|
|
|
return family_find_face_from_filename( family, file_name );
|
2020-10-31 10:19:08 +01:00
|
|
|
}
|
|
|
|
|
2020-10-30 14:38:02 +01:00
|
|
|
static BOOL add_family_replacement( const WCHAR *new_name, const WCHAR *replace )
|
|
|
|
{
|
|
|
|
struct gdi_font_family *new_family, *family;
|
|
|
|
struct gdi_font_face *face;
|
|
|
|
WCHAR new_name_vert[LF_FACESIZE], replace_vert[LF_FACESIZE];
|
|
|
|
|
|
|
|
if (!(family = find_family_from_any_name( replace )))
|
|
|
|
{
|
|
|
|
TRACE( "%s is not available. Skip this replacement.\n", debugstr_w(replace) );
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(new_family = create_family( new_name, NULL ))) return FALSE;
|
2020-10-30 14:39:07 +01:00
|
|
|
new_family->replacement = family;
|
|
|
|
family->refcount++;
|
2020-10-30 14:38:02 +01:00
|
|
|
TRACE( "mapping %s to %s\n", debugstr_w(replace), debugstr_w(new_name) );
|
|
|
|
|
|
|
|
/* also add replacement for vertical font if necessary */
|
|
|
|
if (replace[0] == '@') return TRUE;
|
|
|
|
if (list_empty( &family->faces )) return TRUE;
|
|
|
|
face = LIST_ENTRY( list_head(&family->faces), struct gdi_font_face, entry );
|
|
|
|
if (!(face->fs.fsCsb[0] & FS_DBCS_MASK)) return TRUE;
|
|
|
|
|
|
|
|
new_name_vert[0] = '@';
|
|
|
|
lstrcpynW( new_name_vert + 1, new_name, LF_FACESIZE - 1 );
|
|
|
|
if (find_family_from_any_name( new_name_vert )) return TRUE; /* already exists */
|
|
|
|
|
|
|
|
replace_vert[0] = '@';
|
|
|
|
lstrcpynW( replace_vert + 1, replace, LF_FACESIZE - 1 );
|
|
|
|
add_family_replacement( new_name_vert, replace_vert );
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The replacement list is a way to map an entire font
|
|
|
|
* family onto another family. For example adding
|
|
|
|
*
|
|
|
|
* [HKCU\Software\Wine\Fonts\Replacements]
|
|
|
|
* "Wingdings"="Winedings"
|
|
|
|
*
|
|
|
|
* would enumerate the Winedings font both as Winedings and
|
|
|
|
* Wingdings. However if a real Wingdings font is present the
|
|
|
|
* replacement does not take place.
|
|
|
|
*/
|
2020-10-31 10:19:08 +01:00
|
|
|
static void load_gdi_font_replacements(void)
|
2020-10-30 14:38:02 +01:00
|
|
|
{
|
|
|
|
HKEY hkey;
|
|
|
|
DWORD i = 0, type, dlen, vlen;
|
|
|
|
WCHAR value[LF_FACESIZE], data[1024];
|
|
|
|
|
|
|
|
/* @@ Wine registry key: HKCU\Software\Wine\Fonts\Replacements */
|
2020-11-06 12:08:16 +01:00
|
|
|
if (RegOpenKeyW( wine_fonts_key, L"Replacements", &hkey )) return;
|
2020-10-30 14:38:02 +01:00
|
|
|
|
|
|
|
dlen = sizeof(data);
|
|
|
|
vlen = ARRAY_SIZE(value);
|
|
|
|
while (!RegEnumValueW( hkey, i++, value, &vlen, NULL, &type, (BYTE *)data, &dlen ))
|
|
|
|
{
|
|
|
|
/* "NewName"="Oldname" */
|
|
|
|
if (!find_family_from_any_name( value ))
|
|
|
|
{
|
|
|
|
if (type == REG_MULTI_SZ)
|
|
|
|
{
|
|
|
|
WCHAR *replace = data;
|
|
|
|
while (*replace)
|
|
|
|
{
|
|
|
|
if (add_family_replacement( value, replace )) break;
|
2020-11-05 10:44:16 +01:00
|
|
|
replace += lstrlenW(replace) + 1;
|
2020-10-30 14:38:02 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (type == REG_SZ) add_family_replacement( value, data );
|
|
|
|
}
|
|
|
|
else TRACE("%s is available. Skip this replacement.\n", debugstr_w(value));
|
|
|
|
|
|
|
|
/* reset dlen and vlen */
|
|
|
|
dlen = sizeof(data);
|
|
|
|
vlen = ARRAY_SIZE(value);
|
|
|
|
}
|
|
|
|
RegCloseKey( hkey );
|
|
|
|
}
|
|
|
|
|
2020-10-31 10:21:00 +01:00
|
|
|
static void dump_gdi_font_list(void)
|
|
|
|
{
|
|
|
|
struct gdi_font_family *family;
|
|
|
|
struct gdi_font_face *face;
|
|
|
|
|
2020-11-13 10:05:55 +01:00
|
|
|
WINE_RB_FOR_EACH_ENTRY( family, &family_name_tree, struct gdi_font_family, name_entry )
|
2020-10-31 10:21:00 +01:00
|
|
|
{
|
|
|
|
TRACE( "Family: %s\n", debugstr_w(family->family_name) );
|
|
|
|
LIST_FOR_EACH_ENTRY( face, &family->faces, struct gdi_font_face, entry )
|
|
|
|
{
|
|
|
|
TRACE( "\t%s\t%s\t%08x", debugstr_w(face->style_name), debugstr_w(face->full_name),
|
|
|
|
face->fs.fsCsb[0] );
|
|
|
|
if (!face->scalable) TRACE(" %d", face->size.height );
|
|
|
|
TRACE("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:16:19 +01:00
|
|
|
static BOOL enum_fallbacks( DWORD pitch_and_family, int index, WCHAR buffer[LF_FACESIZE] )
|
|
|
|
{
|
|
|
|
if (index < 3)
|
|
|
|
{
|
|
|
|
const WCHAR * const *defaults;
|
|
|
|
|
|
|
|
if ((pitch_and_family & FIXED_PITCH) || (pitch_and_family & 0xf0) == FF_MODERN)
|
|
|
|
defaults = default_fixed_list;
|
|
|
|
else if ((pitch_and_family & 0xf0) == FF_ROMAN)
|
|
|
|
defaults = default_serif_list;
|
|
|
|
else
|
|
|
|
defaults = default_sans_list;
|
|
|
|
lstrcpynW( buffer, defaults[index], LF_FACESIZE );
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return font_funcs->enum_family_fallbacks( pitch_and_family, index - 3, buffer );
|
|
|
|
}
|
|
|
|
|
2020-11-13 10:05:55 +01:00
|
|
|
static void set_default_family( DWORD pitch_and_family, WCHAR *default_name )
|
2020-11-03 11:25:47 +01:00
|
|
|
{
|
2020-11-13 10:05:55 +01:00
|
|
|
struct wine_rb_entry *entry;
|
2020-11-04 09:16:19 +01:00
|
|
|
WCHAR name[LF_FACESIZE];
|
|
|
|
int i = 0;
|
2020-11-03 11:25:47 +01:00
|
|
|
|
2020-11-04 09:16:19 +01:00
|
|
|
while (enum_fallbacks( pitch_and_family, i++, name ))
|
2020-11-03 11:25:47 +01:00
|
|
|
{
|
2020-11-13 10:05:55 +01:00
|
|
|
if (!(entry = wine_rb_get( &family_name_tree, name ))) continue;
|
|
|
|
wine_rb_remove( &family_name_tree, entry );
|
|
|
|
lstrcpynW( default_name, name, LF_FACESIZE - 1 );
|
|
|
|
wine_rb_put( &family_name_tree, name, entry );
|
2020-11-04 09:16:19 +01:00
|
|
|
return;
|
2020-11-03 11:25:47 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void reorder_font_list(void)
|
|
|
|
{
|
2020-11-13 10:05:55 +01:00
|
|
|
set_default_family( FF_ROMAN, ff_roman_default );
|
|
|
|
set_default_family( FF_MODERN, ff_modern_default );
|
|
|
|
set_default_family( FF_SWISS, ff_swiss_default );
|
2020-11-03 11:25:47 +01:00
|
|
|
}
|
|
|
|
|
2020-11-04 09:12:24 +01:00
|
|
|
static void release_face( struct gdi_font_face *face )
|
2020-11-03 11:26:39 +01:00
|
|
|
{
|
|
|
|
if (--face->refcount) return;
|
|
|
|
if (face->family)
|
|
|
|
{
|
|
|
|
if (face->flags & ADDFONT_ADD_TO_CACHE) remove_face_from_cache( face );
|
|
|
|
list_remove( &face->entry );
|
|
|
|
release_family( face->family );
|
|
|
|
}
|
2020-11-27 15:38:02 +01:00
|
|
|
if (face_is_in_full_name_tree( face )) wine_rb_remove( &face_full_name_tree, &face->full_name_entry );
|
2020-11-03 11:26:39 +01:00
|
|
|
HeapFree( GetProcessHeap(), 0, face->file );
|
|
|
|
HeapFree( GetProcessHeap(), 0, face->style_name );
|
|
|
|
HeapFree( GetProcessHeap(), 0, face->full_name );
|
|
|
|
HeapFree( GetProcessHeap(), 0, face->cached_enum_data );
|
|
|
|
HeapFree( GetProcessHeap(), 0, face );
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:12:24 +01:00
|
|
|
static int remove_font( const WCHAR *file, DWORD flags )
|
|
|
|
{
|
|
|
|
struct gdi_font_family *family, *family_next;
|
|
|
|
struct gdi_font_face *face, *face_next;
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
EnterCriticalSection( &font_cs );
|
2020-11-13 10:05:55 +01:00
|
|
|
WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR( family, family_next, &family_name_tree, struct gdi_font_family, name_entry )
|
2020-11-04 09:12:24 +01:00
|
|
|
{
|
|
|
|
family->refcount++;
|
|
|
|
LIST_FOR_EACH_ENTRY_SAFE( face, face_next, &family->faces, struct gdi_font_face, entry )
|
|
|
|
{
|
|
|
|
if (!face->file) continue;
|
|
|
|
if (LOWORD(face->flags) != LOWORD(flags)) continue;
|
2020-11-05 10:44:16 +01:00
|
|
|
if (!wcsicmp( face->file, file ))
|
2020-11-04 09:12:24 +01:00
|
|
|
{
|
|
|
|
TRACE( "removing matching face %s refcount %d\n", debugstr_w(face->file), face->refcount );
|
|
|
|
release_face( face );
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
release_family( family );
|
|
|
|
}
|
|
|
|
LeaveCriticalSection( &font_cs );
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2020-11-03 11:26:39 +01:00
|
|
|
static inline BOOL faces_equal( const struct gdi_font_face *f1, const struct gdi_font_face *f2 )
|
|
|
|
{
|
2020-11-23 13:20:50 +01:00
|
|
|
if (facename_compare( f1->full_name, f2->full_name, -1 )) return FALSE;
|
2020-11-03 11:26:39 +01:00
|
|
|
if (f1->scalable) return TRUE;
|
|
|
|
if (f1->size.y_ppem != f2->size.y_ppem) return FALSE;
|
|
|
|
return !memcmp( &f1->fs, &f2->fs, sizeof(f1->fs) );
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int style_order( const struct gdi_font_face *face )
|
|
|
|
{
|
|
|
|
switch (face->ntmFlags & (NTM_REGULAR | NTM_BOLD | NTM_ITALIC))
|
|
|
|
{
|
|
|
|
case NTM_REGULAR:
|
|
|
|
return 0;
|
|
|
|
case NTM_BOLD:
|
|
|
|
return 1;
|
|
|
|
case NTM_ITALIC:
|
|
|
|
return 2;
|
|
|
|
case NTM_BOLD | NTM_ITALIC:
|
|
|
|
return 3;
|
|
|
|
default:
|
|
|
|
WARN( "Don't know how to order face %s with flags 0x%08x\n",
|
|
|
|
debugstr_w(face->full_name), face->ntmFlags );
|
|
|
|
return 9999;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-03 11:27:21 +01:00
|
|
|
static BOOL insert_face_in_family_list( struct gdi_font_face *face, struct gdi_font_family *family )
|
2020-11-03 11:26:39 +01:00
|
|
|
{
|
|
|
|
struct gdi_font_face *cursor;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY( cursor, &family->faces, struct gdi_font_face, entry )
|
|
|
|
{
|
|
|
|
if (faces_equal( face, cursor ))
|
|
|
|
{
|
|
|
|
TRACE( "Already loaded face %s in family %s, original version %x, new version %x\n",
|
|
|
|
debugstr_w(face->full_name), debugstr_w(family->family_name),
|
|
|
|
cursor->version, face->version );
|
|
|
|
|
2021-01-11 23:11:33 +01:00
|
|
|
if (face->file && cursor->file && !wcsicmp( face->file, cursor->file ))
|
2020-11-03 11:26:39 +01:00
|
|
|
{
|
|
|
|
cursor->refcount++;
|
|
|
|
TRACE("Font %s already in list, refcount now %d\n",
|
|
|
|
debugstr_w(face->file), cursor->refcount);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (face->version <= cursor->version)
|
|
|
|
{
|
|
|
|
TRACE("Original font %s is newer so skipping %s\n",
|
|
|
|
debugstr_w(cursor->file), debugstr_w(face->file));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TRACE("Replacing original %s with %s\n",
|
|
|
|
debugstr_w(cursor->file), debugstr_w(face->file));
|
|
|
|
list_add_before( &cursor->entry, &face->entry );
|
|
|
|
face->family = family;
|
|
|
|
family->refcount++;
|
|
|
|
face->refcount++;
|
2020-11-27 15:38:02 +01:00
|
|
|
if (face_is_in_full_name_tree( cursor ))
|
|
|
|
{
|
|
|
|
wine_rb_replace( &face_full_name_tree, &cursor->full_name_entry, &face->full_name_entry );
|
|
|
|
memset( &cursor->full_name_entry, 0, sizeof(cursor->full_name_entry) );
|
|
|
|
}
|
2020-11-03 11:26:39 +01:00
|
|
|
release_face( cursor );
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (style_order( face ) < style_order( cursor )) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
TRACE( "Adding face %s in family %s from %s\n", debugstr_w(face->full_name),
|
|
|
|
debugstr_w(family->family_name), debugstr_w(face->file) );
|
|
|
|
list_add_before( &cursor->entry, &face->entry );
|
2020-11-27 15:38:02 +01:00
|
|
|
if (face->scalable) wine_rb_put( &face_full_name_tree, face->full_name, &face->full_name_entry );
|
2020-11-03 11:26:39 +01:00
|
|
|
face->family = family;
|
|
|
|
family->refcount++;
|
|
|
|
face->refcount++;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2020-11-03 11:27:21 +01:00
|
|
|
static struct gdi_font_face *create_face( struct gdi_font_family *family, const WCHAR *style,
|
|
|
|
const WCHAR *fullname, const WCHAR *file,
|
|
|
|
void *data_ptr, SIZE_T data_size, UINT index, FONTSIGNATURE fs,
|
|
|
|
DWORD ntmflags, DWORD version, DWORD flags,
|
|
|
|
const struct bitmap_font_size *size )
|
|
|
|
{
|
|
|
|
struct gdi_font_face *face = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*face) );
|
|
|
|
|
|
|
|
face->refcount = 1;
|
|
|
|
face->style_name = strdupW( style );
|
|
|
|
face->full_name = strdupW( fullname );
|
|
|
|
face->face_index = index;
|
|
|
|
face->fs = fs;
|
|
|
|
face->ntmFlags = ntmflags;
|
|
|
|
face->version = version;
|
|
|
|
face->flags = flags;
|
|
|
|
face->data_ptr = data_ptr;
|
|
|
|
face->data_size = data_size;
|
|
|
|
if (file) face->file = strdupW( file );
|
|
|
|
if (size) face->size = *size;
|
|
|
|
else face->scalable = TRUE;
|
|
|
|
if (insert_face_in_family_list( face, family )) return face;
|
|
|
|
release_face( face );
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-11-05 10:32:04 +01:00
|
|
|
static int CDECL add_gdi_face( const WCHAR *family_name, const WCHAR *second_name,
|
|
|
|
const WCHAR *style, const WCHAR *fullname, const WCHAR *file,
|
|
|
|
void *data_ptr, SIZE_T data_size, UINT index, FONTSIGNATURE fs,
|
|
|
|
DWORD ntmflags, DWORD version, DWORD flags,
|
|
|
|
const struct bitmap_font_size *size )
|
2020-11-03 11:27:21 +01:00
|
|
|
{
|
|
|
|
struct gdi_font_face *face;
|
|
|
|
struct gdi_font_family *family;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if ((family = find_family_from_name( family_name ))) family->refcount++;
|
|
|
|
else if (!(family = create_family( family_name, second_name ))) return ret;
|
|
|
|
|
|
|
|
if ((face = create_face( family, style, fullname, file, data_ptr, data_size,
|
|
|
|
index, fs, ntmflags, version, flags, size )))
|
|
|
|
{
|
|
|
|
if (flags & ADDFONT_ADD_TO_CACHE) add_face_to_cache( face );
|
|
|
|
release_face( face );
|
|
|
|
}
|
|
|
|
release_family( family );
|
|
|
|
ret++;
|
|
|
|
|
|
|
|
if (fs.fsCsb[0] & FS_DBCS_MASK)
|
|
|
|
{
|
|
|
|
WCHAR vert_family[LF_FACESIZE], vert_second[LF_FACESIZE], vert_full[LF_FULLFACESIZE];
|
|
|
|
|
|
|
|
vert_family[0] = '@';
|
|
|
|
lstrcpynW( vert_family + 1, family_name, LF_FACESIZE - 1 );
|
|
|
|
|
|
|
|
if (second_name && second_name[0])
|
|
|
|
{
|
|
|
|
vert_second[0] = '@';
|
|
|
|
lstrcpynW( vert_second + 1, second_name, LF_FACESIZE - 1 );
|
|
|
|
}
|
|
|
|
else vert_second[0] = 0;
|
|
|
|
|
|
|
|
if (fullname)
|
|
|
|
{
|
|
|
|
vert_full[0] = '@';
|
|
|
|
lstrcpynW( vert_full + 1, fullname, LF_FULLFACESIZE - 1 );
|
|
|
|
fullname = vert_full;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((family = find_family_from_name( vert_family ))) family->refcount++;
|
|
|
|
else if (!(family = create_family( vert_family, vert_second ))) return ret;
|
|
|
|
|
|
|
|
if ((face = create_face( family, style, fullname, file, data_ptr, data_size,
|
|
|
|
index, fs, ntmflags, version, flags | ADDFONT_VERTICAL_FONT, size )))
|
|
|
|
{
|
|
|
|
if (flags & ADDFONT_ADD_TO_CACHE) add_face_to_cache( face );
|
|
|
|
release_face( face );
|
|
|
|
}
|
|
|
|
release_family( family );
|
|
|
|
ret++;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-11-03 11:26:39 +01:00
|
|
|
/* font cache */
|
|
|
|
|
|
|
|
struct cached_face
|
|
|
|
{
|
|
|
|
DWORD index;
|
|
|
|
DWORD flags;
|
|
|
|
DWORD ntmflags;
|
|
|
|
DWORD version;
|
|
|
|
struct bitmap_font_size size;
|
|
|
|
FONTSIGNATURE fs;
|
|
|
|
WCHAR full_name[1];
|
|
|
|
/* WCHAR file_name[]; */
|
|
|
|
};
|
|
|
|
|
|
|
|
static void load_face_from_cache( HKEY hkey_family, struct gdi_font_family *family,
|
|
|
|
void *buffer, DWORD buffer_size, BOOL scalable )
|
|
|
|
{
|
|
|
|
DWORD type, size, needed, index = 0;
|
|
|
|
struct gdi_font_face *face;
|
|
|
|
HKEY hkey_strike;
|
|
|
|
WCHAR name[256];
|
|
|
|
struct cached_face *cached = (struct cached_face *)buffer;
|
|
|
|
|
|
|
|
size = sizeof(name);
|
|
|
|
needed = buffer_size - sizeof(DWORD);
|
|
|
|
while (!RegEnumValueW( hkey_family, index++, name, &size, NULL, &type, buffer, &needed ))
|
|
|
|
{
|
|
|
|
if (type == REG_BINARY && needed > sizeof(*cached))
|
|
|
|
{
|
|
|
|
((DWORD *)buffer)[needed / sizeof(DWORD)] = 0;
|
2020-11-03 11:27:21 +01:00
|
|
|
if ((face = create_face( family, name, cached->full_name,
|
2020-11-05 10:44:16 +01:00
|
|
|
cached->full_name + lstrlenW(cached->full_name) + 1,
|
2020-11-03 11:27:21 +01:00
|
|
|
NULL, 0, cached->index, cached->fs, cached->ntmflags, cached->version,
|
|
|
|
cached->flags, scalable ? NULL : &cached->size )))
|
|
|
|
{
|
|
|
|
if (!scalable)
|
|
|
|
TRACE("Adding bitmap size h %d w %d size %d x_ppem %d y_ppem %d\n",
|
|
|
|
face->size.height, face->size.width, face->size.size >> 6,
|
|
|
|
face->size.x_ppem >> 6, face->size.y_ppem >> 6);
|
2020-11-03 11:26:39 +01:00
|
|
|
|
2020-11-03 11:27:21 +01:00
|
|
|
TRACE("fsCsb = %08x %08x/%08x %08x %08x %08x\n",
|
|
|
|
face->fs.fsCsb[0], face->fs.fsCsb[1],
|
|
|
|
face->fs.fsUsb[0], face->fs.fsUsb[1],
|
|
|
|
face->fs.fsUsb[2], face->fs.fsUsb[3]);
|
2020-11-03 11:26:39 +01:00
|
|
|
|
2020-11-03 11:27:21 +01:00
|
|
|
release_face( face );
|
|
|
|
}
|
2020-11-03 11:26:39 +01:00
|
|
|
}
|
|
|
|
size = sizeof(name);
|
|
|
|
needed = buffer_size - sizeof(DWORD);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* load bitmap strikes */
|
|
|
|
|
|
|
|
index = 0;
|
|
|
|
needed = buffer_size;
|
|
|
|
while (!RegEnumKeyExW( hkey_family, index++, buffer, &needed, NULL, NULL, NULL, NULL ))
|
|
|
|
{
|
|
|
|
if (!RegOpenKeyExW( hkey_family, buffer, 0, KEY_ALL_ACCESS, &hkey_strike ))
|
|
|
|
{
|
|
|
|
load_face_from_cache( hkey_strike, family, buffer, buffer_size, FALSE );
|
|
|
|
RegCloseKey( hkey_strike );
|
|
|
|
}
|
|
|
|
needed = buffer_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void load_font_list_from_cache(void)
|
|
|
|
{
|
|
|
|
DWORD size, family_index = 0;
|
|
|
|
struct gdi_font_family *family;
|
|
|
|
HKEY hkey_family;
|
|
|
|
WCHAR buffer[4096], second_name[LF_FACESIZE];
|
|
|
|
|
|
|
|
size = sizeof(buffer);
|
|
|
|
while (!RegEnumKeyExW( wine_fonts_cache_key, family_index++, buffer, &size, NULL, NULL, NULL, NULL ))
|
|
|
|
{
|
|
|
|
RegOpenKeyExW( wine_fonts_cache_key, buffer, 0, KEY_ALL_ACCESS, &hkey_family );
|
|
|
|
TRACE("opened family key %s\n", debugstr_w(buffer));
|
|
|
|
size = sizeof(second_name);
|
|
|
|
if (RegQueryValueExW( hkey_family, NULL, NULL, NULL, (BYTE *)second_name, &size ))
|
|
|
|
second_name[0] = 0;
|
|
|
|
|
|
|
|
family = create_family( buffer, second_name );
|
|
|
|
|
|
|
|
load_face_from_cache( hkey_family, family, buffer, sizeof(buffer), TRUE );
|
|
|
|
|
|
|
|
RegCloseKey( hkey_family );
|
|
|
|
release_family( family );
|
|
|
|
size = sizeof(buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-03 11:27:21 +01:00
|
|
|
static void add_face_to_cache( struct gdi_font_face *face )
|
2020-11-03 11:26:39 +01:00
|
|
|
{
|
|
|
|
HKEY hkey_family, hkey_face;
|
|
|
|
DWORD len, buffer[1024];
|
|
|
|
struct cached_face *cached = (struct cached_face *)buffer;
|
|
|
|
|
|
|
|
if (RegCreateKeyExW( wine_fonts_cache_key, face->family->family_name, 0, NULL, REG_OPTION_VOLATILE,
|
|
|
|
KEY_ALL_ACCESS, NULL, &hkey_family, NULL ))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (face->family->second_name[0])
|
|
|
|
RegSetValueExW( hkey_family, NULL, 0, REG_SZ, (BYTE *)face->family->second_name,
|
2020-11-05 10:44:16 +01:00
|
|
|
(lstrlenW( face->family->second_name ) + 1) * sizeof(WCHAR) );
|
2020-11-03 11:26:39 +01:00
|
|
|
|
|
|
|
if (!face->scalable)
|
|
|
|
{
|
|
|
|
WCHAR name[10];
|
|
|
|
|
2020-11-06 12:08:16 +01:00
|
|
|
swprintf( name, ARRAY_SIZE(name), L"%d", face->size.y_ppem );
|
2020-11-03 11:26:39 +01:00
|
|
|
RegCreateKeyExW( hkey_family, name, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS,
|
|
|
|
NULL, &hkey_face, NULL);
|
|
|
|
}
|
|
|
|
else hkey_face = hkey_family;
|
|
|
|
|
|
|
|
memset( cached, 0, sizeof(*cached) );
|
|
|
|
cached->index = face->face_index;
|
|
|
|
cached->flags = face->flags;
|
|
|
|
cached->ntmflags = face->ntmFlags;
|
|
|
|
cached->version = face->version;
|
|
|
|
cached->fs = face->fs;
|
|
|
|
if (!face->scalable) cached->size = face->size;
|
2020-11-05 10:44:16 +01:00
|
|
|
lstrcpyW( cached->full_name, face->full_name );
|
|
|
|
len = lstrlenW( face->full_name ) + 1;
|
|
|
|
lstrcpyW( cached->full_name + len, face->file );
|
|
|
|
len += lstrlenW( face->file ) + 1;
|
2020-11-03 11:26:39 +01:00
|
|
|
|
|
|
|
RegSetValueExW( hkey_face, face->style_name, 0, REG_BINARY, (BYTE *)cached,
|
|
|
|
offsetof( struct cached_face, full_name[len] ));
|
|
|
|
|
|
|
|
if (hkey_face != hkey_family) RegCloseKey( hkey_face );
|
|
|
|
RegCloseKey( hkey_family );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void remove_face_from_cache( struct gdi_font_face *face )
|
|
|
|
{
|
|
|
|
HKEY hkey_family;
|
|
|
|
|
|
|
|
if (RegOpenKeyExW( wine_fonts_cache_key, face->family->family_name, 0, KEY_ALL_ACCESS, &hkey_family ))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!face->scalable)
|
|
|
|
{
|
|
|
|
WCHAR name[10];
|
2020-11-06 12:08:16 +01:00
|
|
|
swprintf( name, ARRAY_SIZE(name), L"%d", face->size.y_ppem );
|
2020-11-03 11:26:39 +01:00
|
|
|
RegDeleteKeyW( hkey_family, name );
|
|
|
|
}
|
|
|
|
else RegDeleteValueW( hkey_family, face->style_name );
|
|
|
|
|
|
|
|
RegCloseKey( hkey_family );
|
|
|
|
}
|
|
|
|
|
2020-10-31 10:19:08 +01:00
|
|
|
/* font links */
|
|
|
|
|
2020-11-04 09:20:50 +01:00
|
|
|
struct gdi_font_link
|
|
|
|
{
|
|
|
|
struct list entry;
|
|
|
|
struct list links;
|
|
|
|
WCHAR name[LF_FACESIZE];
|
|
|
|
FONTSIGNATURE fs;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct gdi_font_link_entry
|
|
|
|
{
|
|
|
|
struct list entry;
|
|
|
|
FONTSIGNATURE fs;
|
|
|
|
WCHAR family_name[LF_FACESIZE];
|
|
|
|
};
|
|
|
|
|
2020-10-31 10:19:08 +01:00
|
|
|
static struct list font_links = LIST_INIT(font_links);
|
|
|
|
|
2020-11-04 09:20:26 +01:00
|
|
|
static struct gdi_font_link *find_gdi_font_link( const WCHAR *name )
|
2020-10-31 10:19:08 +01:00
|
|
|
{
|
|
|
|
struct gdi_font_link *link;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY( link, &font_links, struct gdi_font_link, entry )
|
2020-11-23 13:20:50 +01:00
|
|
|
if (!facename_compare( link->name, name, LF_FACESIZE - 1 )) return link;
|
2020-10-31 10:19:08 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:15:06 +01:00
|
|
|
static struct gdi_font_family *find_family_from_font_links( const WCHAR *name, const WCHAR *subst,
|
|
|
|
FONTSIGNATURE fs )
|
2020-10-31 10:19:08 +01:00
|
|
|
{
|
|
|
|
struct gdi_font_link *link;
|
|
|
|
struct gdi_font_link_entry *entry;
|
|
|
|
struct gdi_font_family *family;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY( link, &font_links, struct gdi_font_link, entry )
|
|
|
|
{
|
2020-11-23 13:20:50 +01:00
|
|
|
if (!facename_compare( link->name, name, LF_FACESIZE - 1 ) ||
|
|
|
|
(subst && !facename_compare( link->name, subst, LF_FACESIZE - 1 )))
|
2020-10-31 10:19:08 +01:00
|
|
|
{
|
|
|
|
TRACE("found entry in system list\n");
|
|
|
|
LIST_FOR_EACH_ENTRY( entry, &link->links, struct gdi_font_link_entry, entry )
|
|
|
|
{
|
|
|
|
const struct gdi_font_link *links;
|
|
|
|
|
|
|
|
family = find_family_from_name( entry->family_name );
|
|
|
|
if (!fs.fsCsb[0]) return family;
|
|
|
|
if (fs.fsCsb[0] & entry->fs.fsCsb[0]) return family;
|
|
|
|
if ((links = find_gdi_font_link( family->family_name )) && fs.fsCsb[0] & links->fs.fsCsb[0])
|
|
|
|
return family;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct gdi_font_link *add_gdi_font_link( const WCHAR *name )
|
|
|
|
{
|
|
|
|
struct gdi_font_link *link = find_gdi_font_link( name );
|
|
|
|
|
|
|
|
if (link) return link;
|
|
|
|
if ((link = HeapAlloc( GetProcessHeap(), 0, sizeof(*link) )))
|
|
|
|
{
|
|
|
|
lstrcpynW( link->name, name, LF_FACESIZE );
|
|
|
|
memset( &link->fs, 0, sizeof(link->fs) );
|
|
|
|
list_init( &link->links );
|
|
|
|
list_add_tail( &font_links, &link->entry );
|
|
|
|
}
|
|
|
|
return link;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void add_gdi_font_link_entry( struct gdi_font_link *link, const WCHAR *family_name, FONTSIGNATURE fs )
|
|
|
|
{
|
|
|
|
struct gdi_font_link_entry *entry;
|
|
|
|
|
|
|
|
entry = HeapAlloc( GetProcessHeap(), 0, sizeof(*entry) );
|
|
|
|
lstrcpynW( entry->family_name, family_name, LF_FACESIZE );
|
|
|
|
entry->fs = fs;
|
|
|
|
link->fs.fsCsb[0] |= fs.fsCsb[0];
|
|
|
|
link->fs.fsCsb[1] |= fs.fsCsb[1];
|
|
|
|
list_add_tail( &link->links, &entry->entry );
|
|
|
|
}
|
|
|
|
|
|
|
|
static const WCHAR * const font_links_list[] =
|
|
|
|
{
|
2020-11-06 12:08:16 +01:00
|
|
|
L"Lucida Sans Unicode",
|
|
|
|
L"Microsoft Sans Serif",
|
|
|
|
L"Tahoma"
|
2020-10-31 10:19:08 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
static const struct font_links_defaults_list
|
|
|
|
{
|
|
|
|
/* Keyed off substitution for "MS Shell Dlg" */
|
|
|
|
const WCHAR *shelldlg;
|
|
|
|
/* Maximum of four substitutes, plus terminating NULL pointer */
|
|
|
|
const WCHAR *substitutes[5];
|
|
|
|
} font_links_defaults_list[] =
|
|
|
|
{
|
|
|
|
/* Non East-Asian */
|
2020-11-06 12:08:16 +01:00
|
|
|
{ L"Tahoma", /* FIXME unverified ordering */
|
|
|
|
{ L"MS UI Gothic", L"SimSun", L"Gulim", L"PMingLiU", NULL }
|
2020-10-31 10:19:08 +01:00
|
|
|
},
|
|
|
|
/* Below lists are courtesy of
|
|
|
|
* http://blogs.msdn.com/michkap/archive/2005/06/18/430507.aspx
|
|
|
|
*/
|
|
|
|
/* Japanese */
|
2020-11-06 12:08:16 +01:00
|
|
|
{ L"MS UI Gothic",
|
|
|
|
{ L"MS UI Gothic", L"PMingLiU", L"SimSun", L"Gulim", NULL }
|
2020-10-31 10:19:08 +01:00
|
|
|
},
|
|
|
|
/* Chinese Simplified */
|
2020-11-06 12:08:16 +01:00
|
|
|
{ L"SimSun",
|
|
|
|
{ L"SimSun", L"PMingLiU", L"MS UI Gothic", L"Batang", NULL }
|
2020-10-31 10:19:08 +01:00
|
|
|
},
|
|
|
|
/* Korean */
|
2020-11-06 12:08:16 +01:00
|
|
|
{ L"Gulim",
|
|
|
|
{ L"Gulim", L"PMingLiU", L"MS UI Gothic", L"SimSun", NULL }
|
2020-10-31 10:19:08 +01:00
|
|
|
},
|
|
|
|
/* Chinese Traditional */
|
2020-11-06 12:08:16 +01:00
|
|
|
{ L"PMingLiU",
|
|
|
|
{ L"PMingLiU", L"SimSun", L"MS UI Gothic", L"Batang", NULL }
|
2020-10-31 10:19:08 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static void populate_system_links( const WCHAR *name, const WCHAR * const *values )
|
|
|
|
{
|
|
|
|
struct gdi_font_family *family;
|
|
|
|
struct gdi_font_face *face;
|
|
|
|
struct gdi_font_link *font_link;
|
|
|
|
const WCHAR *file, *value;
|
|
|
|
|
|
|
|
/* Don't store fonts that are only substitutes for other fonts */
|
|
|
|
if (get_gdi_font_subst( name, -1, NULL ))
|
|
|
|
{
|
|
|
|
TRACE( "%s: Internal SystemLink entry for substituted font, ignoring\n", debugstr_w(name) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
font_link = add_gdi_font_link( name );
|
|
|
|
for ( ; *values; values++)
|
|
|
|
{
|
2020-11-23 13:20:50 +01:00
|
|
|
if (!facename_compare( name, *values, -1 )) continue;
|
2020-10-31 10:19:08 +01:00
|
|
|
if (!(value = get_gdi_font_subst( *values, -1, NULL ))) value = *values;
|
|
|
|
if (!(family = find_family_from_name( value ))) continue;
|
|
|
|
/* use first extant filename for this Family */
|
|
|
|
LIST_FOR_EACH_ENTRY( face, get_family_face_list(family), struct gdi_font_face, entry )
|
|
|
|
{
|
|
|
|
if (!face->file) continue;
|
2020-11-05 10:44:16 +01:00
|
|
|
file = wcsrchr(face->file, '\\');
|
2020-10-31 10:19:08 +01:00
|
|
|
if (!file) file = face->file;
|
|
|
|
else file++;
|
|
|
|
if ((face = find_face_from_filename( file, value )))
|
|
|
|
{
|
|
|
|
add_gdi_font_link_entry( font_link, face->family->family_name, face->fs );
|
|
|
|
TRACE( "added internal SystemLink for %s to %s in %s\n",
|
|
|
|
debugstr_w(name), debugstr_w(value), debugstr_w(file) );
|
|
|
|
}
|
|
|
|
else TRACE( "Unable to find file %s face name %s\n", debugstr_w(file), debugstr_w(value) );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void load_system_links(void)
|
|
|
|
{
|
|
|
|
HKEY hkey;
|
|
|
|
DWORD i, j;
|
|
|
|
const WCHAR *shelldlg_name;
|
|
|
|
struct gdi_font_link *font_link, *system_font_link;
|
|
|
|
struct gdi_font_face *face;
|
|
|
|
|
2020-11-06 12:08:16 +01:00
|
|
|
if (!RegOpenKeyW( HKEY_LOCAL_MACHINE,
|
|
|
|
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink", &hkey ))
|
2020-10-31 10:19:08 +01:00
|
|
|
{
|
|
|
|
WCHAR value[MAX_PATH], data[1024];
|
|
|
|
DWORD type, val_len, data_len;
|
|
|
|
WCHAR *entry, *next;
|
|
|
|
|
|
|
|
val_len = ARRAY_SIZE(value);
|
|
|
|
data_len = sizeof(data);
|
|
|
|
i = 0;
|
|
|
|
while (!RegEnumValueW( hkey, i++, value, &val_len, NULL, &type, (LPBYTE)data, &data_len))
|
|
|
|
{
|
|
|
|
/* Don't store fonts that are only substitutes for other fonts */
|
|
|
|
if (!get_gdi_font_subst( value, -1, NULL ))
|
|
|
|
{
|
|
|
|
font_link = add_gdi_font_link( value );
|
|
|
|
for (entry = data; (char *)entry < (char *)data + data_len && *entry; entry = next)
|
|
|
|
{
|
|
|
|
const WCHAR *family_name = NULL;
|
|
|
|
WCHAR *p;
|
|
|
|
|
|
|
|
TRACE("%s: %s\n", debugstr_w(value), debugstr_w(entry));
|
|
|
|
|
2020-11-05 10:44:16 +01:00
|
|
|
next = entry + lstrlenW(entry) + 1;
|
|
|
|
if ((p = wcschr( entry, ',' )))
|
2020-10-31 10:19:08 +01:00
|
|
|
{
|
|
|
|
*p++ = 0;
|
2020-11-05 10:44:16 +01:00
|
|
|
while (iswspace(*p)) p++;
|
2020-10-31 10:19:08 +01:00
|
|
|
if (!(family_name = get_gdi_font_subst( p, -1, NULL ))) family_name = p;
|
|
|
|
}
|
|
|
|
if ((face = find_face_from_filename( entry, family_name )))
|
|
|
|
{
|
|
|
|
add_gdi_font_link_entry( font_link, face->family->family_name, face->fs );
|
|
|
|
TRACE("Adding file %s index %u\n", debugstr_w(face->file), face->face_index);
|
|
|
|
}
|
|
|
|
else TRACE( "Unable to find file %s family %s\n",
|
|
|
|
debugstr_w(entry), debugstr_w(family_name) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else TRACE("%s: SystemLink entry for substituted font, ignoring\n", debugstr_w(value));
|
|
|
|
|
|
|
|
val_len = ARRAY_SIZE(value);
|
|
|
|
data_len = sizeof(data);
|
|
|
|
}
|
|
|
|
RegCloseKey( hkey );
|
|
|
|
}
|
|
|
|
|
2020-11-06 12:08:16 +01:00
|
|
|
if ((shelldlg_name = get_gdi_font_subst( L"MS Shell Dlg", -1, NULL )))
|
2020-10-31 10:19:08 +01:00
|
|
|
{
|
|
|
|
for (i = 0; i < ARRAY_SIZE(font_links_defaults_list); i++)
|
|
|
|
{
|
|
|
|
const WCHAR *subst = get_gdi_font_subst( font_links_defaults_list[i].shelldlg, -1, NULL );
|
|
|
|
|
2020-11-23 13:20:50 +01:00
|
|
|
if ((!facename_compare( font_links_defaults_list[i].shelldlg, shelldlg_name, -1 ) ||
|
|
|
|
(subst && !facename_compare( subst, shelldlg_name, -1 ))))
|
2020-10-31 10:19:08 +01:00
|
|
|
{
|
|
|
|
for (j = 0; j < ARRAY_SIZE(font_links_list); j++)
|
|
|
|
populate_system_links( font_links_list[j], font_links_defaults_list[i].substitutes );
|
2020-11-23 13:20:50 +01:00
|
|
|
if (!facename_compare(shelldlg_name, font_links_defaults_list[i].substitutes[0], -1))
|
2020-10-31 10:19:08 +01:00
|
|
|
populate_system_links( shelldlg_name, font_links_defaults_list[i].substitutes );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else WARN( "could not find FontSubstitute for MS Shell Dlg\n" );
|
|
|
|
|
|
|
|
/* Explicitly add an entry for the system font, this links to Tahoma and any links
|
|
|
|
that Tahoma has */
|
|
|
|
|
2020-11-06 12:08:16 +01:00
|
|
|
system_font_link = add_gdi_font_link( L"System" );
|
|
|
|
if ((face = find_face_from_filename( L"tahoma.ttf", L"Tahoma" )))
|
2020-10-31 10:19:08 +01:00
|
|
|
{
|
|
|
|
add_gdi_font_link_entry( system_font_link, face->family->family_name, face->fs );
|
|
|
|
TRACE("Found Tahoma in %s index %u\n", debugstr_w(face->file), face->face_index);
|
|
|
|
}
|
2020-11-06 12:08:16 +01:00
|
|
|
if ((font_link = find_gdi_font_link( L"Tahoma" )))
|
2020-10-31 10:19:08 +01:00
|
|
|
{
|
|
|
|
struct gdi_font_link_entry *entry;
|
|
|
|
LIST_FOR_EACH_ENTRY( entry, &font_link->links, struct gdi_font_link_entry, entry )
|
|
|
|
add_gdi_font_link_entry( system_font_link, entry->family_name, entry->fs );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-01 14:09:04 +02:00
|
|
|
/* see TranslateCharsetInfo */
|
|
|
|
BOOL translate_charset_info( DWORD *src, CHARSETINFO *cs, DWORD flags )
|
|
|
|
{
|
|
|
|
int index = 0;
|
|
|
|
|
|
|
|
switch (flags)
|
|
|
|
{
|
|
|
|
case TCI_SRCFONTSIG:
|
|
|
|
while (index < ARRAY_SIZE(charset_info) && !(*src>>index & 0x0001)) index++;
|
|
|
|
break;
|
|
|
|
case TCI_SRCCODEPAGE:
|
|
|
|
while (index < ARRAY_SIZE(charset_info) && PtrToUlong(src) != charset_info[index].ciACP)
|
|
|
|
index++;
|
|
|
|
break;
|
|
|
|
case TCI_SRCCHARSET:
|
|
|
|
while (index < ARRAY_SIZE(charset_info) &&
|
|
|
|
PtrToUlong(src) != charset_info[index].ciCharset)
|
|
|
|
index++;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index >= ARRAY_SIZE(charset_info) || charset_info[index].ciCharset == DEFAULT_CHARSET) return FALSE;
|
|
|
|
*cs = charset_info[index];
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:15:06 +01:00
|
|
|
/* font matching */
|
|
|
|
|
|
|
|
static BOOL can_select_face( const struct gdi_font_face *face, FONTSIGNATURE fs, BOOL can_use_bitmap )
|
|
|
|
{
|
|
|
|
struct gdi_font_link *font_link;
|
|
|
|
|
|
|
|
if (!face->scalable && !can_use_bitmap) return FALSE;
|
|
|
|
if (!fs.fsCsb[0]) return TRUE;
|
|
|
|
if (fs.fsCsb[0] & face->fs.fsCsb[0]) return TRUE;
|
|
|
|
if (!(font_link = find_gdi_font_link( face->family->family_name ))) return FALSE;
|
|
|
|
if (fs.fsCsb[0] & font_link->fs.fsCsb[0]) return TRUE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct gdi_font_face *find_best_matching_face( const struct gdi_font_family *family,
|
|
|
|
const LOGFONTW *lf, FONTSIGNATURE fs,
|
|
|
|
BOOL can_use_bitmap )
|
|
|
|
{
|
|
|
|
struct gdi_font_face *face = NULL, *best = NULL, *best_bitmap = NULL;
|
|
|
|
unsigned int best_score = 4;
|
|
|
|
int best_diff = 0;
|
|
|
|
int it = !!lf->lfItalic;
|
|
|
|
int bd = lf->lfWeight > 550;
|
|
|
|
int height = lf->lfHeight;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY( face, get_family_face_list(family), struct gdi_font_face, entry )
|
|
|
|
{
|
|
|
|
int italic = !!(face->ntmFlags & NTM_ITALIC);
|
|
|
|
int bold = !!(face->ntmFlags & NTM_BOLD);
|
|
|
|
int score = (italic ^ it) + (bold ^ bd);
|
|
|
|
|
|
|
|
if (!can_select_face( face, fs, can_use_bitmap )) continue;
|
|
|
|
if (score > best_score) continue;
|
|
|
|
TRACE( "(it=%d, bd=%d) is selected for (it=%d, bd=%d)\n", italic, bold, it, bd );
|
|
|
|
best_score = score;
|
|
|
|
best = face;
|
|
|
|
if (best->scalable && best_score == 0) break;
|
|
|
|
if (!best->scalable)
|
|
|
|
{
|
|
|
|
int diff;
|
|
|
|
if (height > 0)
|
|
|
|
diff = height - (signed int)best->size.height;
|
|
|
|
else
|
|
|
|
diff = -height - ((signed int)best->size.height - best->size.internal_leading);
|
|
|
|
if (!best_bitmap ||
|
|
|
|
(best_diff > 0 && diff >= 0 && diff < best_diff) ||
|
|
|
|
(best_diff < 0 && diff > best_diff))
|
|
|
|
{
|
|
|
|
TRACE( "%d is better for %d diff was %d\n", best->size.height, height, best_diff );
|
|
|
|
best_diff = diff;
|
|
|
|
best_bitmap = best;
|
|
|
|
if (best_score == 0 && best_diff == 0) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!best) return NULL;
|
|
|
|
return best->scalable ? best : best_bitmap;
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:18:59 +01:00
|
|
|
static struct gdi_font_face *find_matching_face_by_name( const WCHAR *name, const WCHAR *subst,
|
|
|
|
const LOGFONTW *lf, FONTSIGNATURE fs,
|
|
|
|
BOOL can_use_bitmap )
|
2020-11-04 09:15:06 +01:00
|
|
|
{
|
|
|
|
struct gdi_font_family *family;
|
|
|
|
struct gdi_font_face *face;
|
|
|
|
|
|
|
|
family = find_family_from_any_name( name );
|
|
|
|
if (family && (face = find_best_matching_face( family, lf, fs, can_use_bitmap ))) return face;
|
|
|
|
if (subst)
|
|
|
|
{
|
|
|
|
family = find_family_from_any_name( subst );
|
|
|
|
if (family && (face = find_best_matching_face( family, lf, fs, can_use_bitmap ))) return face;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* search by full face name */
|
2020-11-13 10:05:55 +01:00
|
|
|
WINE_RB_FOR_EACH_ENTRY( family, &family_name_tree, struct gdi_font_family, name_entry )
|
2020-11-04 09:15:06 +01:00
|
|
|
LIST_FOR_EACH_ENTRY( face, get_family_face_list(family), struct gdi_font_face, entry )
|
2020-11-23 13:20:50 +01:00
|
|
|
if (!facename_compare( face->full_name, name, LF_FACESIZE - 1 ) &&
|
2020-11-04 09:15:06 +01:00
|
|
|
can_select_face( face, fs, can_use_bitmap ))
|
|
|
|
return face;
|
|
|
|
|
|
|
|
if ((family = find_family_from_font_links( name, subst, fs )))
|
|
|
|
{
|
|
|
|
if ((face = find_best_matching_face( family, lf, fs, can_use_bitmap ))) return face;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:18:59 +01:00
|
|
|
static struct gdi_font_face *find_any_face( const LOGFONTW *lf, FONTSIGNATURE fs,
|
|
|
|
BOOL can_use_bitmap, BOOL want_vertical )
|
2020-11-04 09:15:06 +01:00
|
|
|
{
|
|
|
|
struct gdi_font_family *family;
|
|
|
|
struct gdi_font_face *face;
|
2020-11-13 10:05:57 +01:00
|
|
|
WCHAR name[LF_FACESIZE + 1];
|
2020-11-04 09:16:19 +01:00
|
|
|
int i = 0;
|
2020-11-04 09:15:06 +01:00
|
|
|
|
2020-11-04 09:16:19 +01:00
|
|
|
/* first try the family fallbacks */
|
|
|
|
while (enum_fallbacks( lf->lfPitchAndFamily, i++, name ))
|
|
|
|
{
|
2020-11-13 10:05:57 +01:00
|
|
|
if (want_vertical)
|
2020-11-04 09:16:19 +01:00
|
|
|
{
|
2020-11-13 10:05:57 +01:00
|
|
|
memmove(name + 1, name, min(lstrlenW(name), LF_FACESIZE));
|
|
|
|
name[0] = '@';
|
2020-11-04 09:16:19 +01:00
|
|
|
}
|
2020-11-13 10:05:57 +01:00
|
|
|
|
|
|
|
if (!(family = find_family_from_any_name(name))) continue;
|
|
|
|
if ((face = find_best_matching_face( family, lf, fs, FALSE ))) return face;
|
2020-11-04 09:16:19 +01:00
|
|
|
}
|
|
|
|
/* otherwise try only scalable */
|
2020-11-13 10:05:55 +01:00
|
|
|
WINE_RB_FOR_EACH_ENTRY( family, &family_name_tree, struct gdi_font_family, name_entry )
|
2020-11-04 09:15:06 +01:00
|
|
|
{
|
|
|
|
if ((family->family_name[0] == '@') == !want_vertical) continue;
|
|
|
|
if ((face = find_best_matching_face( family, lf, fs, FALSE ))) return face;
|
|
|
|
}
|
|
|
|
if (!can_use_bitmap) return NULL;
|
2020-11-04 09:16:19 +01:00
|
|
|
/* then also bitmap fonts */
|
2020-11-13 10:05:55 +01:00
|
|
|
WINE_RB_FOR_EACH_ENTRY( family, &family_name_tree, struct gdi_font_family, name_entry )
|
2020-11-04 09:15:06 +01:00
|
|
|
{
|
|
|
|
if ((family->family_name[0] == '@') == !want_vertical) continue;
|
|
|
|
if ((face = find_best_matching_face( family, lf, fs, can_use_bitmap ))) return face;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:20:26 +01:00
|
|
|
static struct gdi_font_face *find_matching_face( const LOGFONTW *lf, CHARSETINFO *csi, BOOL can_use_bitmap,
|
|
|
|
const WCHAR **orig_name )
|
2020-11-04 09:18:59 +01:00
|
|
|
{
|
|
|
|
BOOL want_vertical = (lf->lfFaceName[0] == '@');
|
|
|
|
struct gdi_font_face *face;
|
|
|
|
|
2021-09-01 14:09:04 +02:00
|
|
|
if (!translate_charset_info( (DWORD *)(INT_PTR)lf->lfCharSet, csi, TCI_SRCCHARSET ))
|
2020-11-04 09:18:59 +01:00
|
|
|
{
|
|
|
|
if (lf->lfCharSet != DEFAULT_CHARSET) FIXME( "Untranslated charset %d\n", lf->lfCharSet );
|
|
|
|
csi->fs.fsCsb[0] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lf->lfFaceName[0])
|
|
|
|
{
|
|
|
|
int subst_charset;
|
|
|
|
const WCHAR *subst = get_gdi_font_subst( lf->lfFaceName, lf->lfCharSet, &subst_charset );
|
|
|
|
|
|
|
|
if (subst)
|
|
|
|
{
|
|
|
|
TRACE( "substituting %s,%d -> %s,%d\n", debugstr_w(lf->lfFaceName), lf->lfCharSet,
|
|
|
|
debugstr_w(subst), (subst_charset != -1) ? subst_charset : lf->lfCharSet );
|
2020-11-04 09:20:26 +01:00
|
|
|
if (subst_charset != -1)
|
2021-09-01 14:09:04 +02:00
|
|
|
translate_charset_info( (DWORD *)(INT_PTR)subst_charset, csi, TCI_SRCCHARSET );
|
2020-11-04 09:18:59 +01:00
|
|
|
*orig_name = lf->lfFaceName;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((face = find_matching_face_by_name( lf->lfFaceName, subst, lf, csi->fs, can_use_bitmap )))
|
|
|
|
return face;
|
|
|
|
}
|
|
|
|
*orig_name = NULL; /* substitution is no longer relevant */
|
|
|
|
|
|
|
|
/* If requested charset was DEFAULT_CHARSET then try using charset
|
|
|
|
corresponding to the current ansi codepage */
|
|
|
|
if (!csi->fs.fsCsb[0])
|
|
|
|
{
|
|
|
|
INT acp = GetACP();
|
2021-09-01 14:09:04 +02:00
|
|
|
if (!translate_charset_info( (DWORD *)(INT_PTR)acp, csi, TCI_SRCCODEPAGE ))
|
2020-11-04 09:18:59 +01:00
|
|
|
{
|
|
|
|
FIXME( "TCI failed on codepage %d\n", acp );
|
|
|
|
csi->fs.fsCsb[0] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((face = find_any_face( lf, csi->fs, can_use_bitmap, want_vertical ))) return face;
|
|
|
|
if (csi->fs.fsCsb[0])
|
|
|
|
{
|
|
|
|
csi->fs.fsCsb[0] = 0;
|
|
|
|
if ((face = find_any_face( lf, csi->fs, can_use_bitmap, want_vertical ))) return face;
|
|
|
|
}
|
|
|
|
if (want_vertical && (face = find_any_face( lf, csi->fs, can_use_bitmap, FALSE ))) return face;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-10-21 10:59:51 +02:00
|
|
|
/* realized font objects */
|
|
|
|
|
|
|
|
#define FIRST_FONT_HANDLE 1
|
|
|
|
#define MAX_FONT_HANDLES 256
|
|
|
|
|
|
|
|
struct font_handle_entry
|
|
|
|
{
|
|
|
|
struct gdi_font *font;
|
|
|
|
WORD generation; /* generation count for reusing handle values */
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct font_handle_entry font_handles[MAX_FONT_HANDLES];
|
|
|
|
static struct font_handle_entry *next_free;
|
|
|
|
static struct font_handle_entry *next_unused = font_handles;
|
|
|
|
|
|
|
|
static struct font_handle_entry *handle_entry( DWORD handle )
|
|
|
|
{
|
|
|
|
unsigned int idx = LOWORD(handle) - FIRST_FONT_HANDLE;
|
|
|
|
|
|
|
|
if (idx < MAX_FONT_HANDLES)
|
|
|
|
{
|
|
|
|
if (!HIWORD( handle ) || HIWORD( handle ) == font_handles[idx].generation)
|
|
|
|
return &font_handles[idx];
|
|
|
|
}
|
|
|
|
if (handle) WARN( "invalid handle 0x%08x\n", handle );
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct gdi_font *get_font_from_handle( DWORD handle )
|
|
|
|
{
|
|
|
|
struct font_handle_entry *entry = handle_entry( handle );
|
|
|
|
|
|
|
|
if (entry) return entry->font;
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static DWORD alloc_font_handle( struct gdi_font *font )
|
|
|
|
{
|
|
|
|
struct font_handle_entry *entry;
|
|
|
|
|
|
|
|
entry = next_free;
|
|
|
|
if (entry)
|
|
|
|
next_free = (struct font_handle_entry *)entry->font;
|
|
|
|
else if (next_unused < font_handles + MAX_FONT_HANDLES)
|
|
|
|
entry = next_unused++;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ERR( "out of realized font handles\n" );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
entry->font = font;
|
|
|
|
if (++entry->generation == 0xffff) entry->generation = 1;
|
|
|
|
return MAKELONG( entry - font_handles + FIRST_FONT_HANDLE, entry->generation );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_font_handle( DWORD handle )
|
|
|
|
{
|
|
|
|
struct font_handle_entry *entry;
|
|
|
|
|
|
|
|
if ((entry = handle_entry( handle )))
|
|
|
|
{
|
|
|
|
entry->font = (struct gdi_font *)next_free;
|
|
|
|
next_free = entry;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-31 15:58:54 +01:00
|
|
|
static struct gdi_font *alloc_gdi_font( const WCHAR *file, void *data_ptr, SIZE_T data_size )
|
2020-10-20 22:05:37 +02:00
|
|
|
{
|
2020-11-05 10:44:16 +01:00
|
|
|
UINT len = file ? lstrlenW(file) : 0;
|
2020-10-26 11:37:03 +01:00
|
|
|
struct gdi_font *font = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
|
|
|
offsetof( struct gdi_font, file[len + 1] ));
|
2020-10-20 22:05:37 +02:00
|
|
|
|
2020-10-21 11:01:50 +02:00
|
|
|
font->refcount = 1;
|
|
|
|
font->matrix.eM11 = font->matrix.eM22 = 1.0;
|
2020-11-05 09:59:32 +01:00
|
|
|
font->scale_y = 1;
|
2020-10-26 11:50:07 +01:00
|
|
|
font->kern_count = -1;
|
2020-10-29 14:44:25 +01:00
|
|
|
list_init( &font->child_fonts );
|
2020-10-21 11:01:50 +02:00
|
|
|
|
2020-10-26 11:37:03 +01:00
|
|
|
if (file)
|
|
|
|
{
|
|
|
|
WIN32_FILE_ATTRIBUTE_DATA info;
|
|
|
|
if (GetFileAttributesExW( file, GetFileExInfoStandard, &info ))
|
|
|
|
{
|
|
|
|
font->writetime = info.ftLastWriteTime;
|
|
|
|
font->data_size = (LONGLONG)info.nFileSizeHigh << 32 | info.nFileSizeLow;
|
|
|
|
memcpy( font->file, file, len * sizeof(WCHAR) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
font->data_ptr = data_ptr;
|
|
|
|
font->data_size = data_size;
|
|
|
|
}
|
|
|
|
|
2020-12-21 21:04:55 +01:00
|
|
|
font->handle = alloc_font_handle( font );
|
2020-10-20 22:05:37 +02:00
|
|
|
return font;
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:20:26 +01:00
|
|
|
static void free_gdi_font( struct gdi_font *font )
|
2020-10-20 22:05:37 +02:00
|
|
|
{
|
2020-10-22 11:51:07 +02:00
|
|
|
DWORD i;
|
2020-10-29 14:44:25 +01:00
|
|
|
struct gdi_font *child, *child_next;
|
2020-10-22 11:51:07 +02:00
|
|
|
|
2020-10-20 22:05:37 +02:00
|
|
|
if (font->private) font_funcs->destroy_font( font );
|
2020-10-21 10:59:51 +02:00
|
|
|
free_font_handle( font->handle );
|
2020-10-29 14:44:25 +01:00
|
|
|
LIST_FOR_EACH_ENTRY_SAFE( child, child_next, &font->child_fonts, struct gdi_font, entry )
|
|
|
|
{
|
|
|
|
list_remove( &child->entry );
|
|
|
|
free_gdi_font( child );
|
|
|
|
}
|
2020-10-22 11:51:07 +02:00
|
|
|
for (i = 0; i < font->gm_size; i++) HeapFree( GetProcessHeap(), 0, font->gm[i] );
|
2020-10-26 11:43:24 +01:00
|
|
|
HeapFree( GetProcessHeap(), 0, font->otm.otmpFamilyName );
|
|
|
|
HeapFree( GetProcessHeap(), 0, font->otm.otmpStyleName );
|
|
|
|
HeapFree( GetProcessHeap(), 0, font->otm.otmpFaceName );
|
|
|
|
HeapFree( GetProcessHeap(), 0, font->otm.otmpFullName );
|
2020-10-22 11:51:07 +02:00
|
|
|
HeapFree( GetProcessHeap(), 0, font->gm );
|
2020-10-26 11:50:07 +01:00
|
|
|
HeapFree( GetProcessHeap(), 0, font->kern_pairs );
|
2020-10-29 11:10:30 +01:00
|
|
|
HeapFree( GetProcessHeap(), 0, font->gsub_table );
|
2020-10-20 22:05:37 +02:00
|
|
|
HeapFree( GetProcessHeap(), 0, font );
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:20:50 +01:00
|
|
|
static inline const WCHAR *get_gdi_font_name( struct gdi_font *font )
|
2020-10-21 11:03:51 +02:00
|
|
|
{
|
2020-11-04 09:20:50 +01:00
|
|
|
return (WCHAR *)font->otm.otmpFamilyName;
|
2020-10-21 11:03:51 +02:00
|
|
|
}
|
|
|
|
|
2020-11-04 09:20:26 +01:00
|
|
|
static struct gdi_font *create_gdi_font( const struct gdi_font_face *face, const WCHAR *family_name,
|
|
|
|
const LOGFONTW *lf )
|
2020-10-31 15:58:54 +01:00
|
|
|
{
|
|
|
|
struct gdi_font *font;
|
|
|
|
|
|
|
|
if (!(font = alloc_gdi_font( face->file, face->data_ptr, face->data_size ))) return NULL;
|
|
|
|
font->fs = face->fs;
|
|
|
|
font->lf = *lf;
|
|
|
|
font->fake_italic = (lf->lfItalic && !(face->ntmFlags & NTM_ITALIC));
|
|
|
|
font->fake_bold = (lf->lfWeight > 550 && !(face->ntmFlags & NTM_BOLD));
|
|
|
|
font->scalable = face->scalable;
|
|
|
|
font->face_index = face->face_index;
|
|
|
|
font->ntmFlags = face->ntmFlags;
|
|
|
|
font->aa_flags = HIWORD( face->flags );
|
|
|
|
if (!family_name) family_name = face->family->family_name;
|
2020-11-04 09:20:50 +01:00
|
|
|
font->otm.otmpFamilyName = (char *)strdupW( family_name );
|
|
|
|
font->otm.otmpStyleName = (char *)strdupW( face->style_name );
|
|
|
|
font->otm.otmpFaceName = (char *)strdupW( face->full_name );
|
2020-10-31 15:58:54 +01:00
|
|
|
return font;
|
|
|
|
}
|
|
|
|
|
2020-10-22 11:51:07 +02:00
|
|
|
struct glyph_metrics
|
|
|
|
{
|
|
|
|
GLYPHMETRICS gm;
|
|
|
|
ABC abc; /* metrics of the unrotated char */
|
|
|
|
BOOL init;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define GM_BLOCK_SIZE 128
|
|
|
|
|
|
|
|
/* TODO: GGO format support */
|
2020-10-29 14:47:18 +01:00
|
|
|
static BOOL get_gdi_font_glyph_metrics( struct gdi_font *font, UINT index, GLYPHMETRICS *gm, ABC *abc )
|
2020-10-22 11:51:07 +02:00
|
|
|
{
|
|
|
|
UINT block = index / GM_BLOCK_SIZE;
|
|
|
|
UINT entry = index % GM_BLOCK_SIZE;
|
|
|
|
|
|
|
|
if (block < font->gm_size && font->gm[block] && font->gm[block][entry].init)
|
|
|
|
{
|
|
|
|
*gm = font->gm[block][entry].gm;
|
|
|
|
*abc = font->gm[block][entry].abc;
|
|
|
|
|
|
|
|
TRACE( "cached gm: %u, %u, %s, %d, %d abc: %d, %u, %d\n",
|
|
|
|
gm->gmBlackBoxX, gm->gmBlackBoxY, wine_dbgstr_point( &gm->gmptGlyphOrigin ),
|
|
|
|
gm->gmCellIncX, gm->gmCellIncY, abc->abcA, abc->abcB, abc->abcC );
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2020-10-29 14:47:18 +01:00
|
|
|
static void set_gdi_font_glyph_metrics( struct gdi_font *font, UINT index,
|
|
|
|
const GLYPHMETRICS *gm, const ABC *abc )
|
2020-10-22 11:51:07 +02:00
|
|
|
{
|
|
|
|
UINT block = index / GM_BLOCK_SIZE;
|
|
|
|
UINT entry = index % GM_BLOCK_SIZE;
|
|
|
|
|
|
|
|
if (block >= font->gm_size)
|
|
|
|
{
|
|
|
|
struct glyph_metrics **ptr;
|
|
|
|
|
|
|
|
if (font->gm)
|
|
|
|
ptr = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm, (block + 1) * sizeof(*ptr) );
|
|
|
|
else
|
|
|
|
ptr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, (block + 1) * sizeof(*ptr) );
|
|
|
|
if (!ptr) return;
|
|
|
|
font->gm_size = block + 1;
|
|
|
|
font->gm = ptr;
|
|
|
|
}
|
|
|
|
if (!font->gm[block])
|
|
|
|
{
|
|
|
|
font->gm[block] = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(**font->gm) * GM_BLOCK_SIZE );
|
|
|
|
if (!font->gm[block]) return;
|
|
|
|
}
|
|
|
|
font->gm[block][entry].gm = *gm;
|
|
|
|
font->gm[block][entry].abc = *abc;
|
|
|
|
font->gm[block][entry].init = TRUE;
|
|
|
|
}
|
|
|
|
|
2020-10-29 11:10:30 +01:00
|
|
|
|
|
|
|
/* GSUB table support */
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
DWORD version;
|
|
|
|
WORD ScriptList;
|
|
|
|
WORD FeatureList;
|
|
|
|
WORD LookupList;
|
|
|
|
} GSUB_Header;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
CHAR ScriptTag[4];
|
|
|
|
WORD Script;
|
|
|
|
} GSUB_ScriptRecord;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
WORD ScriptCount;
|
|
|
|
GSUB_ScriptRecord ScriptRecord[1];
|
|
|
|
} GSUB_ScriptList;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
CHAR LangSysTag[4];
|
|
|
|
WORD LangSys;
|
|
|
|
} GSUB_LangSysRecord;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
WORD DefaultLangSys;
|
|
|
|
WORD LangSysCount;
|
|
|
|
GSUB_LangSysRecord LangSysRecord[1];
|
|
|
|
} GSUB_Script;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
WORD LookupOrder; /* Reserved */
|
|
|
|
WORD ReqFeatureIndex;
|
|
|
|
WORD FeatureCount;
|
|
|
|
WORD FeatureIndex[1];
|
|
|
|
} GSUB_LangSys;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
CHAR FeatureTag[4];
|
|
|
|
WORD Feature;
|
|
|
|
} GSUB_FeatureRecord;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
WORD FeatureCount;
|
|
|
|
GSUB_FeatureRecord FeatureRecord[1];
|
|
|
|
} GSUB_FeatureList;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
WORD FeatureParams; /* Reserved */
|
|
|
|
WORD LookupCount;
|
|
|
|
WORD LookupListIndex[1];
|
|
|
|
} GSUB_Feature;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
WORD LookupCount;
|
|
|
|
WORD Lookup[1];
|
|
|
|
} GSUB_LookupList;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
WORD LookupType;
|
|
|
|
WORD LookupFlag;
|
|
|
|
WORD SubTableCount;
|
|
|
|
WORD SubTable[1];
|
|
|
|
} GSUB_LookupTable;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
WORD CoverageFormat;
|
|
|
|
WORD GlyphCount;
|
|
|
|
WORD GlyphArray[1];
|
|
|
|
} GSUB_CoverageFormat1;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
WORD Start;
|
|
|
|
WORD End;
|
|
|
|
WORD StartCoverageIndex;
|
|
|
|
} GSUB_RangeRecord;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
WORD CoverageFormat;
|
|
|
|
WORD RangeCount;
|
|
|
|
GSUB_RangeRecord RangeRecord[1];
|
|
|
|
} GSUB_CoverageFormat2;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
WORD SubstFormat; /* = 1 */
|
|
|
|
WORD Coverage;
|
|
|
|
WORD DeltaGlyphID;
|
|
|
|
} GSUB_SingleSubstFormat1;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
WORD SubstFormat; /* = 2 */
|
|
|
|
WORD Coverage;
|
|
|
|
WORD GlyphCount;
|
|
|
|
WORD Substitute[1];
|
|
|
|
} GSUB_SingleSubstFormat2;
|
|
|
|
|
|
|
|
static GSUB_Script *GSUB_get_script_table( GSUB_Header *header, const char *tag )
|
|
|
|
{
|
|
|
|
GSUB_ScriptList *script;
|
|
|
|
GSUB_Script *deflt = NULL;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
script = (GSUB_ScriptList *)((BYTE *)header + GET_BE_WORD(header->ScriptList));
|
|
|
|
TRACE("%i scripts in this font\n", GET_BE_WORD(script->ScriptCount) );
|
|
|
|
for (i = 0; i < GET_BE_WORD(script->ScriptCount); i++)
|
|
|
|
{
|
|
|
|
int offset = GET_BE_WORD(script->ScriptRecord[i].Script);
|
|
|
|
GSUB_Script *scr = (GSUB_Script *)((BYTE *)script + offset);
|
|
|
|
if (!memcmp( script->ScriptRecord[i].ScriptTag, tag, 4 )) return scr;
|
|
|
|
if (!memcmp( script->ScriptRecord[i].ScriptTag, "dflt", 4 )) deflt = scr;
|
|
|
|
}
|
|
|
|
return deflt;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GSUB_LangSys *GSUB_get_lang_table( GSUB_Script *script, const char *tag )
|
|
|
|
{
|
|
|
|
int i, offset;
|
|
|
|
GSUB_LangSys *lang;
|
|
|
|
|
|
|
|
TRACE("Deflang %x, LangCount %i\n",GET_BE_WORD(script->DefaultLangSys), GET_BE_WORD(script->LangSysCount));
|
|
|
|
|
|
|
|
for (i = 0; i < GET_BE_WORD(script->LangSysCount) ; i++)
|
|
|
|
{
|
|
|
|
offset = GET_BE_WORD(script->LangSysRecord[i].LangSys);
|
|
|
|
lang = (GSUB_LangSys *)((BYTE *)script + offset);
|
|
|
|
if (!memcmp( script->LangSysRecord[i].LangSysTag, tag, 4 )) return lang;
|
|
|
|
}
|
|
|
|
offset = GET_BE_WORD(script->DefaultLangSys);
|
|
|
|
if (offset) return (GSUB_LangSys *)((BYTE *)script + offset);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GSUB_Feature *GSUB_get_feature( GSUB_Header *header, GSUB_LangSys *lang, const char *tag )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
const GSUB_FeatureList *feature;
|
|
|
|
|
|
|
|
feature = (GSUB_FeatureList *)((BYTE *)header + GET_BE_WORD(header->FeatureList));
|
|
|
|
TRACE("%i features\n",GET_BE_WORD(lang->FeatureCount));
|
|
|
|
for (i = 0; i < GET_BE_WORD(lang->FeatureCount); i++)
|
|
|
|
{
|
|
|
|
int index = GET_BE_WORD(lang->FeatureIndex[i]);
|
|
|
|
if (!memcmp( feature->FeatureRecord[index].FeatureTag, tag, 4 ))
|
|
|
|
return (GSUB_Feature *)((BYTE *)feature + GET_BE_WORD(feature->FeatureRecord[index].Feature));
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *get_opentype_script( const struct gdi_font *font )
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* I am not sure if this is the correct way to generate our script tag
|
|
|
|
*/
|
|
|
|
switch (font->charset)
|
|
|
|
{
|
|
|
|
case ANSI_CHARSET: return "latn";
|
|
|
|
case BALTIC_CHARSET: return "latn"; /* ?? */
|
|
|
|
case CHINESEBIG5_CHARSET: return "hani";
|
|
|
|
case EASTEUROPE_CHARSET: return "latn"; /* ?? */
|
|
|
|
case GB2312_CHARSET: return "hani";
|
|
|
|
case GREEK_CHARSET: return "grek";
|
|
|
|
case HANGUL_CHARSET: return "hang";
|
|
|
|
case RUSSIAN_CHARSET: return "cyrl";
|
|
|
|
case SHIFTJIS_CHARSET: return "kana";
|
|
|
|
case TURKISH_CHARSET: return "latn"; /* ?? */
|
|
|
|
case VIETNAMESE_CHARSET: return "latn";
|
|
|
|
case JOHAB_CHARSET: return "latn"; /* ?? */
|
|
|
|
case ARABIC_CHARSET: return "arab";
|
|
|
|
case HEBREW_CHARSET: return "hebr";
|
|
|
|
case THAI_CHARSET: return "thai";
|
|
|
|
default: return "latn";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:20:26 +01:00
|
|
|
static void *get_GSUB_vert_feature( struct gdi_font *font )
|
2020-10-29 11:10:30 +01:00
|
|
|
{
|
|
|
|
GSUB_Header *header;
|
|
|
|
GSUB_Script *script;
|
|
|
|
GSUB_LangSys *language;
|
|
|
|
GSUB_Feature *feature;
|
|
|
|
DWORD length = font_funcs->get_font_data( font, MS_GSUB_TAG, 0, NULL, 0 );
|
|
|
|
|
|
|
|
if (length == GDI_ERROR) return NULL;
|
|
|
|
|
|
|
|
header = HeapAlloc( GetProcessHeap(), 0, length );
|
|
|
|
font_funcs->get_font_data( font, MS_GSUB_TAG, 0, header, length );
|
|
|
|
TRACE( "Loaded GSUB table of %i bytes\n", length );
|
|
|
|
|
|
|
|
if ((script = GSUB_get_script_table( header, get_opentype_script(font) )))
|
|
|
|
{
|
|
|
|
if ((language = GSUB_get_lang_table( script, "xxxx" ))) /* Need to get Lang tag */
|
|
|
|
{
|
|
|
|
feature = GSUB_get_feature( header, language, "vrt2" );
|
|
|
|
if (!feature) feature = GSUB_get_feature( header, language, "vert" );
|
|
|
|
if (feature)
|
|
|
|
{
|
|
|
|
font->gsub_table = header;
|
|
|
|
return feature;
|
|
|
|
}
|
|
|
|
TRACE("vrt2/vert feature not found\n");
|
|
|
|
}
|
|
|
|
else TRACE("Language not found\n");
|
|
|
|
}
|
|
|
|
else TRACE("Script not found\n");
|
|
|
|
|
|
|
|
HeapFree( GetProcessHeap(), 0, header );
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int GSUB_is_glyph_covered( void *table, UINT glyph )
|
|
|
|
{
|
|
|
|
GSUB_CoverageFormat1 *cf1 = table;
|
|
|
|
|
|
|
|
if (GET_BE_WORD(cf1->CoverageFormat) == 1)
|
|
|
|
{
|
|
|
|
int i, count = GET_BE_WORD(cf1->GlyphCount);
|
|
|
|
|
|
|
|
TRACE("Coverage Format 1, %i glyphs\n",count);
|
|
|
|
for (i = 0; i < count; i++) if (glyph == GET_BE_WORD(cf1->GlyphArray[i])) return i;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else if (GET_BE_WORD(cf1->CoverageFormat) == 2)
|
|
|
|
{
|
|
|
|
int i, count;
|
|
|
|
GSUB_CoverageFormat2 *cf2 = table;
|
|
|
|
|
|
|
|
count = GET_BE_WORD(cf2->RangeCount);
|
|
|
|
TRACE("Coverage Format 2, %i ranges\n",count);
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
if (glyph < GET_BE_WORD(cf2->RangeRecord[i].Start)) return -1;
|
|
|
|
if ((glyph >= GET_BE_WORD(cf2->RangeRecord[i].Start)) &&
|
|
|
|
(glyph <= GET_BE_WORD(cf2->RangeRecord[i].End)))
|
|
|
|
{
|
|
|
|
return (GET_BE_WORD(cf2->RangeRecord[i].StartCoverageIndex) +
|
|
|
|
glyph - GET_BE_WORD(cf2->RangeRecord[i].Start));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else ERR("Unknown CoverageFormat %i\n",GET_BE_WORD(cf1->CoverageFormat));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static UINT GSUB_apply_feature( GSUB_Header *header, GSUB_Feature *feature, UINT glyph )
|
|
|
|
{
|
|
|
|
GSUB_LookupList *lookup = (GSUB_LookupList *)((BYTE *)header + GET_BE_WORD(header->LookupList));
|
|
|
|
int i, j, offset;
|
|
|
|
|
|
|
|
TRACE("%i lookups\n", GET_BE_WORD(feature->LookupCount));
|
|
|
|
for (i = 0; i < GET_BE_WORD(feature->LookupCount); i++)
|
|
|
|
{
|
|
|
|
GSUB_LookupTable *look;
|
|
|
|
offset = GET_BE_WORD(lookup->Lookup[GET_BE_WORD(feature->LookupListIndex[i])]);
|
|
|
|
look = (GSUB_LookupTable *)((BYTE *)lookup + offset);
|
|
|
|
TRACE("type %i, flag %x, subtables %i\n",
|
|
|
|
GET_BE_WORD(look->LookupType),GET_BE_WORD(look->LookupFlag),GET_BE_WORD(look->SubTableCount));
|
|
|
|
if (GET_BE_WORD(look->LookupType) == 1)
|
|
|
|
{
|
|
|
|
for (j = 0; j < GET_BE_WORD(look->SubTableCount); j++)
|
|
|
|
{
|
|
|
|
GSUB_SingleSubstFormat1 *ssf1;
|
|
|
|
offset = GET_BE_WORD(look->SubTable[j]);
|
|
|
|
ssf1 = (GSUB_SingleSubstFormat1 *)((BYTE *)look + offset);
|
|
|
|
if (GET_BE_WORD(ssf1->SubstFormat) == 1)
|
|
|
|
{
|
|
|
|
int offset = GET_BE_WORD(ssf1->Coverage);
|
|
|
|
TRACE(" subtype 1, delta %i\n", GET_BE_WORD(ssf1->DeltaGlyphID));
|
|
|
|
if (GSUB_is_glyph_covered( (BYTE *) ssf1 + offset, glyph ) != -1)
|
|
|
|
{
|
|
|
|
TRACE(" Glyph 0x%x ->",glyph);
|
|
|
|
glyph += GET_BE_WORD(ssf1->DeltaGlyphID);
|
|
|
|
TRACE(" 0x%x\n",glyph);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GSUB_SingleSubstFormat2 *ssf2;
|
|
|
|
int index, offset;
|
|
|
|
|
|
|
|
ssf2 = (GSUB_SingleSubstFormat2 *)ssf1;
|
|
|
|
offset = GET_BE_WORD(ssf1->Coverage);
|
|
|
|
TRACE(" subtype 2, glyph count %i\n", GET_BE_WORD(ssf2->GlyphCount));
|
|
|
|
index = GSUB_is_glyph_covered( (BYTE *)ssf2 + offset, glyph );
|
|
|
|
TRACE(" Coverage index %i\n",index);
|
|
|
|
if (index != -1)
|
|
|
|
{
|
|
|
|
TRACE(" Glyph is 0x%x ->",glyph);
|
|
|
|
glyph = GET_BE_WORD(ssf2->Substitute[index]);
|
|
|
|
TRACE("0x%x\n",glyph);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else FIXME("We only handle SubType 1\n");
|
|
|
|
}
|
|
|
|
return glyph;
|
|
|
|
}
|
|
|
|
|
2020-10-29 14:47:18 +01:00
|
|
|
static UINT get_GSUB_vert_glyph( struct gdi_font *font, UINT glyph )
|
2020-10-29 11:10:30 +01:00
|
|
|
{
|
2020-10-29 14:47:18 +01:00
|
|
|
if (!glyph) return glyph;
|
2020-10-29 11:10:30 +01:00
|
|
|
if (!font->gsub_table) return glyph;
|
|
|
|
return GSUB_apply_feature( font->gsub_table, font->vert_feature, glyph );
|
|
|
|
}
|
|
|
|
|
2020-10-31 10:20:26 +01:00
|
|
|
static void add_child_font( struct gdi_font *font, const WCHAR *family_name )
|
|
|
|
{
|
2020-11-04 09:15:06 +01:00
|
|
|
FONTSIGNATURE fs = {{0}};
|
2020-10-31 10:20:26 +01:00
|
|
|
struct gdi_font *child;
|
2020-11-04 09:15:06 +01:00
|
|
|
struct gdi_font_face *face;
|
2020-10-31 10:20:26 +01:00
|
|
|
|
2020-11-04 09:15:06 +01:00
|
|
|
if (!(face = find_matching_face_by_name( family_name, NULL, &font->lf, fs, FALSE ))) return;
|
2020-10-31 10:20:26 +01:00
|
|
|
|
2020-11-04 09:15:06 +01:00
|
|
|
if (!(child = create_gdi_font( face, family_name, &font->lf ))) return;
|
2020-10-31 10:20:26 +01:00
|
|
|
child->matrix = font->matrix;
|
|
|
|
child->can_use_bitmap = font->can_use_bitmap;
|
|
|
|
child->scale_y = font->scale_y;
|
|
|
|
child->aveWidth = font->aveWidth;
|
|
|
|
child->charset = font->charset;
|
|
|
|
child->codepage = font->codepage;
|
|
|
|
child->base_font = font;
|
|
|
|
list_add_tail( &font->child_fonts, &child->entry );
|
|
|
|
TRACE( "created child font %p for base %p\n", child, font );
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:20:26 +01:00
|
|
|
static void create_child_font_list( struct gdi_font *font )
|
2020-10-31 10:20:26 +01:00
|
|
|
{
|
|
|
|
struct gdi_font_link *font_link;
|
|
|
|
struct gdi_font_link_entry *entry;
|
|
|
|
const WCHAR* font_name;
|
|
|
|
|
|
|
|
if (!(font_name = get_gdi_font_subst( get_gdi_font_name(font), -1, NULL )))
|
|
|
|
font_name = get_gdi_font_name( font );
|
|
|
|
|
|
|
|
if ((font_link = find_gdi_font_link( font_name )))
|
|
|
|
{
|
|
|
|
TRACE("found entry in system list\n");
|
|
|
|
LIST_FOR_EACH_ENTRY( entry, &font_link->links, struct gdi_font_link_entry, entry )
|
|
|
|
add_child_font( font, entry->family_name );
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* if not SYMBOL or OEM then we also get all the fonts for Microsoft
|
|
|
|
* Sans Serif. This is how asian windows get default fallbacks for fonts
|
|
|
|
*/
|
|
|
|
if (is_dbcs_ansi_cp(GetACP()) && font->charset != SYMBOL_CHARSET && font->charset != OEM_CHARSET &&
|
2020-11-23 13:20:50 +01:00
|
|
|
facename_compare( font_name, L"Microsoft Sans Serif", -1 ) != 0)
|
2020-10-31 10:20:26 +01:00
|
|
|
{
|
2020-11-06 12:08:16 +01:00
|
|
|
if ((font_link = find_gdi_font_link( L"Microsoft Sans Serif" )))
|
2020-10-31 10:20:26 +01:00
|
|
|
{
|
|
|
|
TRACE("found entry in default fallback list\n");
|
|
|
|
LIST_FOR_EACH_ENTRY( entry, &font_link->links, struct gdi_font_link_entry, entry )
|
|
|
|
add_child_font( font, entry->family_name );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-21 11:01:50 +02:00
|
|
|
/* font cache */
|
|
|
|
|
|
|
|
static struct list gdi_font_list = LIST_INIT( gdi_font_list );
|
|
|
|
static struct list unused_gdi_font_list = LIST_INIT( unused_gdi_font_list );
|
|
|
|
static unsigned int unused_font_count;
|
|
|
|
#define UNUSED_CACHE_SIZE 10
|
|
|
|
|
|
|
|
static BOOL fontcmp( const struct gdi_font *font, DWORD hash, const LOGFONTW *lf,
|
|
|
|
const FMAT2 *matrix, BOOL can_use_bitmap )
|
|
|
|
{
|
|
|
|
if (font->hash != hash) return TRUE;
|
|
|
|
if (memcmp( &font->matrix, matrix, sizeof(*matrix))) return TRUE;
|
|
|
|
if (memcmp( &font->lf, lf, offsetof(LOGFONTW, lfFaceName))) return TRUE;
|
|
|
|
if (!font->can_use_bitmap != !can_use_bitmap) return TRUE;
|
2020-11-23 13:20:50 +01:00
|
|
|
return facename_compare( font->lf.lfFaceName, lf->lfFaceName, -1 );
|
2020-10-21 11:01:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static DWORD hash_font( const LOGFONTW *lf, const FMAT2 *matrix, BOOL can_use_bitmap )
|
|
|
|
{
|
|
|
|
DWORD hash = 0, *ptr, two_chars;
|
|
|
|
WORD *pwc;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0, ptr = (DWORD *)matrix; i < sizeof(*matrix) / sizeof(DWORD); i++, ptr++)
|
|
|
|
hash ^= *ptr;
|
|
|
|
for(i = 0, ptr = (DWORD *)lf; i < 7; i++, ptr++)
|
|
|
|
hash ^= *ptr;
|
|
|
|
for(i = 0, ptr = (DWORD *)lf->lfFaceName; i < LF_FACESIZE/2; i++, ptr++)
|
|
|
|
{
|
|
|
|
two_chars = *ptr;
|
|
|
|
pwc = (WCHAR *)&two_chars;
|
|
|
|
if(!*pwc) break;
|
2020-11-05 10:44:16 +01:00
|
|
|
*pwc = towupper(*pwc);
|
2020-10-21 11:01:50 +02:00
|
|
|
pwc++;
|
2020-11-05 10:44:16 +01:00
|
|
|
*pwc = towupper(*pwc);
|
2020-10-21 11:01:50 +02:00
|
|
|
hash ^= two_chars;
|
|
|
|
if(!*pwc) break;
|
|
|
|
}
|
|
|
|
hash ^= !can_use_bitmap;
|
|
|
|
return hash;
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:20:26 +01:00
|
|
|
static void cache_gdi_font( struct gdi_font *font )
|
2020-10-21 11:01:50 +02:00
|
|
|
{
|
|
|
|
static DWORD cache_num = 1;
|
|
|
|
|
|
|
|
font->cache_num = cache_num++;
|
|
|
|
font->hash = hash_font( &font->lf, &font->matrix, font->can_use_bitmap );
|
|
|
|
list_add_head( &gdi_font_list, &font->entry );
|
|
|
|
TRACE( "font %p\n", font );
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:20:26 +01:00
|
|
|
static struct gdi_font *find_cached_gdi_font( const LOGFONTW *lf, const FMAT2 *matrix, BOOL can_use_bitmap )
|
2020-10-21 11:01:50 +02:00
|
|
|
{
|
|
|
|
struct gdi_font *font;
|
|
|
|
DWORD hash = hash_font( lf, matrix, can_use_bitmap );
|
|
|
|
|
|
|
|
/* try the in-use list */
|
|
|
|
LIST_FOR_EACH_ENTRY( font, &gdi_font_list, struct gdi_font, entry )
|
|
|
|
{
|
|
|
|
if (fontcmp( font, hash, lf, matrix, can_use_bitmap )) continue;
|
|
|
|
list_remove( &font->entry );
|
|
|
|
list_add_head( &gdi_font_list, &font->entry );
|
|
|
|
if (!font->refcount++)
|
|
|
|
{
|
|
|
|
list_remove( &font->unused_entry );
|
|
|
|
unused_font_count--;
|
|
|
|
}
|
|
|
|
return font;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void release_gdi_font( struct gdi_font *font )
|
|
|
|
{
|
|
|
|
if (!font) return;
|
|
|
|
if (--font->refcount) return;
|
|
|
|
|
|
|
|
TRACE( "font %p\n", font );
|
|
|
|
|
|
|
|
/* add it to the unused list */
|
2020-11-03 11:25:30 +01:00
|
|
|
EnterCriticalSection( &font_cs );
|
2020-10-21 11:01:50 +02:00
|
|
|
list_add_head( &unused_gdi_font_list, &font->unused_entry );
|
|
|
|
if (unused_font_count > UNUSED_CACHE_SIZE)
|
|
|
|
{
|
|
|
|
font = LIST_ENTRY( list_tail( &unused_gdi_font_list ), struct gdi_font, unused_entry );
|
|
|
|
TRACE( "freeing %p\n", font );
|
|
|
|
list_remove( &font->entry );
|
|
|
|
list_remove( &font->unused_entry );
|
|
|
|
free_gdi_font( font );
|
|
|
|
}
|
2020-11-03 11:25:30 +01:00
|
|
|
else unused_font_count++;
|
|
|
|
LeaveCriticalSection( &font_cs );
|
2020-10-21 11:01:50 +02:00
|
|
|
}
|
|
|
|
|
2020-09-30 16:08:21 +02:00
|
|
|
static void add_font_list(HKEY hkey, const struct nls_update_font_list *fl, int dpi)
|
|
|
|
{
|
|
|
|
const char *sserif = (dpi <= 108) ? fl->sserif_96 : fl->sserif_120;
|
|
|
|
|
|
|
|
RegSetValueExA(hkey, "Courier", 0, REG_SZ, (const BYTE *)fl->courier, strlen(fl->courier)+1);
|
|
|
|
RegSetValueExA(hkey, "MS Serif", 0, REG_SZ, (const BYTE *)fl->serif, strlen(fl->serif)+1);
|
|
|
|
RegSetValueExA(hkey, "MS Sans Serif", 0, REG_SZ, (const BYTE *)sserif, strlen(sserif)+1);
|
|
|
|
RegSetValueExA(hkey, "Small Fonts", 0, REG_SZ, (const BYTE *)fl->small, strlen(fl->small)+1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void set_value_key(HKEY hkey, const char *name, const char *value)
|
|
|
|
{
|
|
|
|
if (value)
|
|
|
|
RegSetValueExA(hkey, name, 0, REG_SZ, (const BYTE *)value, strlen(value) + 1);
|
|
|
|
else if (name)
|
|
|
|
RegDeleteValueA(hkey, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void update_font_association_info(UINT current_ansi_codepage)
|
|
|
|
{
|
|
|
|
if (is_dbcs_ansi_cp(current_ansi_codepage))
|
|
|
|
{
|
|
|
|
HKEY hkey;
|
2020-11-06 12:08:16 +01:00
|
|
|
if (RegCreateKeyW(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\FontAssoc", &hkey) == ERROR_SUCCESS)
|
2020-09-30 16:08:21 +02:00
|
|
|
{
|
|
|
|
HKEY hsubkey;
|
2020-11-06 12:08:16 +01:00
|
|
|
if (RegCreateKeyW(hkey, L"Associated Charset", &hsubkey) == ERROR_SUCCESS)
|
2020-09-30 16:08:21 +02:00
|
|
|
{
|
|
|
|
switch (current_ansi_codepage)
|
|
|
|
{
|
|
|
|
case 932:
|
|
|
|
set_value_key(hsubkey, "ANSI(00)", "NO");
|
|
|
|
set_value_key(hsubkey, "OEM(FF)", "NO");
|
|
|
|
set_value_key(hsubkey, "SYMBOL(02)", "NO");
|
|
|
|
break;
|
|
|
|
case 936:
|
|
|
|
case 949:
|
|
|
|
case 950:
|
|
|
|
set_value_key(hsubkey, "ANSI(00)", "YES");
|
|
|
|
set_value_key(hsubkey, "OEM(FF)", "YES");
|
|
|
|
set_value_key(hsubkey, "SYMBOL(02)", "NO");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
RegCloseKey(hsubkey);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: Associated DefaultFonts */
|
|
|
|
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2020-11-06 12:08:16 +01:00
|
|
|
RegDeleteTreeW(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\FontAssoc");
|
2020-09-30 16:08:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void set_multi_value_key(HKEY hkey, const WCHAR *name, const WCHAR *value, DWORD len)
|
|
|
|
{
|
|
|
|
if (value)
|
|
|
|
RegSetValueExW(hkey, name, 0, REG_MULTI_SZ, (const BYTE *)value, len);
|
|
|
|
else if (name)
|
|
|
|
RegDeleteValueW(hkey, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void update_font_system_link_info(UINT current_ansi_codepage)
|
|
|
|
{
|
|
|
|
static const WCHAR system_link_simplified_chinese[] =
|
2020-11-06 12:08:16 +01:00
|
|
|
L"SIMSUN.TTC,SimSun\0"
|
|
|
|
L"MINGLIU.TTC,PMingLiu\0"
|
|
|
|
L"MSGOTHIC.TTC,MS UI Gothic\0"
|
|
|
|
L"BATANG.TTC,Batang\0";
|
2020-09-30 16:08:21 +02:00
|
|
|
static const WCHAR system_link_traditional_chinese[] =
|
2020-11-06 12:08:16 +01:00
|
|
|
L"MINGLIU.TTC,PMingLiu\0"
|
|
|
|
L"SIMSUN.TTC,SimSun\0"
|
|
|
|
L"MSGOTHIC.TTC,MS UI Gothic\0"
|
|
|
|
L"BATANG.TTC,Batang\0";
|
2020-09-30 16:08:21 +02:00
|
|
|
static const WCHAR system_link_japanese[] =
|
2020-11-06 12:08:16 +01:00
|
|
|
L"MSGOTHIC.TTC,MS UI Gothic\0"
|
|
|
|
L"MINGLIU.TTC,PMingLiU\0"
|
|
|
|
L"SIMSUN.TTC,SimSun\0"
|
|
|
|
L"GULIM.TTC,Gulim\0";
|
2020-09-30 16:08:21 +02:00
|
|
|
static const WCHAR system_link_korean[] =
|
2020-11-06 12:08:16 +01:00
|
|
|
L"GULIM.TTC,Gulim\0"
|
|
|
|
L"MSGOTHIC.TTC,MS UI Gothic\0"
|
|
|
|
L"MINGLIU.TTC,PMingLiU\0"
|
|
|
|
L"SIMSUN.TTC,SimSun\0";
|
2020-09-30 16:08:21 +02:00
|
|
|
static const WCHAR system_link_non_cjk[] =
|
2020-11-06 12:08:16 +01:00
|
|
|
L"MSGOTHIC.TTC,MS UI Gothic\0"
|
|
|
|
L"MINGLIU.TTC,PMingLiU\0"
|
|
|
|
L"SIMSUN.TTC,SimSun\0"
|
|
|
|
L"GULIM.TTC,Gulim\0";
|
2020-09-30 16:08:21 +02:00
|
|
|
HKEY hkey;
|
|
|
|
|
2020-11-06 12:08:16 +01:00
|
|
|
if (!RegCreateKeyW(HKEY_LOCAL_MACHINE,
|
|
|
|
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink", &hkey))
|
2020-09-30 16:08:21 +02:00
|
|
|
{
|
|
|
|
const WCHAR *link;
|
|
|
|
DWORD len;
|
|
|
|
|
|
|
|
switch (current_ansi_codepage)
|
|
|
|
{
|
|
|
|
case 932:
|
|
|
|
link = system_link_japanese;
|
|
|
|
len = sizeof(system_link_japanese);
|
|
|
|
break;
|
|
|
|
case 936:
|
|
|
|
link = system_link_simplified_chinese;
|
|
|
|
len = sizeof(system_link_simplified_chinese);
|
|
|
|
break;
|
|
|
|
case 949:
|
|
|
|
link = system_link_korean;
|
|
|
|
len = sizeof(system_link_korean);
|
|
|
|
break;
|
|
|
|
case 950:
|
|
|
|
link = system_link_traditional_chinese;
|
|
|
|
len = sizeof(system_link_traditional_chinese);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
link = system_link_non_cjk;
|
|
|
|
len = sizeof(system_link_non_cjk);
|
|
|
|
}
|
2020-11-06 12:08:16 +01:00
|
|
|
set_multi_value_key(hkey, L"Lucida Sans Unicode", link, len);
|
|
|
|
set_multi_value_key(hkey, L"Microsoft Sans Serif", link, len);
|
|
|
|
set_multi_value_key(hkey, L"Tahoma", link, len);
|
2020-09-30 16:08:21 +02:00
|
|
|
RegCloseKey(hkey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void update_codepage(void)
|
|
|
|
{
|
|
|
|
char buf[40], cpbuf[40];
|
|
|
|
HKEY hkey;
|
|
|
|
DWORD len, type, size;
|
|
|
|
UINT i, ansi_cp, oem_cp;
|
|
|
|
DWORD screen_dpi, font_dpi = 0;
|
|
|
|
BOOL done = FALSE;
|
|
|
|
|
|
|
|
screen_dpi = get_dpi();
|
|
|
|
if (!screen_dpi) screen_dpi = 96;
|
|
|
|
|
|
|
|
size = sizeof(DWORD);
|
2020-11-06 12:08:16 +01:00
|
|
|
if (RegQueryValueExW(wine_fonts_key, L"LogPixels", NULL, &type, (BYTE *)&font_dpi, &size) ||
|
2020-09-30 16:08:21 +02:00
|
|
|
type != REG_DWORD || size != sizeof(DWORD))
|
|
|
|
font_dpi = 0;
|
|
|
|
|
|
|
|
ansi_cp = GetACP();
|
|
|
|
oem_cp = GetOEMCP();
|
|
|
|
sprintf( cpbuf, "%u,%u", ansi_cp, oem_cp );
|
|
|
|
|
|
|
|
buf[0] = 0;
|
|
|
|
len = sizeof(buf);
|
|
|
|
if (!RegQueryValueExA(wine_fonts_key, "Codepages", 0, &type, (BYTE *)buf, &len) && type == REG_SZ)
|
|
|
|
{
|
|
|
|
if (!strcmp( buf, cpbuf ) && screen_dpi == font_dpi) return; /* already set correctly */
|
|
|
|
TRACE("updating registry, codepages/logpixels changed %s/%u -> %u,%u/%u\n",
|
|
|
|
buf, font_dpi, ansi_cp, oem_cp, screen_dpi);
|
|
|
|
}
|
|
|
|
else TRACE("updating registry, codepages/logpixels changed none -> %u,%u/%u\n",
|
|
|
|
ansi_cp, oem_cp, screen_dpi);
|
|
|
|
|
|
|
|
RegSetValueExA(wine_fonts_key, "Codepages", 0, REG_SZ, (const BYTE *)cpbuf, strlen(cpbuf)+1);
|
2020-11-06 12:08:16 +01:00
|
|
|
RegSetValueExW(wine_fonts_key, L"LogPixels", 0, REG_DWORD, (const BYTE *)&screen_dpi, sizeof(screen_dpi));
|
2020-09-30 16:08:21 +02:00
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(nls_update_font_list); i++)
|
|
|
|
{
|
|
|
|
if (nls_update_font_list[i].ansi_cp == ansi_cp && nls_update_font_list[i].oem_cp == oem_cp)
|
|
|
|
{
|
2020-11-06 12:08:16 +01:00
|
|
|
if (!RegCreateKeyW( HKEY_CURRENT_CONFIG, L"Software\\Fonts", &hkey ))
|
2020-09-30 16:08:21 +02:00
|
|
|
{
|
|
|
|
RegSetValueExA(hkey, "OEMFONT.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].oem,
|
|
|
|
strlen(nls_update_font_list[i].oem)+1);
|
|
|
|
RegSetValueExA(hkey, "FIXEDFON.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].fixed,
|
|
|
|
strlen(nls_update_font_list[i].fixed)+1);
|
|
|
|
RegSetValueExA(hkey, "FONTS.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].system,
|
|
|
|
strlen(nls_update_font_list[i].system)+1);
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
}
|
2020-11-06 12:08:16 +01:00
|
|
|
if (!RegCreateKeyW( HKEY_LOCAL_MACHINE,
|
|
|
|
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts", &hkey ))
|
2020-09-30 16:08:21 +02:00
|
|
|
{
|
|
|
|
add_font_list(hkey, &nls_update_font_list[i], screen_dpi);
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
}
|
2020-11-06 12:08:16 +01:00
|
|
|
if (!RegCreateKeyW( HKEY_LOCAL_MACHINE,
|
|
|
|
L"Software\\Microsoft\\Windows\\CurrentVersion\\Fonts", &hkey ))
|
2020-09-30 16:08:21 +02:00
|
|
|
{
|
|
|
|
add_font_list(hkey, &nls_update_font_list[i], screen_dpi);
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
}
|
2021-05-27 07:50:48 +02:00
|
|
|
/* Only update these if the Codepage changed. */
|
|
|
|
if (strcmp( buf, cpbuf ) && !RegCreateKeyW( HKEY_LOCAL_MACHINE,
|
2020-11-06 12:08:16 +01:00
|
|
|
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes", &hkey ))
|
2020-09-30 16:08:21 +02:00
|
|
|
{
|
|
|
|
RegSetValueExA(hkey, "MS Shell Dlg", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].shelldlg,
|
|
|
|
strlen(nls_update_font_list[i].shelldlg)+1);
|
|
|
|
RegSetValueExA(hkey, "Tms Rmn", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].tmsrmn,
|
|
|
|
strlen(nls_update_font_list[i].tmsrmn)+1);
|
|
|
|
|
|
|
|
set_value_key(hkey, "Fixedsys,0", nls_update_font_list[i].fixed_0);
|
|
|
|
set_value_key(hkey, "System,0", nls_update_font_list[i].system_0);
|
|
|
|
set_value_key(hkey, "Courier,0", nls_update_font_list[i].courier_0);
|
|
|
|
set_value_key(hkey, "MS Serif,0", nls_update_font_list[i].serif_0);
|
|
|
|
set_value_key(hkey, "Small Fonts,0", nls_update_font_list[i].small_0);
|
|
|
|
set_value_key(hkey, "MS Sans Serif,0", nls_update_font_list[i].sserif_0);
|
|
|
|
set_value_key(hkey, "Helv,0", nls_update_font_list[i].helv_0);
|
|
|
|
set_value_key(hkey, "Tms Rmn,0", nls_update_font_list[i].tmsrmn_0);
|
|
|
|
|
|
|
|
set_value_key(hkey, nls_update_font_list[i].arial_0.from, nls_update_font_list[i].arial_0.to);
|
|
|
|
set_value_key(hkey, nls_update_font_list[i].courier_new_0.from, nls_update_font_list[i].courier_new_0.to);
|
|
|
|
set_value_key(hkey, nls_update_font_list[i].times_new_roman_0.from, nls_update_font_list[i].times_new_roman_0.to);
|
|
|
|
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
}
|
|
|
|
done = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Delete the FontSubstitutes from other locales */
|
2020-11-06 12:08:16 +01:00
|
|
|
if (!RegCreateKeyW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes", &hkey ))
|
2020-09-30 16:08:21 +02:00
|
|
|
{
|
|
|
|
set_value_key(hkey, nls_update_font_list[i].arial_0.from, NULL);
|
|
|
|
set_value_key(hkey, nls_update_font_list[i].courier_new_0.from, NULL);
|
|
|
|
set_value_key(hkey, nls_update_font_list[i].times_new_roman_0.from, NULL);
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!done)
|
|
|
|
FIXME("there is no font defaults for codepages %u,%u\n", ansi_cp, oem_cp);
|
|
|
|
|
|
|
|
/* update locale dependent font association info and font system link info in registry.
|
|
|
|
update only when codepages changed, not logpixels. */
|
|
|
|
if (strcmp(buf, cpbuf) != 0)
|
|
|
|
{
|
|
|
|
update_font_association_info(ansi_cp);
|
|
|
|
update_font_system_link_info(ansi_cp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-20 22:05:37 +02:00
|
|
|
|
|
|
|
/*************************************************************
|
|
|
|
* font_CreateDC
|
|
|
|
*/
|
|
|
|
static BOOL CDECL font_CreateDC( PHYSDEV *dev, LPCWSTR driver, LPCWSTR device,
|
|
|
|
LPCWSTR output, const DEVMODEW *devmode )
|
|
|
|
{
|
|
|
|
struct font_physdev *physdev;
|
|
|
|
|
|
|
|
if (!font_funcs) return TRUE;
|
|
|
|
if (!(physdev = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physdev) ))) return FALSE;
|
|
|
|
push_dc_driver( dev, &physdev->dev, &font_driver );
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************
|
|
|
|
* font_DeleteDC
|
|
|
|
*/
|
|
|
|
static BOOL CDECL font_DeleteDC( PHYSDEV dev )
|
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
|
|
|
|
2020-10-21 11:01:50 +02:00
|
|
|
release_gdi_font( physdev->font );
|
2020-10-20 22:05:37 +02:00
|
|
|
HeapFree( GetProcessHeap(), 0, physdev );
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-31 16:13:33 +01:00
|
|
|
struct gdi_font_enum_data
|
|
|
|
{
|
|
|
|
ENUMLOGFONTEXW elf;
|
|
|
|
NEWTEXTMETRICEXW ntm;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct enum_charset
|
|
|
|
{
|
|
|
|
DWORD mask;
|
|
|
|
DWORD charset;
|
|
|
|
DWORD script;
|
|
|
|
};
|
|
|
|
|
|
|
|
static BOOL is_complex_script_ansi_cp( UINT ansi_cp )
|
|
|
|
{
|
|
|
|
return (ansi_cp == 874 /* Thai */
|
|
|
|
|| ansi_cp == 1255 /* Hebrew */
|
|
|
|
|| ansi_cp == 1256 /* Arabic */
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************
|
|
|
|
* create_enum_charset_list
|
|
|
|
*
|
|
|
|
* This function creates charset enumeration list because in DEFAULT_CHARSET
|
|
|
|
* case, the ANSI codepage's charset takes precedence over other charsets.
|
|
|
|
* Above rule doesn't apply if the ANSI codepage uses complex script (e.g. Thai).
|
|
|
|
* This function works as a filter other than DEFAULT_CHARSET case.
|
|
|
|
*/
|
|
|
|
static DWORD create_enum_charset_list(DWORD charset, struct enum_charset *list)
|
|
|
|
{
|
|
|
|
struct enum_charset *start = list;
|
|
|
|
CHARSETINFO csi;
|
|
|
|
int i;
|
|
|
|
|
2021-09-01 14:09:04 +02:00
|
|
|
if (translate_charset_info( ULongToPtr(charset), &csi, TCI_SRCCHARSET ) && csi.fs.fsCsb[0] != 0)
|
2020-10-31 16:13:33 +01:00
|
|
|
{
|
|
|
|
list->mask = csi.fs.fsCsb[0];
|
|
|
|
list->charset = csi.ciCharset;
|
|
|
|
for (i = 0; i < 32; i++) if (csi.fs.fsCsb[0] & (1u << i)) list->script = i;
|
|
|
|
list++;
|
|
|
|
}
|
|
|
|
else /* charset is DEFAULT_CHARSET or invalid. */
|
|
|
|
{
|
|
|
|
int acp = GetACP();
|
|
|
|
DWORD mask = 0;
|
|
|
|
|
|
|
|
/* Set the current codepage's charset as the first element. */
|
|
|
|
if (!is_complex_script_ansi_cp(acp) &&
|
2021-09-01 14:09:04 +02:00
|
|
|
translate_charset_info( (DWORD *)(INT_PTR)acp, &csi, TCI_SRCCODEPAGE ) &&
|
2020-10-31 16:13:33 +01:00
|
|
|
csi.fs.fsCsb[0] != 0)
|
|
|
|
{
|
|
|
|
list->mask = csi.fs.fsCsb[0];
|
|
|
|
list->charset = csi.ciCharset;
|
|
|
|
for (i = 0; i < 32; i++) if (csi.fs.fsCsb[0] & (1u << i)) list->script = i;
|
|
|
|
mask |= csi.fs.fsCsb[0];
|
|
|
|
list++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fill out left elements. */
|
|
|
|
for (i = 0; i < 32; i++)
|
|
|
|
{
|
|
|
|
FONTSIGNATURE fs;
|
|
|
|
fs.fsCsb[0] = 1u << i;
|
|
|
|
fs.fsCsb[1] = 0;
|
|
|
|
if (fs.fsCsb[0] & mask) continue; /* skip, already added. */
|
2021-09-01 14:09:04 +02:00
|
|
|
if (!translate_charset_info( fs.fsCsb, &csi, TCI_SRCFONTSIG ))
|
2020-10-31 16:13:33 +01:00
|
|
|
continue; /* skip, this is an invalid fsCsb bit. */
|
|
|
|
list->mask = fs.fsCsb[0];
|
|
|
|
list->charset = csi.ciCharset;
|
|
|
|
list->script = i;
|
|
|
|
mask |= fs.fsCsb[0];
|
|
|
|
list++;
|
|
|
|
}
|
|
|
|
/* add catch all mask for remaining bits */
|
|
|
|
if (~mask)
|
|
|
|
{
|
|
|
|
list->mask = ~mask;
|
|
|
|
list->charset = DEFAULT_CHARSET;
|
2021-09-20 13:13:47 +02:00
|
|
|
list->script = 33; /* other */
|
2020-10-31 16:13:33 +01:00
|
|
|
list++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return list - start;
|
|
|
|
}
|
|
|
|
|
|
|
|
static UINT get_font_type( const NEWTEXTMETRICEXW *ntm )
|
|
|
|
{
|
|
|
|
UINT ret = 0;
|
|
|
|
|
|
|
|
if (ntm->ntmTm.tmPitchAndFamily & TMPF_TRUETYPE) ret |= TRUETYPE_FONTTYPE;
|
|
|
|
if (ntm->ntmTm.tmPitchAndFamily & TMPF_DEVICE) ret |= DEVICE_FONTTYPE;
|
|
|
|
if (!(ntm->ntmTm.tmPitchAndFamily & TMPF_VECTOR)) ret |= RASTER_FONTTYPE;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL get_face_enum_data( struct gdi_font_face *face, ENUMLOGFONTEXW *elf, NEWTEXTMETRICEXW *ntm )
|
|
|
|
{
|
|
|
|
struct gdi_font *font;
|
2021-04-06 14:34:21 +02:00
|
|
|
LOGFONTW lf = { .lfHeight = -4096 /* preferable EM Square size */ };
|
|
|
|
|
|
|
|
if (!face->scalable) lf.lfHeight = 0;
|
2020-10-31 16:13:33 +01:00
|
|
|
|
|
|
|
if (!(font = create_gdi_font( face, NULL, &lf ))) return FALSE;
|
|
|
|
|
|
|
|
if (!font_funcs->load_font( font ))
|
|
|
|
{
|
|
|
|
free_gdi_font( font );
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2021-04-06 14:34:21 +02:00
|
|
|
if (font->scalable && -lf.lfHeight % font->otm.otmEMSquare != 0)
|
|
|
|
{
|
|
|
|
/* reload with the original EM Square size */
|
|
|
|
lf.lfHeight = -font->otm.otmEMSquare;
|
|
|
|
free_gdi_font( font );
|
|
|
|
|
|
|
|
if (!(font = create_gdi_font( face, NULL, &lf ))) return FALSE;
|
|
|
|
if (!font_funcs->load_font( font ))
|
|
|
|
{
|
|
|
|
free_gdi_font( font );
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-31 16:13:33 +01:00
|
|
|
if (font_funcs->set_outline_text_metrics( font ))
|
|
|
|
{
|
2021-04-06 14:34:21 +02:00
|
|
|
static const DWORD ntm_ppem = 32;
|
2021-04-06 14:34:22 +02:00
|
|
|
UINT cell_height;
|
2021-04-06 14:34:21 +02:00
|
|
|
|
|
|
|
#define TM font->otm.otmTextMetrics
|
|
|
|
#define SCALE_NTM(value) (MulDiv( ntm->ntmTm.tmHeight, (value), TM.tmHeight ))
|
2021-04-06 14:34:22 +02:00
|
|
|
cell_height = TM.tmHeight / ( -lf.lfHeight / font->otm.otmEMSquare );
|
|
|
|
ntm->ntmTm.tmHeight = MulDiv( ntm_ppem, cell_height, font->otm.otmEMSquare );
|
2021-04-06 14:34:21 +02:00
|
|
|
ntm->ntmTm.tmAscent = SCALE_NTM( TM.tmAscent );
|
|
|
|
ntm->ntmTm.tmDescent = ntm->ntmTm.tmHeight - ntm->ntmTm.tmAscent;
|
|
|
|
ntm->ntmTm.tmInternalLeading = SCALE_NTM( TM.tmInternalLeading );
|
|
|
|
ntm->ntmTm.tmExternalLeading = SCALE_NTM( TM.tmExternalLeading );
|
|
|
|
ntm->ntmTm.tmAveCharWidth = SCALE_NTM( TM.tmAveCharWidth );
|
|
|
|
ntm->ntmTm.tmMaxCharWidth = SCALE_NTM( TM.tmMaxCharWidth );
|
|
|
|
|
|
|
|
memcpy((char *)&ntm->ntmTm + offsetof( TEXTMETRICW, tmWeight ),
|
|
|
|
(const char *)&TM + offsetof( TEXTMETRICW, tmWeight ),
|
|
|
|
sizeof(TEXTMETRICW) - offsetof( TEXTMETRICW, tmWeight ));
|
2020-10-31 16:13:33 +01:00
|
|
|
ntm->ntmTm.ntmSizeEM = font->otm.otmEMSquare;
|
2021-04-06 14:34:22 +02:00
|
|
|
ntm->ntmTm.ntmCellHeight = cell_height;
|
2020-10-31 16:13:33 +01:00
|
|
|
ntm->ntmTm.ntmAvgWidth = font->ntmAvgWidth;
|
2021-04-06 14:34:21 +02:00
|
|
|
#undef SCALE_NTM
|
|
|
|
#undef TM
|
2020-10-31 16:13:33 +01:00
|
|
|
}
|
|
|
|
else if (font_funcs->set_bitmap_text_metrics( font ))
|
|
|
|
{
|
|
|
|
memcpy( &ntm->ntmTm, &font->otm.otmTextMetrics, sizeof(TEXTMETRICW) );
|
|
|
|
ntm->ntmTm.ntmSizeEM = ntm->ntmTm.tmHeight - ntm->ntmTm.tmInternalLeading;
|
|
|
|
ntm->ntmTm.ntmCellHeight = ntm->ntmTm.tmHeight;
|
|
|
|
ntm->ntmTm.ntmAvgWidth = ntm->ntmTm.tmAveCharWidth;
|
|
|
|
}
|
|
|
|
ntm->ntmTm.ntmFlags = font->ntmFlags;
|
|
|
|
ntm->ntmFontSig = font->fs;
|
|
|
|
|
|
|
|
elf->elfLogFont.lfEscapement = 0;
|
|
|
|
elf->elfLogFont.lfOrientation = 0;
|
|
|
|
elf->elfLogFont.lfHeight = ntm->ntmTm.tmHeight;
|
|
|
|
elf->elfLogFont.lfWidth = ntm->ntmTm.tmAveCharWidth;
|
|
|
|
elf->elfLogFont.lfWeight = ntm->ntmTm.tmWeight;
|
|
|
|
elf->elfLogFont.lfItalic = ntm->ntmTm.tmItalic;
|
|
|
|
elf->elfLogFont.lfUnderline = ntm->ntmTm.tmUnderlined;
|
|
|
|
elf->elfLogFont.lfStrikeOut = ntm->ntmTm.tmStruckOut;
|
|
|
|
elf->elfLogFont.lfCharSet = ntm->ntmTm.tmCharSet;
|
|
|
|
elf->elfLogFont.lfOutPrecision = OUT_STROKE_PRECIS;
|
|
|
|
elf->elfLogFont.lfClipPrecision = CLIP_STROKE_PRECIS;
|
|
|
|
elf->elfLogFont.lfQuality = DRAFT_QUALITY;
|
|
|
|
elf->elfLogFont.lfPitchAndFamily = (ntm->ntmTm.tmPitchAndFamily & 0xf1) + 1;
|
|
|
|
lstrcpynW( elf->elfLogFont.lfFaceName, (WCHAR *)font->otm.otmpFamilyName, LF_FACESIZE );
|
|
|
|
lstrcpynW( elf->elfFullName, (WCHAR *)font->otm.otmpFaceName, LF_FULLFACESIZE );
|
|
|
|
lstrcpynW( elf->elfStyle, (WCHAR *)font->otm.otmpStyleName, LF_FACESIZE );
|
|
|
|
|
|
|
|
free_gdi_font( font );
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL family_matches( struct gdi_font_family *family, const WCHAR *face_name )
|
|
|
|
{
|
|
|
|
struct gdi_font_face *face;
|
|
|
|
|
2020-11-23 13:20:50 +01:00
|
|
|
if (!facename_compare( face_name, family->family_name, LF_FACESIZE - 1 )) return TRUE;
|
2020-10-31 16:13:33 +01:00
|
|
|
LIST_FOR_EACH_ENTRY( face, get_family_face_list(family), struct gdi_font_face, entry )
|
2020-11-23 13:20:50 +01:00
|
|
|
if (!facename_compare( face_name, face->full_name, LF_FACESIZE - 1 )) return TRUE;
|
2020-10-31 16:13:33 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL face_matches( const WCHAR *family_name, struct gdi_font_face *face, const WCHAR *face_name )
|
|
|
|
{
|
2020-11-23 13:20:50 +01:00
|
|
|
if (!facename_compare( face_name, family_name, LF_FACESIZE - 1)) return TRUE;
|
|
|
|
return !facename_compare( face_name, face->full_name, LF_FACESIZE - 1 );
|
2020-10-31 16:13:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL enum_face_charsets( const struct gdi_font_family *family, struct gdi_font_face *face,
|
|
|
|
struct enum_charset *list, DWORD count, FONTENUMPROCW proc, LPARAM lparam,
|
|
|
|
const WCHAR *subst )
|
|
|
|
{
|
|
|
|
ENUMLOGFONTEXW elf;
|
|
|
|
NEWTEXTMETRICEXW ntm;
|
|
|
|
DWORD type, i;
|
|
|
|
|
|
|
|
if (!face->cached_enum_data)
|
|
|
|
{
|
|
|
|
struct gdi_font_enum_data *data;
|
|
|
|
|
2020-11-05 09:59:22 +01:00
|
|
|
if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) )) ||
|
|
|
|
!get_face_enum_data( face, &data->elf, &data->ntm ))
|
2020-10-31 16:13:33 +01:00
|
|
|
{
|
|
|
|
HeapFree( GetProcessHeap(), 0, data );
|
2020-11-05 09:59:22 +01:00
|
|
|
return TRUE;
|
2020-10-31 16:13:33 +01:00
|
|
|
}
|
|
|
|
face->cached_enum_data = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
elf = face->cached_enum_data->elf;
|
|
|
|
ntm = face->cached_enum_data->ntm;
|
|
|
|
type = get_font_type( &ntm );
|
|
|
|
|
|
|
|
/* font replacement */
|
|
|
|
if (family != face->family)
|
|
|
|
{
|
|
|
|
lstrcpynW( elf.elfLogFont.lfFaceName, family->family_name, LF_FACESIZE );
|
|
|
|
lstrcpynW( elf.elfFullName, face->full_name, LF_FULLFACESIZE );
|
|
|
|
}
|
|
|
|
if (subst) lstrcpynW( elf.elfLogFont.lfFaceName, subst, LF_FACESIZE );
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
2021-04-27 23:03:51 +02:00
|
|
|
if (face->fs.fsCsb[0] == 0) /* OEM */
|
2020-10-31 16:13:33 +01:00
|
|
|
{
|
|
|
|
elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
|
2021-09-20 13:13:47 +02:00
|
|
|
elf.elfScript[0] = 32;
|
2020-10-31 16:13:33 +01:00
|
|
|
i = count; /* break out of loop after enumeration */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!(face->fs.fsCsb[0] & list[i].mask)) continue;
|
|
|
|
/* use the DEFAULT_CHARSET case only if no other charset is present */
|
|
|
|
if (list[i].charset == DEFAULT_CHARSET && (face->fs.fsCsb[0] & ~list[i].mask)) continue;
|
|
|
|
elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = list[i].charset;
|
2021-09-20 13:13:47 +02:00
|
|
|
/* caller may fill elfScript with the actual string, see load_script_name */
|
|
|
|
elf.elfScript[0] = list[i].script;
|
2020-10-31 16:13:33 +01:00
|
|
|
}
|
|
|
|
TRACE( "face %s full %s style %s charset = %d type %d script %s it %d weight %d ntmflags %08x\n",
|
|
|
|
debugstr_w(elf.elfLogFont.lfFaceName), debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
|
|
|
|
elf.elfLogFont.lfCharSet, type, debugstr_w(elf.elfScript),
|
|
|
|
elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight, ntm.ntmTm.ntmFlags );
|
|
|
|
/* release section before callback (FIXME) */
|
|
|
|
LeaveCriticalSection( &font_cs );
|
|
|
|
if (!proc( &elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam )) return FALSE;
|
|
|
|
EnterCriticalSection( &font_cs );
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2020-10-20 22:05:37 +02:00
|
|
|
/*************************************************************
|
|
|
|
* font_EnumFonts
|
|
|
|
*/
|
|
|
|
static BOOL CDECL font_EnumFonts( PHYSDEV dev, LOGFONTW *lf, FONTENUMPROCW proc, LPARAM lparam )
|
|
|
|
{
|
2020-10-31 16:13:33 +01:00
|
|
|
struct gdi_font_family *family;
|
|
|
|
struct gdi_font_face *face;
|
|
|
|
struct enum_charset enum_charsets[32];
|
|
|
|
DWORD count, charset;
|
|
|
|
|
|
|
|
charset = lf ? lf->lfCharSet : DEFAULT_CHARSET;
|
|
|
|
|
|
|
|
count = create_enum_charset_list( charset, enum_charsets );
|
|
|
|
|
|
|
|
EnterCriticalSection( &font_cs );
|
|
|
|
|
|
|
|
if (lf && lf->lfFaceName[0])
|
|
|
|
{
|
|
|
|
const WCHAR *face_name = get_gdi_font_subst( lf->lfFaceName, charset, NULL );
|
|
|
|
const WCHAR *orig_name = NULL;
|
|
|
|
|
|
|
|
TRACE( "facename = %s charset %d\n", debugstr_w(lf->lfFaceName), charset );
|
|
|
|
if (face_name)
|
|
|
|
{
|
|
|
|
orig_name = lf->lfFaceName;
|
|
|
|
TRACE( "substituting %s -> %s\n", debugstr_w(lf->lfFaceName), debugstr_w(face_name) );
|
|
|
|
}
|
|
|
|
else face_name = lf->lfFaceName;
|
|
|
|
|
2020-11-13 10:05:55 +01:00
|
|
|
WINE_RB_FOR_EACH_ENTRY( family, &family_name_tree, struct gdi_font_family, name_entry )
|
2020-10-31 16:13:33 +01:00
|
|
|
{
|
|
|
|
if (!family_matches(family, face_name)) continue;
|
|
|
|
LIST_FOR_EACH_ENTRY( face, get_family_face_list(family), struct gdi_font_face, entry )
|
|
|
|
{
|
|
|
|
if (!face_matches( family->family_name, face, face_name )) continue;
|
|
|
|
if (!enum_face_charsets( family, face, enum_charsets, count, proc, lparam, orig_name ))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TRACE( "charset %d\n", charset );
|
2020-11-13 10:05:55 +01:00
|
|
|
WINE_RB_FOR_EACH_ENTRY( family, &family_name_tree, struct gdi_font_family, name_entry )
|
2020-10-31 16:13:33 +01:00
|
|
|
{
|
|
|
|
face = LIST_ENTRY( list_head(get_family_face_list(family)), struct gdi_font_face, entry );
|
|
|
|
if (!enum_face_charsets( family, face, enum_charsets, count, proc, lparam, NULL ))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LeaveCriticalSection( &font_cs );
|
|
|
|
return TRUE;
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-29 14:47:18 +01:00
|
|
|
static BOOL check_unicode_tategaki( WCHAR ch )
|
|
|
|
{
|
|
|
|
extern const unsigned short vertical_orientation_table[] DECLSPEC_HIDDEN;
|
|
|
|
unsigned short orientation = vertical_orientation_table[vertical_orientation_table[vertical_orientation_table[ch >> 8]+((ch >> 4) & 0x0f)]+ (ch & 0xf)];
|
|
|
|
|
|
|
|
/* We only reach this code if typographical substitution did not occur */
|
|
|
|
/* Type: U or Type: Tu */
|
|
|
|
return (orientation == 1 || orientation == 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
static UINT get_glyph_index_symbol( struct gdi_font *font, UINT glyph )
|
|
|
|
{
|
|
|
|
UINT index;
|
|
|
|
|
|
|
|
if (glyph < 0x100) glyph += 0xf000;
|
|
|
|
/* there are a number of old pre-Unicode "broken" TTFs, which
|
|
|
|
do have symbols at U+00XX instead of U+f0XX */
|
|
|
|
index = glyph;
|
|
|
|
font_funcs->get_glyph_index( font, &index, FALSE );
|
|
|
|
if (!index)
|
|
|
|
{
|
|
|
|
index = glyph - 0xf000;
|
|
|
|
font_funcs->get_glyph_index( font, &index, FALSE );
|
|
|
|
}
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
|
|
|
static UINT get_glyph_index( struct gdi_font *font, UINT glyph )
|
|
|
|
{
|
|
|
|
WCHAR wc = glyph;
|
|
|
|
char ch;
|
|
|
|
BOOL used;
|
|
|
|
|
|
|
|
if (font_funcs->get_glyph_index( font, &glyph, TRUE )) return glyph;
|
|
|
|
|
|
|
|
if (font->codepage == CP_SYMBOL)
|
|
|
|
{
|
|
|
|
glyph = get_glyph_index_symbol( font, wc );
|
|
|
|
if (!glyph)
|
|
|
|
{
|
2021-01-20 11:54:48 +01:00
|
|
|
if (WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, &wc, 1, &ch, 1, NULL, NULL ))
|
2020-10-29 14:47:18 +01:00
|
|
|
glyph = get_glyph_index_symbol( font, (unsigned char)ch );
|
|
|
|
}
|
|
|
|
}
|
2021-01-20 11:54:48 +01:00
|
|
|
else if (WideCharToMultiByte( font->codepage, WC_NO_BEST_FIT_CHARS, &wc, 1, &ch, 1, NULL, &used ) && !used)
|
2020-10-29 14:47:18 +01:00
|
|
|
{
|
|
|
|
glyph = (unsigned char)ch;
|
|
|
|
font_funcs->get_glyph_index( font, &glyph, FALSE );
|
|
|
|
}
|
2020-12-14 16:55:14 +01:00
|
|
|
else return 0;
|
|
|
|
|
2020-10-29 14:47:18 +01:00
|
|
|
return glyph;
|
|
|
|
}
|
|
|
|
|
|
|
|
static UINT get_glyph_index_linked( struct gdi_font **font, UINT glyph )
|
|
|
|
{
|
|
|
|
struct gdi_font *child;
|
|
|
|
UINT res;
|
|
|
|
|
|
|
|
if ((res = get_glyph_index( *font, glyph ))) return res;
|
|
|
|
if (glyph < 32) return 0; /* don't check linked fonts for control characters */
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY( child, &(*font)->child_fonts, struct gdi_font, entry )
|
|
|
|
{
|
|
|
|
if (!child->private && !font_funcs->load_font( child )) continue;
|
|
|
|
if ((res = get_glyph_index( child, glyph )))
|
|
|
|
{
|
|
|
|
*font = child;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static DWORD get_glyph_outline( struct gdi_font *font, UINT glyph, UINT format,
|
|
|
|
GLYPHMETRICS *gm_ret, ABC *abc_ret, DWORD buflen, void *buf,
|
|
|
|
const MAT2 *mat )
|
|
|
|
{
|
|
|
|
GLYPHMETRICS gm;
|
|
|
|
ABC abc;
|
|
|
|
DWORD ret = 1;
|
|
|
|
UINT index = glyph;
|
|
|
|
BOOL tategaki = (*get_gdi_font_name( font ) == '@');
|
|
|
|
|
|
|
|
if (format & GGO_GLYPH_INDEX)
|
|
|
|
{
|
|
|
|
/* Windows bitmap font, e.g. Small Fonts, uses ANSI character code
|
|
|
|
as glyph index. "Treasure Adventure Game" depends on this. */
|
|
|
|
font_funcs->get_glyph_index( font, &index, FALSE );
|
2021-01-11 05:18:42 +01:00
|
|
|
format &= ~GGO_GLYPH_INDEX;
|
2020-10-29 14:47:18 +01:00
|
|
|
/* TODO: Window also turns off tategaki for glyphs passed in by index
|
|
|
|
if their unicode code points fall outside of the range that is
|
|
|
|
rotated. */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
index = get_glyph_index_linked( &font, glyph );
|
|
|
|
if (tategaki)
|
|
|
|
{
|
|
|
|
UINT orig = index;
|
|
|
|
index = get_GSUB_vert_glyph( font, index );
|
|
|
|
if (index == orig) tategaki = check_unicode_tategaki( glyph );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mat && !memcmp( mat, &identity, sizeof(*mat) )) mat = NULL;
|
|
|
|
|
|
|
|
if (format == GGO_METRICS && !mat && get_gdi_font_glyph_metrics( font, index, &gm, &abc ))
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
ret = font_funcs->get_glyph_outline( font, index, format, &gm, &abc, buflen, buf, mat, tategaki );
|
|
|
|
if (ret == GDI_ERROR) return ret;
|
|
|
|
|
|
|
|
if ((format == GGO_METRICS || format == GGO_BITMAP || format == WINE_GGO_GRAY16_BITMAP) && !mat)
|
|
|
|
set_gdi_font_glyph_metrics( font, index, &gm, &abc );
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (gm_ret) *gm_ret = gm;
|
|
|
|
if (abc_ret) *abc_ret = abc;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-20 22:05:37 +02:00
|
|
|
/*************************************************************
|
|
|
|
* font_FontIsLinked
|
|
|
|
*/
|
|
|
|
static BOOL CDECL font_FontIsLinked( PHYSDEV dev )
|
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
|
|
|
|
|
|
|
if (!physdev->font)
|
|
|
|
{
|
|
|
|
dev = GET_NEXT_PHYSDEV( dev, pFontIsLinked );
|
|
|
|
return dev->funcs->pFontIsLinked( dev );
|
|
|
|
}
|
2020-10-29 14:44:25 +01:00
|
|
|
return !list_empty( &physdev->font->child_fonts );
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************
|
|
|
|
* font_GetCharABCWidths
|
|
|
|
*/
|
2021-08-27 14:51:49 +02:00
|
|
|
static BOOL CDECL font_GetCharABCWidths( PHYSDEV dev, UINT first, UINT count,
|
|
|
|
WCHAR *chars, ABC *buffer )
|
2020-10-20 22:05:37 +02:00
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
2021-08-27 14:51:49 +02:00
|
|
|
UINT c, i;
|
2020-10-20 22:05:37 +02:00
|
|
|
|
|
|
|
if (!physdev->font)
|
|
|
|
{
|
|
|
|
dev = GET_NEXT_PHYSDEV( dev, pGetCharABCWidths );
|
2021-08-27 14:51:49 +02:00
|
|
|
return dev->funcs->pGetCharABCWidths( dev, first, count, chars, buffer );
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
2020-10-22 11:56:47 +02:00
|
|
|
|
2021-08-27 14:51:49 +02:00
|
|
|
TRACE( "%p, %u, %u, %p\n", physdev->font, first, count, buffer );
|
2020-10-22 11:56:47 +02:00
|
|
|
|
2020-10-22 11:54:35 +02:00
|
|
|
EnterCriticalSection( &font_cs );
|
2021-08-27 14:51:49 +02:00
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
c = chars ? chars[i] : first + i;
|
|
|
|
get_glyph_outline( physdev->font, c, GGO_METRICS, NULL, &buffer[i], 0, NULL, NULL );
|
|
|
|
}
|
2020-10-22 11:54:35 +02:00
|
|
|
LeaveCriticalSection( &font_cs );
|
2020-10-22 11:56:47 +02:00
|
|
|
return TRUE;
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************
|
|
|
|
* font_GetCharABCWidthsI
|
|
|
|
*/
|
|
|
|
static BOOL CDECL font_GetCharABCWidthsI( PHYSDEV dev, UINT first, UINT count, WORD *gi, ABC *buffer )
|
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
2020-10-22 11:56:47 +02:00
|
|
|
UINT c;
|
2020-10-20 22:05:37 +02:00
|
|
|
|
|
|
|
if (!physdev->font)
|
|
|
|
{
|
|
|
|
dev = GET_NEXT_PHYSDEV( dev, pGetCharABCWidthsI );
|
|
|
|
return dev->funcs->pGetCharABCWidthsI( dev, first, count, gi, buffer );
|
|
|
|
}
|
2020-10-22 11:56:47 +02:00
|
|
|
|
|
|
|
TRACE( "%p, %u, %u, %p\n", physdev->font, first, count, buffer );
|
|
|
|
|
2020-10-22 11:54:35 +02:00
|
|
|
EnterCriticalSection( &font_cs );
|
2020-10-22 11:56:47 +02:00
|
|
|
for (c = 0; c < count; c++, buffer++)
|
2020-10-29 14:47:18 +01:00
|
|
|
get_glyph_outline( physdev->font, gi ? gi[c] : first + c, GGO_METRICS | GGO_GLYPH_INDEX,
|
|
|
|
NULL, buffer, 0, NULL, NULL );
|
2020-10-22 11:54:35 +02:00
|
|
|
LeaveCriticalSection( &font_cs );
|
2020-10-22 11:56:47 +02:00
|
|
|
return TRUE;
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************
|
|
|
|
* font_GetCharWidth
|
|
|
|
*/
|
2021-08-26 14:45:15 +02:00
|
|
|
static BOOL CDECL font_GetCharWidth( PHYSDEV dev, UINT first, UINT count,
|
|
|
|
const WCHAR *chars, INT *buffer )
|
2020-10-20 22:05:37 +02:00
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
2021-08-26 14:45:15 +02:00
|
|
|
UINT c, i;
|
2020-10-22 11:56:47 +02:00
|
|
|
ABC abc;
|
2020-10-20 22:05:37 +02:00
|
|
|
|
|
|
|
if (!physdev->font)
|
|
|
|
{
|
|
|
|
dev = GET_NEXT_PHYSDEV( dev, pGetCharWidth );
|
2021-08-26 14:45:15 +02:00
|
|
|
return dev->funcs->pGetCharWidth( dev, first, count, chars, buffer );
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
2020-10-22 11:56:47 +02:00
|
|
|
|
2021-08-26 14:45:15 +02:00
|
|
|
TRACE( "%p, %d, %d, %p\n", physdev->font, first, count, buffer );
|
2020-10-22 11:56:47 +02:00
|
|
|
|
2020-10-22 11:54:35 +02:00
|
|
|
EnterCriticalSection( &font_cs );
|
2021-08-26 14:45:15 +02:00
|
|
|
for (i = 0; i < count; i++)
|
2020-10-22 11:56:47 +02:00
|
|
|
{
|
2021-08-26 14:45:15 +02:00
|
|
|
c = chars ? chars[i] : i + first;
|
2020-10-29 14:47:18 +01:00
|
|
|
if (get_glyph_outline( physdev->font, c, GGO_METRICS, NULL, &abc, 0, NULL, NULL ) == GDI_ERROR)
|
2021-08-26 14:45:15 +02:00
|
|
|
buffer[i] = 0;
|
2020-10-22 11:56:47 +02:00
|
|
|
else
|
2021-08-26 14:45:15 +02:00
|
|
|
buffer[i] = abc.abcA + abc.abcB + abc.abcC;
|
2020-10-22 11:56:47 +02:00
|
|
|
}
|
2020-10-22 11:54:35 +02:00
|
|
|
LeaveCriticalSection( &font_cs );
|
2020-10-22 11:56:47 +02:00
|
|
|
return TRUE;
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************
|
|
|
|
* font_GetCharWidthInfo
|
|
|
|
*/
|
|
|
|
static BOOL CDECL font_GetCharWidthInfo( PHYSDEV dev, void *ptr )
|
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
2020-10-28 10:14:01 +01:00
|
|
|
struct char_width_info *info = ptr;
|
2020-10-20 22:05:37 +02:00
|
|
|
|
|
|
|
if (!physdev->font)
|
|
|
|
{
|
|
|
|
dev = GET_NEXT_PHYSDEV( dev, pGetCharWidthInfo );
|
|
|
|
return dev->funcs->pGetCharWidthInfo( dev, ptr );
|
|
|
|
}
|
2020-10-28 10:14:01 +01:00
|
|
|
|
|
|
|
info->unk = 0;
|
|
|
|
if (!physdev->font->scalable || !font_funcs->get_char_width_info( physdev->font, info ))
|
|
|
|
info->lsb = info->rsb = 0;
|
|
|
|
|
|
|
|
return TRUE;
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************
|
|
|
|
* font_GetFontData
|
|
|
|
*/
|
|
|
|
static DWORD CDECL font_GetFontData( PHYSDEV dev, DWORD table, DWORD offset, void *buf, DWORD size )
|
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
|
|
|
|
|
|
|
if (!physdev->font)
|
|
|
|
{
|
|
|
|
dev = GET_NEXT_PHYSDEV( dev, pGetFontData );
|
|
|
|
return dev->funcs->pGetFontData( dev, table, offset, buf, size );
|
|
|
|
}
|
2020-10-22 11:57:48 +02:00
|
|
|
return font_funcs->get_font_data( physdev->font, table, offset, buf, size );
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************
|
|
|
|
* font_GetFontRealizationInfo
|
|
|
|
*/
|
|
|
|
static BOOL CDECL font_GetFontRealizationInfo( PHYSDEV dev, void *ptr )
|
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
2020-10-21 11:05:28 +02:00
|
|
|
struct font_realization_info *info = ptr;
|
2020-10-20 22:05:37 +02:00
|
|
|
|
|
|
|
if (!physdev->font)
|
|
|
|
{
|
|
|
|
dev = GET_NEXT_PHYSDEV( dev, pGetFontRealizationInfo );
|
|
|
|
return dev->funcs->pGetFontRealizationInfo( dev, ptr );
|
|
|
|
}
|
2020-10-21 11:05:28 +02:00
|
|
|
|
|
|
|
TRACE( "(%p, %p)\n", physdev->font, info);
|
|
|
|
|
|
|
|
info->flags = 1;
|
|
|
|
if (physdev->font->scalable) info->flags |= 2;
|
|
|
|
|
|
|
|
info->cache_num = physdev->font->cache_num;
|
|
|
|
info->instance_id = physdev->font->handle;
|
|
|
|
if (info->size == sizeof(*info))
|
|
|
|
{
|
2021-08-02 19:46:35 +02:00
|
|
|
info->file_count = 1;
|
2020-10-21 11:05:28 +02:00
|
|
|
info->face_index = physdev->font->face_index;
|
|
|
|
info->simulations = 0;
|
|
|
|
if (physdev->font->fake_bold) info->simulations |= 0x1;
|
|
|
|
if (physdev->font->fake_italic) info->simulations |= 0x2;
|
|
|
|
}
|
|
|
|
return TRUE;
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************
|
|
|
|
* font_GetFontUnicodeRanges
|
|
|
|
*/
|
|
|
|
static DWORD CDECL font_GetFontUnicodeRanges( PHYSDEV dev, GLYPHSET *glyphset )
|
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
2020-10-28 10:13:53 +01:00
|
|
|
DWORD size, num_ranges;
|
2020-10-20 22:05:37 +02:00
|
|
|
|
|
|
|
if (!physdev->font)
|
|
|
|
{
|
|
|
|
dev = GET_NEXT_PHYSDEV( dev, pGetFontUnicodeRanges );
|
|
|
|
return dev->funcs->pGetFontUnicodeRanges( dev, glyphset );
|
|
|
|
}
|
2020-10-28 10:13:53 +01:00
|
|
|
|
|
|
|
num_ranges = font_funcs->get_unicode_ranges( physdev->font, glyphset );
|
|
|
|
size = offsetof( GLYPHSET, ranges[num_ranges] );
|
|
|
|
if (glyphset)
|
|
|
|
{
|
|
|
|
glyphset->cbThis = size;
|
|
|
|
glyphset->cRanges = num_ranges;
|
|
|
|
glyphset->flAccel = 0;
|
|
|
|
}
|
|
|
|
return size;
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************
|
|
|
|
* font_GetGlyphIndices
|
|
|
|
*/
|
|
|
|
static DWORD CDECL font_GetGlyphIndices( PHYSDEV dev, const WCHAR *str, INT count, WORD *gi, DWORD flags )
|
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
2020-10-22 13:13:52 +02:00
|
|
|
UINT default_char;
|
|
|
|
char ch;
|
|
|
|
BOOL used, got_default = FALSE;
|
|
|
|
int i;
|
2020-10-20 22:05:37 +02:00
|
|
|
|
|
|
|
if (!physdev->font)
|
|
|
|
{
|
|
|
|
dev = GET_NEXT_PHYSDEV( dev, pGetGlyphIndices );
|
|
|
|
return dev->funcs->pGetGlyphIndices( dev, str, count, gi, flags );
|
|
|
|
}
|
2020-10-22 13:13:52 +02:00
|
|
|
|
|
|
|
if (flags & GGI_MARK_NONEXISTING_GLYPHS)
|
|
|
|
{
|
|
|
|
default_char = 0xffff; /* XP would use 0x1f for bitmap fonts */
|
|
|
|
got_default = TRUE;
|
|
|
|
}
|
|
|
|
|
2020-10-22 11:54:35 +02:00
|
|
|
EnterCriticalSection( &font_cs );
|
2020-10-22 13:13:52 +02:00
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
UINT glyph = str[i];
|
|
|
|
|
2020-10-29 14:47:18 +01:00
|
|
|
if (!font_funcs->get_glyph_index( physdev->font, &glyph, TRUE ))
|
2020-10-22 13:13:52 +02:00
|
|
|
{
|
|
|
|
glyph = 0;
|
|
|
|
if (physdev->font->codepage == CP_SYMBOL)
|
|
|
|
{
|
|
|
|
if (str[i] >= 0xf020 && str[i] <= 0xf100) glyph = str[i] - 0xf000;
|
|
|
|
else if (str[i] < 0x100) glyph = str[i];
|
|
|
|
}
|
2021-01-20 11:54:48 +01:00
|
|
|
else if (WideCharToMultiByte( physdev->font->codepage, WC_NO_BEST_FIT_CHARS, &str[i], 1,
|
2020-10-22 13:13:52 +02:00
|
|
|
&ch, 1, NULL, &used ) && !used)
|
|
|
|
glyph = (unsigned char)ch;
|
|
|
|
}
|
|
|
|
if (!glyph)
|
|
|
|
{
|
|
|
|
if (!got_default)
|
|
|
|
{
|
|
|
|
default_char = font_funcs->get_default_glyph( physdev->font );
|
|
|
|
got_default = TRUE;
|
|
|
|
}
|
2020-10-29 11:10:30 +01:00
|
|
|
gi[i] = default_char;
|
2020-10-22 13:13:52 +02:00
|
|
|
}
|
2020-10-29 11:10:30 +01:00
|
|
|
else gi[i] = get_GSUB_vert_glyph( physdev->font, glyph );
|
2020-10-22 13:13:52 +02:00
|
|
|
}
|
|
|
|
|
2020-10-22 11:54:35 +02:00
|
|
|
LeaveCriticalSection( &font_cs );
|
2020-10-22 13:13:52 +02:00
|
|
|
return count;
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************
|
|
|
|
* font_GetGlyphOutline
|
|
|
|
*/
|
|
|
|
static DWORD CDECL font_GetGlyphOutline( PHYSDEV dev, UINT glyph, UINT format,
|
|
|
|
GLYPHMETRICS *gm, DWORD buflen, void *buf, const MAT2 *mat )
|
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
2020-10-22 11:54:35 +02:00
|
|
|
DWORD ret;
|
2020-10-20 22:05:37 +02:00
|
|
|
|
|
|
|
if (!physdev->font)
|
|
|
|
{
|
|
|
|
dev = GET_NEXT_PHYSDEV( dev, pGetGlyphOutline );
|
|
|
|
return dev->funcs->pGetGlyphOutline( dev, glyph, format, gm, buflen, buf, mat );
|
|
|
|
}
|
2020-10-22 11:54:35 +02:00
|
|
|
EnterCriticalSection( &font_cs );
|
2020-10-29 14:47:18 +01:00
|
|
|
ret = get_glyph_outline( physdev->font, glyph, format, gm, NULL, buflen, buf, mat );
|
2020-10-22 11:54:35 +02:00
|
|
|
LeaveCriticalSection( &font_cs );
|
|
|
|
return ret;
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************
|
|
|
|
* font_GetKerningPairs
|
|
|
|
*/
|
|
|
|
static DWORD CDECL font_GetKerningPairs( PHYSDEV dev, DWORD count, KERNINGPAIR *pairs )
|
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
|
|
|
|
|
|
|
if (!physdev->font)
|
|
|
|
{
|
|
|
|
dev = GET_NEXT_PHYSDEV( dev, pGetKerningPairs );
|
|
|
|
return dev->funcs->pGetKerningPairs( dev, count, pairs );
|
|
|
|
}
|
2020-10-26 11:50:07 +01:00
|
|
|
|
2020-10-22 11:54:35 +02:00
|
|
|
EnterCriticalSection( &font_cs );
|
2020-10-26 11:50:07 +01:00
|
|
|
if (physdev->font->kern_count == -1)
|
|
|
|
physdev->font->kern_count = font_funcs->get_kerning_pairs( physdev->font,
|
|
|
|
&physdev->font->kern_pairs );
|
2020-10-22 11:54:35 +02:00
|
|
|
LeaveCriticalSection( &font_cs );
|
2020-10-26 11:50:07 +01:00
|
|
|
|
|
|
|
if (count && pairs)
|
|
|
|
{
|
|
|
|
count = min( count, physdev->font->kern_count );
|
|
|
|
memcpy( pairs, physdev->font->kern_pairs, count * sizeof(*pairs) );
|
|
|
|
}
|
|
|
|
else count = physdev->font->kern_count;
|
|
|
|
|
|
|
|
return count;
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-26 11:43:24 +01:00
|
|
|
static void scale_outline_font_metrics( const struct gdi_font *font, OUTLINETEXTMETRICW *otm )
|
|
|
|
{
|
|
|
|
double scale_x, scale_y;
|
|
|
|
|
|
|
|
if (font->aveWidth)
|
|
|
|
{
|
|
|
|
scale_x = (double)font->aveWidth;
|
|
|
|
scale_x /= (double)font->otm.otmTextMetrics.tmAveCharWidth;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
scale_x = font->scale_y;
|
|
|
|
|
|
|
|
scale_x *= fabs(font->matrix.eM11);
|
|
|
|
scale_y = font->scale_y * fabs(font->matrix.eM22);
|
|
|
|
|
|
|
|
/* Windows scales these values as signed integers even if they are unsigned */
|
|
|
|
#define SCALE_X(x) (x) = GDI_ROUND((int)(x) * (scale_x))
|
|
|
|
#define SCALE_Y(y) (y) = GDI_ROUND((int)(y) * (scale_y))
|
|
|
|
|
|
|
|
SCALE_Y(otm->otmTextMetrics.tmHeight);
|
|
|
|
SCALE_Y(otm->otmTextMetrics.tmAscent);
|
|
|
|
SCALE_Y(otm->otmTextMetrics.tmDescent);
|
|
|
|
SCALE_Y(otm->otmTextMetrics.tmInternalLeading);
|
|
|
|
SCALE_Y(otm->otmTextMetrics.tmExternalLeading);
|
|
|
|
|
|
|
|
SCALE_X(otm->otmTextMetrics.tmOverhang);
|
|
|
|
if (font->fake_bold)
|
|
|
|
{
|
|
|
|
if (!font->scalable) otm->otmTextMetrics.tmOverhang++;
|
|
|
|
otm->otmTextMetrics.tmAveCharWidth++;
|
|
|
|
otm->otmTextMetrics.tmMaxCharWidth++;
|
|
|
|
}
|
|
|
|
SCALE_X(otm->otmTextMetrics.tmAveCharWidth);
|
|
|
|
SCALE_X(otm->otmTextMetrics.tmMaxCharWidth);
|
|
|
|
|
|
|
|
SCALE_Y(otm->otmAscent);
|
|
|
|
SCALE_Y(otm->otmDescent);
|
|
|
|
SCALE_Y(otm->otmLineGap);
|
|
|
|
SCALE_Y(otm->otmsCapEmHeight);
|
|
|
|
SCALE_Y(otm->otmsXHeight);
|
|
|
|
SCALE_Y(otm->otmrcFontBox.top);
|
|
|
|
SCALE_Y(otm->otmrcFontBox.bottom);
|
|
|
|
SCALE_X(otm->otmrcFontBox.left);
|
|
|
|
SCALE_X(otm->otmrcFontBox.right);
|
|
|
|
SCALE_Y(otm->otmMacAscent);
|
|
|
|
SCALE_Y(otm->otmMacDescent);
|
|
|
|
SCALE_Y(otm->otmMacLineGap);
|
|
|
|
SCALE_X(otm->otmptSubscriptSize.x);
|
|
|
|
SCALE_Y(otm->otmptSubscriptSize.y);
|
|
|
|
SCALE_X(otm->otmptSubscriptOffset.x);
|
|
|
|
SCALE_Y(otm->otmptSubscriptOffset.y);
|
|
|
|
SCALE_X(otm->otmptSuperscriptSize.x);
|
|
|
|
SCALE_Y(otm->otmptSuperscriptSize.y);
|
|
|
|
SCALE_X(otm->otmptSuperscriptOffset.x);
|
|
|
|
SCALE_Y(otm->otmptSuperscriptOffset.y);
|
|
|
|
SCALE_Y(otm->otmsStrikeoutSize);
|
|
|
|
SCALE_Y(otm->otmsStrikeoutPosition);
|
|
|
|
SCALE_Y(otm->otmsUnderscoreSize);
|
|
|
|
SCALE_Y(otm->otmsUnderscorePosition);
|
|
|
|
|
|
|
|
#undef SCALE_X
|
|
|
|
#undef SCALE_Y
|
|
|
|
}
|
|
|
|
|
2020-10-20 22:05:37 +02:00
|
|
|
/*************************************************************
|
|
|
|
* font_GetOutlineTextMetrics
|
|
|
|
*/
|
|
|
|
static UINT CDECL font_GetOutlineTextMetrics( PHYSDEV dev, UINT size, OUTLINETEXTMETRICW *metrics )
|
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
2020-10-26 11:43:24 +01:00
|
|
|
UINT ret = 0;
|
2020-10-20 22:05:37 +02:00
|
|
|
|
|
|
|
if (!physdev->font)
|
|
|
|
{
|
|
|
|
dev = GET_NEXT_PHYSDEV( dev, pGetOutlineTextMetrics );
|
|
|
|
return dev->funcs->pGetOutlineTextMetrics( dev, size, metrics );
|
|
|
|
}
|
2020-10-22 11:54:35 +02:00
|
|
|
|
|
|
|
if (!physdev->font->scalable) return 0;
|
|
|
|
|
|
|
|
EnterCriticalSection( &font_cs );
|
2020-10-26 11:43:24 +01:00
|
|
|
if (font_funcs->set_outline_text_metrics( physdev->font ))
|
|
|
|
{
|
|
|
|
ret = physdev->font->otm.otmSize;
|
|
|
|
if (metrics && size >= physdev->font->otm.otmSize)
|
|
|
|
{
|
|
|
|
WCHAR *ptr = (WCHAR *)(metrics + 1);
|
|
|
|
*metrics = physdev->font->otm;
|
|
|
|
metrics->otmpFamilyName = (char *)ptr - (ULONG_PTR)metrics;
|
2020-11-05 10:44:16 +01:00
|
|
|
lstrcpyW( ptr, (WCHAR *)physdev->font->otm.otmpFamilyName );
|
|
|
|
ptr += lstrlenW(ptr) + 1;
|
2020-10-26 11:43:24 +01:00
|
|
|
metrics->otmpStyleName = (char *)ptr - (ULONG_PTR)metrics;
|
2020-11-05 10:44:16 +01:00
|
|
|
lstrcpyW( ptr, (WCHAR *)physdev->font->otm.otmpStyleName );
|
|
|
|
ptr += lstrlenW(ptr) + 1;
|
2020-10-26 11:43:24 +01:00
|
|
|
metrics->otmpFaceName = (char *)ptr - (ULONG_PTR)metrics;
|
2020-11-05 10:44:16 +01:00
|
|
|
lstrcpyW( ptr, (WCHAR *)physdev->font->otm.otmpFaceName );
|
|
|
|
ptr += lstrlenW(ptr) + 1;
|
2020-10-26 11:43:24 +01:00
|
|
|
metrics->otmpFullName = (char *)ptr - (ULONG_PTR)metrics;
|
2020-11-05 10:44:16 +01:00
|
|
|
lstrcpyW( ptr, (WCHAR *)physdev->font->otm.otmpFullName );
|
2020-10-26 11:43:24 +01:00
|
|
|
scale_outline_font_metrics( physdev->font, metrics );
|
|
|
|
}
|
|
|
|
}
|
2020-10-22 11:54:35 +02:00
|
|
|
LeaveCriticalSection( &font_cs );
|
|
|
|
return ret;
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************
|
|
|
|
* font_GetTextCharsetInfo
|
|
|
|
*/
|
|
|
|
static UINT CDECL font_GetTextCharsetInfo( PHYSDEV dev, FONTSIGNATURE *fs, DWORD flags )
|
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
|
|
|
|
|
|
|
if (!physdev->font)
|
|
|
|
{
|
|
|
|
dev = GET_NEXT_PHYSDEV( dev, pGetTextCharsetInfo );
|
|
|
|
return dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
|
|
|
|
}
|
2020-10-21 11:04:35 +02:00
|
|
|
if (fs) *fs = physdev->font->fs;
|
|
|
|
return physdev->font->charset;
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************
|
|
|
|
* font_GetTextExtentExPoint
|
|
|
|
*/
|
|
|
|
static BOOL CDECL font_GetTextExtentExPoint( PHYSDEV dev, const WCHAR *str, INT count, INT *dxs )
|
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
2020-10-22 11:56:47 +02:00
|
|
|
INT i, pos;
|
|
|
|
ABC abc;
|
2020-10-20 22:05:37 +02:00
|
|
|
|
|
|
|
if (!physdev->font)
|
|
|
|
{
|
|
|
|
dev = GET_NEXT_PHYSDEV( dev, pGetTextExtentExPoint );
|
|
|
|
return dev->funcs->pGetTextExtentExPoint( dev, str, count, dxs );
|
|
|
|
}
|
2020-10-22 11:56:47 +02:00
|
|
|
|
|
|
|
TRACE( "%p, %s, %d\n", physdev->font, debugstr_wn(str, count), count );
|
|
|
|
|
2020-10-22 11:54:35 +02:00
|
|
|
EnterCriticalSection( &font_cs );
|
2020-10-22 11:56:47 +02:00
|
|
|
for (i = pos = 0; i < count; i++)
|
|
|
|
{
|
2020-10-29 14:47:18 +01:00
|
|
|
get_glyph_outline( physdev->font, str[i], GGO_METRICS, NULL, &abc, 0, NULL, NULL );
|
2020-10-22 11:56:47 +02:00
|
|
|
pos += abc.abcA + abc.abcB + abc.abcC;
|
|
|
|
dxs[i] = pos;
|
|
|
|
}
|
2020-10-22 11:54:35 +02:00
|
|
|
LeaveCriticalSection( &font_cs );
|
2020-10-22 11:56:47 +02:00
|
|
|
return TRUE;
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************
|
|
|
|
* font_GetTextExtentExPointI
|
|
|
|
*/
|
|
|
|
static BOOL CDECL font_GetTextExtentExPointI( PHYSDEV dev, const WORD *indices, INT count, INT *dxs )
|
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
2020-10-22 11:56:47 +02:00
|
|
|
INT i, pos;
|
|
|
|
ABC abc;
|
2020-10-20 22:05:37 +02:00
|
|
|
|
|
|
|
if (!physdev->font)
|
|
|
|
{
|
|
|
|
dev = GET_NEXT_PHYSDEV( dev, pGetTextExtentExPointI );
|
|
|
|
return dev->funcs->pGetTextExtentExPointI( dev, indices, count, dxs );
|
|
|
|
}
|
2020-10-22 11:56:47 +02:00
|
|
|
|
|
|
|
TRACE( "%p, %p, %d\n", physdev->font, indices, count );
|
|
|
|
|
2020-10-22 11:54:35 +02:00
|
|
|
EnterCriticalSection( &font_cs );
|
2020-10-22 11:56:47 +02:00
|
|
|
for (i = pos = 0; i < count; i++)
|
|
|
|
{
|
2020-10-29 14:47:18 +01:00
|
|
|
get_glyph_outline( physdev->font, indices[i], GGO_METRICS | GGO_GLYPH_INDEX,
|
|
|
|
NULL, &abc, 0, NULL, NULL );
|
2020-10-22 11:56:47 +02:00
|
|
|
pos += abc.abcA + abc.abcB + abc.abcC;
|
|
|
|
dxs[i] = pos;
|
|
|
|
}
|
2020-10-22 11:54:35 +02:00
|
|
|
LeaveCriticalSection( &font_cs );
|
2020-10-22 11:56:47 +02:00
|
|
|
return TRUE;
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************
|
|
|
|
* font_GetTextFace
|
|
|
|
*/
|
|
|
|
static INT CDECL font_GetTextFace( PHYSDEV dev, INT count, WCHAR *str )
|
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
2020-10-21 11:03:51 +02:00
|
|
|
INT len;
|
2020-10-20 22:05:37 +02:00
|
|
|
|
|
|
|
if (!physdev->font)
|
|
|
|
{
|
|
|
|
dev = GET_NEXT_PHYSDEV( dev, pGetTextFace );
|
|
|
|
return dev->funcs->pGetTextFace( dev, count, str );
|
|
|
|
}
|
2020-11-05 10:44:16 +01:00
|
|
|
len = lstrlenW( get_gdi_font_name(physdev->font) ) + 1;
|
2020-10-21 11:03:51 +02:00
|
|
|
if (str)
|
|
|
|
{
|
2020-10-26 11:43:24 +01:00
|
|
|
lstrcpynW( str, get_gdi_font_name(physdev->font), count );
|
2020-10-21 11:03:51 +02:00
|
|
|
len = min( count, len );
|
|
|
|
}
|
|
|
|
return len;
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-26 11:43:24 +01:00
|
|
|
static void scale_font_metrics( struct gdi_font *font, TEXTMETRICW *tm )
|
|
|
|
{
|
|
|
|
double scale_x, scale_y;
|
|
|
|
|
|
|
|
/* Make sure that the font has sane width/height ratio */
|
|
|
|
if (font->aveWidth && (font->aveWidth + tm->tmHeight - 1) / tm->tmHeight > 100)
|
|
|
|
{
|
|
|
|
WARN( "Ignoring too large font->aveWidth %d\n", font->aveWidth );
|
|
|
|
font->aveWidth = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (font->aveWidth)
|
|
|
|
{
|
|
|
|
scale_x = (double)font->aveWidth;
|
|
|
|
scale_x /= (double)font->otm.otmTextMetrics.tmAveCharWidth;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
scale_x = font->scale_y;
|
|
|
|
|
|
|
|
scale_x *= fabs(font->matrix.eM11);
|
|
|
|
scale_y = font->scale_y * fabs(font->matrix.eM22);
|
|
|
|
|
|
|
|
#define SCALE_X(x) (x) = GDI_ROUND((x) * scale_x)
|
|
|
|
#define SCALE_Y(y) (y) = GDI_ROUND((y) * scale_y)
|
|
|
|
|
|
|
|
SCALE_Y(tm->tmHeight);
|
|
|
|
SCALE_Y(tm->tmAscent);
|
|
|
|
SCALE_Y(tm->tmDescent);
|
|
|
|
SCALE_Y(tm->tmInternalLeading);
|
|
|
|
SCALE_Y(tm->tmExternalLeading);
|
|
|
|
|
|
|
|
SCALE_X(tm->tmOverhang);
|
|
|
|
if (font->fake_bold)
|
|
|
|
{
|
|
|
|
if (!font->scalable) tm->tmOverhang++;
|
|
|
|
tm->tmAveCharWidth++;
|
|
|
|
tm->tmMaxCharWidth++;
|
|
|
|
}
|
|
|
|
SCALE_X(tm->tmAveCharWidth);
|
|
|
|
SCALE_X(tm->tmMaxCharWidth);
|
|
|
|
|
|
|
|
#undef SCALE_X
|
|
|
|
#undef SCALE_Y
|
|
|
|
}
|
|
|
|
|
2020-10-20 22:05:37 +02:00
|
|
|
/*************************************************************
|
|
|
|
* font_GetTextMetrics
|
|
|
|
*/
|
|
|
|
static BOOL CDECL font_GetTextMetrics( PHYSDEV dev, TEXTMETRICW *metrics )
|
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
2020-10-26 11:43:24 +01:00
|
|
|
BOOL ret = FALSE;
|
2020-10-20 22:05:37 +02:00
|
|
|
|
|
|
|
if (!physdev->font)
|
|
|
|
{
|
|
|
|
dev = GET_NEXT_PHYSDEV( dev, pGetTextMetrics );
|
|
|
|
return dev->funcs->pGetTextMetrics( dev, metrics );
|
|
|
|
}
|
2020-10-22 11:54:35 +02:00
|
|
|
|
|
|
|
EnterCriticalSection( &font_cs );
|
2020-10-26 11:43:24 +01:00
|
|
|
if (font_funcs->set_outline_text_metrics( physdev->font ) ||
|
|
|
|
font_funcs->set_bitmap_text_metrics( physdev->font ))
|
|
|
|
{
|
|
|
|
*metrics = physdev->font->otm.otmTextMetrics;
|
|
|
|
scale_font_metrics( physdev->font, metrics );
|
|
|
|
ret = TRUE;
|
|
|
|
}
|
2020-10-22 11:54:35 +02:00
|
|
|
LeaveCriticalSection( &font_cs );
|
|
|
|
return ret;
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-11-04 09:20:26 +01:00
|
|
|
static void get_nearest_charset( const WCHAR *family_name, struct gdi_font_face *face, CHARSETINFO *csi )
|
|
|
|
{
|
|
|
|
/* Only get here if lfCharSet == DEFAULT_CHARSET or we couldn't find
|
|
|
|
a single face with the requested charset. The idea is to check if
|
|
|
|
the selected font supports the current ANSI codepage, if it does
|
|
|
|
return the corresponding charset, else return the first charset */
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
2021-09-01 14:09:04 +02:00
|
|
|
if (translate_charset_info( (DWORD*)(INT_PTR)GetACP(), csi, TCI_SRCCODEPAGE ))
|
2020-11-04 09:20:26 +01:00
|
|
|
{
|
|
|
|
const struct gdi_font_link *font_link;
|
|
|
|
|
|
|
|
if (csi->fs.fsCsb[0] & face->fs.fsCsb[0]) return;
|
|
|
|
font_link = find_gdi_font_link(family_name);
|
|
|
|
if (font_link && (csi->fs.fsCsb[0] & font_link->fs.fsCsb[0])) return;
|
|
|
|
}
|
|
|
|
for (i = 0; i < 32; i++)
|
|
|
|
{
|
|
|
|
DWORD fs0 = 1u << i;
|
|
|
|
if (face->fs.fsCsb[0] & fs0)
|
|
|
|
{
|
2021-09-01 14:09:04 +02:00
|
|
|
if (translate_charset_info(&fs0, csi, TCI_SRCFONTSIG)) return;
|
2020-11-04 09:20:26 +01:00
|
|
|
FIXME("TCI failing on %x\n", fs0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FIXME("returning DEFAULT_CHARSET face->fs.fsCsb[0] = %08x file = %s\n",
|
|
|
|
face->fs.fsCsb[0], debugstr_w(face->file));
|
|
|
|
csi->ciACP = GetACP();
|
|
|
|
csi->ciCharset = DEFAULT_CHARSET;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct gdi_font *select_font( LOGFONTW *lf, FMAT2 dcmat, BOOL can_use_bitmap )
|
|
|
|
{
|
|
|
|
struct gdi_font *font;
|
|
|
|
struct gdi_font_face *face;
|
|
|
|
INT height;
|
|
|
|
CHARSETINFO csi;
|
|
|
|
const WCHAR *orig_name = NULL;
|
|
|
|
|
|
|
|
/* If lfFaceName is "Symbol" then Windows fixes up lfCharSet to
|
|
|
|
SYMBOL_CHARSET so that Symbol gets picked irrespective of the
|
|
|
|
original value lfCharSet. Note this is a special case for
|
|
|
|
Symbol and doesn't happen at least for "Wingdings*" */
|
2020-11-23 13:20:50 +01:00
|
|
|
if (!facename_compare( lf->lfFaceName, L"Symbol", -1 )) lf->lfCharSet = SYMBOL_CHARSET;
|
2020-11-04 09:20:26 +01:00
|
|
|
|
|
|
|
/* check the cache first */
|
|
|
|
if ((font = find_cached_gdi_font( lf, &dcmat, can_use_bitmap )))
|
|
|
|
{
|
|
|
|
TRACE( "returning cached gdiFont(%p)\n", font );
|
|
|
|
return font;
|
|
|
|
}
|
|
|
|
if (!(face = find_matching_face( lf, &csi, can_use_bitmap, &orig_name )))
|
|
|
|
{
|
|
|
|
FIXME( "can't find a single appropriate font - bailing\n" );
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
height = lf->lfHeight;
|
|
|
|
|
|
|
|
font = create_gdi_font( face, orig_name, lf );
|
|
|
|
font->matrix = dcmat;
|
|
|
|
font->can_use_bitmap = can_use_bitmap;
|
|
|
|
if (!csi.fs.fsCsb[0]) get_nearest_charset( face->family->family_name, face, &csi );
|
|
|
|
font->charset = csi.ciCharset;
|
|
|
|
font->codepage = csi.ciACP;
|
|
|
|
|
|
|
|
TRACE( "Chosen: %s (%s/%p:%u)\n", debugstr_w(face->full_name), debugstr_w(face->file),
|
|
|
|
face->data_ptr, face->face_index );
|
|
|
|
|
|
|
|
font->aveWidth = height ? lf->lfWidth : 0;
|
|
|
|
if (!face->scalable)
|
|
|
|
{
|
|
|
|
/* Windows uses integer scaling factors for bitmap fonts */
|
|
|
|
INT scale, scaled_height, diff;
|
|
|
|
struct gdi_font *cachedfont;
|
|
|
|
|
|
|
|
if (height > 0)
|
|
|
|
diff = height - (signed int)face->size.height;
|
|
|
|
else
|
|
|
|
diff = -height - ((signed int)face->size.height - face->size.internal_leading);
|
|
|
|
|
|
|
|
/* FIXME: rotation of bitmap fonts is ignored */
|
|
|
|
height = abs(GDI_ROUND( (double)height * font->matrix.eM22 ));
|
|
|
|
if (font->aveWidth)
|
|
|
|
font->aveWidth = (double)font->aveWidth * font->matrix.eM11;
|
|
|
|
font->matrix.eM11 = font->matrix.eM22 = 1.0;
|
|
|
|
dcmat.eM11 = dcmat.eM22 = 1.0;
|
|
|
|
/* As we changed the matrix, we need to search the cache for the font again,
|
|
|
|
* otherwise we might explode the cache. */
|
|
|
|
if ((cachedfont = find_cached_gdi_font( lf, &dcmat, can_use_bitmap )))
|
|
|
|
{
|
|
|
|
TRACE("Found cached font after non-scalable matrix rescale!\n");
|
|
|
|
free_gdi_font( font );
|
|
|
|
return cachedfont;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (height != 0) height = diff;
|
|
|
|
height += face->size.height;
|
|
|
|
|
|
|
|
scale = (height + face->size.height - 1) / face->size.height;
|
|
|
|
scaled_height = scale * face->size.height;
|
|
|
|
/* Only jump to the next height if the difference <= 25% original height */
|
|
|
|
if (scale > 2 && scaled_height - height > face->size.height / 4) scale--;
|
|
|
|
/* The jump between unscaled and doubled is delayed by 1 */
|
|
|
|
else if (scale == 2 && scaled_height - height > (face->size.height / 4 - 1)) scale--;
|
|
|
|
font->scale_y = scale;
|
2020-11-05 09:59:32 +01:00
|
|
|
TRACE("font scale y: %d\n", font->scale_y);
|
2020-11-04 09:20:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!font_funcs->load_font( font ))
|
|
|
|
{
|
|
|
|
free_gdi_font( font );
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (face->flags & ADDFONT_VERTICAL_FONT) /* We need to try to load the GSUB table */
|
|
|
|
font->vert_feature = get_GSUB_vert_feature( font );
|
|
|
|
|
|
|
|
create_child_font_list( font );
|
|
|
|
|
|
|
|
TRACE( "caching: gdiFont=%p\n", font );
|
|
|
|
cache_gdi_font( font );
|
|
|
|
return font;
|
|
|
|
}
|
|
|
|
|
2020-10-20 22:05:37 +02:00
|
|
|
/*************************************************************
|
|
|
|
* font_SelectFont
|
|
|
|
*/
|
|
|
|
static HFONT CDECL font_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags )
|
|
|
|
{
|
|
|
|
struct font_physdev *physdev = get_font_dev( dev );
|
2020-11-03 11:25:30 +01:00
|
|
|
struct gdi_font *font = NULL, *prev = physdev->font;
|
2020-10-20 22:05:37 +02:00
|
|
|
DC *dc = get_physdev_dc( dev );
|
|
|
|
|
2020-10-22 11:54:35 +02:00
|
|
|
if (hfont)
|
|
|
|
{
|
2020-11-03 11:25:30 +01:00
|
|
|
LOGFONTW lf;
|
2020-11-04 09:20:26 +01:00
|
|
|
FMAT2 dcmat;
|
2021-09-10 14:28:30 +02:00
|
|
|
BOOL can_use_bitmap = !!(NtGdiGetDeviceCaps( dc->hSelf, TEXTCAPS ) & TC_RA_ABLE);
|
2020-11-03 11:25:30 +01:00
|
|
|
|
2021-09-10 14:28:30 +02:00
|
|
|
NtGdiExtGetObjectW( hfont, sizeof(lf), &lf );
|
2020-11-03 11:25:30 +01:00
|
|
|
switch (lf.lfQuality)
|
|
|
|
{
|
|
|
|
case NONANTIALIASED_QUALITY:
|
|
|
|
if (!*aa_flags) *aa_flags = GGO_BITMAP;
|
|
|
|
break;
|
|
|
|
case ANTIALIASED_QUALITY:
|
|
|
|
if (!*aa_flags) *aa_flags = GGO_GRAY4_BITMAP;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:20:26 +01:00
|
|
|
lf.lfWidth = abs(lf.lfWidth);
|
|
|
|
|
|
|
|
TRACE( "%s, h=%d, it=%d, weight=%d, PandF=%02x, charset=%d orient %d escapement %d\n",
|
|
|
|
debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic,
|
|
|
|
lf.lfWeight, lf.lfPitchAndFamily, lf.lfCharSet, lf.lfOrientation,
|
|
|
|
lf.lfEscapement );
|
|
|
|
|
2021-07-20 09:19:14 +02:00
|
|
|
if (dc->attr->graphics_mode == GM_ADVANCED)
|
2020-11-04 09:20:26 +01:00
|
|
|
{
|
|
|
|
memcpy( &dcmat, &dc->xformWorld2Vport, sizeof(FMAT2) );
|
|
|
|
/* try to avoid not necessary glyph transformations */
|
|
|
|
if (dcmat.eM21 == 0.0 && dcmat.eM12 == 0.0 && dcmat.eM11 == dcmat.eM22)
|
|
|
|
{
|
|
|
|
lf.lfHeight *= fabs(dcmat.eM11);
|
|
|
|
lf.lfWidth *= fabs(dcmat.eM11);
|
|
|
|
dcmat.eM11 = dcmat.eM22 = dcmat.eM11 < 0 ? -1 : 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Windows 3.1 compatibility mode GM_COMPATIBLE has only limited font scaling abilities */
|
|
|
|
dcmat.eM11 = dcmat.eM22 = 1.0;
|
|
|
|
dcmat.eM21 = dcmat.eM12 = 0;
|
|
|
|
lf.lfOrientation = lf.lfEscapement;
|
|
|
|
if (dc->vport2WorldValid)
|
|
|
|
{
|
|
|
|
if (dc->xformWorld2Vport.eM11 * dc->xformWorld2Vport.eM22 < 0)
|
|
|
|
lf.lfOrientation = -lf.lfOrientation;
|
|
|
|
lf.lfHeight *= fabs(dc->xformWorld2Vport.eM22);
|
|
|
|
lf.lfWidth *= fabs(dc->xformWorld2Vport.eM22);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TRACE( "DC transform %f %f %f %f\n", dcmat.eM11, dcmat.eM12, dcmat.eM21, dcmat.eM22 );
|
|
|
|
|
2020-10-22 11:54:35 +02:00
|
|
|
EnterCriticalSection( &font_cs );
|
2020-11-03 11:25:30 +01:00
|
|
|
|
2020-11-04 09:20:26 +01:00
|
|
|
font = select_font( &lf, dcmat, can_use_bitmap );
|
|
|
|
|
2020-12-07 12:46:28 +01:00
|
|
|
if (font)
|
2020-11-03 11:25:30 +01:00
|
|
|
{
|
2020-12-07 12:46:28 +01:00
|
|
|
if (!*aa_flags) *aa_flags = font->aa_flags;
|
2020-11-03 11:25:30 +01:00
|
|
|
if (!*aa_flags)
|
|
|
|
{
|
|
|
|
if (lf.lfQuality == CLEARTYPE_QUALITY || lf.lfQuality == CLEARTYPE_NATURAL_QUALITY)
|
|
|
|
*aa_flags = subpixel_orientation;
|
|
|
|
else
|
|
|
|
*aa_flags = font_smoothing;
|
|
|
|
}
|
|
|
|
*aa_flags = font_funcs->get_aa_flags( font, *aa_flags, antialias_fakes );
|
|
|
|
}
|
|
|
|
TRACE( "%p %s %d aa %x\n", hfont, debugstr_w(lf.lfFaceName), lf.lfHeight, *aa_flags );
|
2020-10-22 11:54:35 +02:00
|
|
|
LeaveCriticalSection( &font_cs );
|
|
|
|
}
|
2020-11-03 11:25:30 +01:00
|
|
|
physdev->font = font;
|
2020-10-21 11:01:50 +02:00
|
|
|
if (prev) release_gdi_font( prev );
|
2020-11-03 11:25:30 +01:00
|
|
|
return font ? hfont : 0;
|
2020-10-20 22:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const struct gdi_dc_funcs font_driver =
|
|
|
|
{
|
|
|
|
NULL, /* pAbortDoc */
|
|
|
|
NULL, /* pAbortPath */
|
|
|
|
NULL, /* pAlphaBlend */
|
|
|
|
NULL, /* pAngleArc */
|
|
|
|
NULL, /* pArc */
|
|
|
|
NULL, /* pArcTo */
|
|
|
|
NULL, /* pBeginPath */
|
|
|
|
NULL, /* pBlendImage */
|
|
|
|
NULL, /* pChord */
|
|
|
|
NULL, /* pCloseFigure */
|
|
|
|
NULL, /* pCreateCompatibleDC */
|
|
|
|
font_CreateDC, /* pCreateDC */
|
|
|
|
font_DeleteDC, /* pDeleteDC */
|
|
|
|
NULL, /* pDeleteObject */
|
|
|
|
NULL, /* pEllipse */
|
|
|
|
NULL, /* pEndDoc */
|
|
|
|
NULL, /* pEndPage */
|
|
|
|
NULL, /* pEndPath */
|
|
|
|
font_EnumFonts, /* pEnumFonts */
|
|
|
|
NULL, /* pExtEscape */
|
|
|
|
NULL, /* pExtFloodFill */
|
|
|
|
NULL, /* pExtTextOut */
|
|
|
|
NULL, /* pFillPath */
|
|
|
|
NULL, /* pFillRgn */
|
|
|
|
font_FontIsLinked, /* pFontIsLinked */
|
|
|
|
NULL, /* pFrameRgn */
|
|
|
|
NULL, /* pGetBoundsRect */
|
|
|
|
font_GetCharABCWidths, /* pGetCharABCWidths */
|
|
|
|
font_GetCharABCWidthsI, /* pGetCharABCWidthsI */
|
|
|
|
font_GetCharWidth, /* pGetCharWidth */
|
|
|
|
font_GetCharWidthInfo, /* pGetCharWidthInfo */
|
|
|
|
NULL, /* pGetDeviceCaps */
|
|
|
|
NULL, /* pGetDeviceGammaRamp */
|
|
|
|
font_GetFontData, /* pGetFontData */
|
|
|
|
font_GetFontRealizationInfo, /* pGetFontRealizationInfo */
|
|
|
|
font_GetFontUnicodeRanges, /* pGetFontUnicodeRanges */
|
|
|
|
font_GetGlyphIndices, /* pGetGlyphIndices */
|
|
|
|
font_GetGlyphOutline, /* pGetGlyphOutline */
|
|
|
|
NULL, /* pGetICMProfile */
|
|
|
|
NULL, /* pGetImage */
|
|
|
|
font_GetKerningPairs, /* pGetKerningPairs */
|
|
|
|
NULL, /* pGetNearestColor */
|
|
|
|
font_GetOutlineTextMetrics, /* pGetOutlineTextMetrics */
|
|
|
|
NULL, /* pGetPixel */
|
|
|
|
NULL, /* pGetSystemPaletteEntries */
|
|
|
|
font_GetTextCharsetInfo, /* pGetTextCharsetInfo */
|
|
|
|
font_GetTextExtentExPoint, /* pGetTextExtentExPoint */
|
|
|
|
font_GetTextExtentExPointI, /* pGetTextExtentExPointI */
|
|
|
|
font_GetTextFace, /* pGetTextFace */
|
|
|
|
font_GetTextMetrics, /* pGetTextMetrics */
|
|
|
|
NULL, /* pGradientFill */
|
|
|
|
NULL, /* pInvertRgn */
|
|
|
|
NULL, /* pLineTo */
|
|
|
|
NULL, /* pMoveTo */
|
|
|
|
NULL, /* pPaintRgn */
|
|
|
|
NULL, /* pPatBlt */
|
|
|
|
NULL, /* pPie */
|
|
|
|
NULL, /* pPolyBezier */
|
|
|
|
NULL, /* pPolyBezierTo */
|
|
|
|
NULL, /* pPolyDraw */
|
|
|
|
NULL, /* pPolyPolygon */
|
|
|
|
NULL, /* pPolyPolyline */
|
|
|
|
NULL, /* pPolylineTo */
|
|
|
|
NULL, /* pPutImage */
|
|
|
|
NULL, /* pRealizeDefaultPalette */
|
|
|
|
NULL, /* pRealizePalette */
|
|
|
|
NULL, /* pRectangle */
|
|
|
|
NULL, /* pResetDC */
|
|
|
|
NULL, /* pRoundRect */
|
|
|
|
NULL, /* pSelectBitmap */
|
|
|
|
NULL, /* pSelectBrush */
|
|
|
|
font_SelectFont, /* pSelectFont */
|
|
|
|
NULL, /* pSelectPen */
|
|
|
|
NULL, /* pSetBkColor */
|
|
|
|
NULL, /* pSetBoundsRect */
|
|
|
|
NULL, /* pSetDCBrushColor */
|
|
|
|
NULL, /* pSetDCPenColor */
|
|
|
|
NULL, /* pSetDIBitsToDevice */
|
|
|
|
NULL, /* pSetDeviceClipping */
|
|
|
|
NULL, /* pSetDeviceGammaRamp */
|
|
|
|
NULL, /* pSetPixel */
|
|
|
|
NULL, /* pSetTextColor */
|
|
|
|
NULL, /* pStartDoc */
|
|
|
|
NULL, /* pStartPage */
|
|
|
|
NULL, /* pStretchBlt */
|
|
|
|
NULL, /* pStretchDIBits */
|
|
|
|
NULL, /* pStrokeAndFillPath */
|
|
|
|
NULL, /* pStrokePath */
|
|
|
|
NULL, /* pUnrealizePalette */
|
|
|
|
NULL, /* pD3DKMTCheckVidPnExclusiveOwnership */
|
|
|
|
NULL, /* pD3DKMTSetVidPnSourceOwner */
|
|
|
|
NULL, /* wine_get_wgl_driver */
|
|
|
|
NULL, /* wine_get_vulkan_driver */
|
|
|
|
GDI_PRIORITY_FONT_DRV /* priority */
|
|
|
|
};
|
|
|
|
|
2020-11-03 11:25:30 +01:00
|
|
|
static DWORD get_key_value( HKEY key, const WCHAR *name, DWORD *value )
|
|
|
|
{
|
|
|
|
WCHAR buf[12];
|
|
|
|
DWORD count = sizeof(buf), type, err;
|
|
|
|
|
|
|
|
err = RegQueryValueExW( key, name, NULL, &type, (BYTE *)buf, &count );
|
|
|
|
if (!err)
|
|
|
|
{
|
|
|
|
if (type == REG_DWORD) memcpy( value, buf, sizeof(*value) );
|
2020-11-05 10:44:16 +01:00
|
|
|
else *value = wcstol( buf, NULL, 10 );
|
2020-11-03 11:25:30 +01:00
|
|
|
}
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void init_font_options(void)
|
|
|
|
{
|
|
|
|
HKEY key;
|
2020-11-06 12:10:54 +01:00
|
|
|
DWORD i, type, size, val, gamma = 1400;
|
2020-11-03 11:25:30 +01:00
|
|
|
WCHAR buffer[20];
|
|
|
|
|
|
|
|
size = sizeof(buffer);
|
2020-11-06 12:08:16 +01:00
|
|
|
if (!RegQueryValueExW( wine_fonts_key, L"AntialiasFakeBoldOrItalic", NULL,
|
2020-11-03 11:25:30 +01:00
|
|
|
&type, (BYTE *)buffer, &size) && type == REG_SZ && size >= 1)
|
|
|
|
{
|
2020-11-06 12:08:16 +01:00
|
|
|
antialias_fakes = (wcschr(L"yYtT1", buffer[0]) != NULL);
|
2020-11-03 11:25:30 +01:00
|
|
|
}
|
|
|
|
|
2020-11-06 12:08:16 +01:00
|
|
|
if (!RegOpenKeyW( HKEY_CURRENT_USER, L"Control Panel\\Desktop", &key ))
|
2020-11-03 11:25:30 +01:00
|
|
|
{
|
|
|
|
/* FIXME: handle vertical orientations even though Windows doesn't */
|
2020-11-06 12:08:16 +01:00
|
|
|
if (!get_key_value( key, L"FontSmoothingOrientation", &val ))
|
2020-11-03 11:25:30 +01:00
|
|
|
{
|
|
|
|
switch (val)
|
|
|
|
{
|
|
|
|
case 0: /* FE_FONTSMOOTHINGORIENTATIONBGR */
|
|
|
|
subpixel_orientation = WINE_GGO_HBGR_BITMAP;
|
|
|
|
break;
|
|
|
|
case 1: /* FE_FONTSMOOTHINGORIENTATIONRGB */
|
|
|
|
subpixel_orientation = WINE_GGO_HRGB_BITMAP;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-11-06 12:08:16 +01:00
|
|
|
if (!get_key_value( key, L"FontSmoothing", &val ) && val /* enabled */)
|
2020-11-03 11:25:30 +01:00
|
|
|
{
|
2020-11-06 12:08:16 +01:00
|
|
|
if (!get_key_value( key, L"FontSmoothingType", &val ) && val == 2 /* FE_FONTSMOOTHINGCLEARTYPE */)
|
2020-11-03 11:25:30 +01:00
|
|
|
font_smoothing = subpixel_orientation;
|
|
|
|
else
|
|
|
|
font_smoothing = GGO_GRAY4_BITMAP;
|
|
|
|
}
|
2020-11-06 12:10:54 +01:00
|
|
|
if (!get_key_value( key, L"FontSmoothingGamma", &val ) && val)
|
|
|
|
{
|
|
|
|
gamma = min( max( val, 1000 ), 2200 );
|
|
|
|
}
|
2020-11-03 11:25:30 +01:00
|
|
|
RegCloseKey( key );
|
|
|
|
}
|
2020-11-06 12:10:54 +01:00
|
|
|
|
|
|
|
/* Calibrating the difference between the registry value and the Wine gamma value.
|
|
|
|
This looks roughly similar to Windows Native with the same registry value.
|
|
|
|
MS GDI seems to be rasterizing the outline at a different rate than FreeType. */
|
|
|
|
gamma = 1000 * gamma / 1400;
|
2021-05-03 09:48:00 +02:00
|
|
|
if (gamma != 1000)
|
2020-11-06 12:10:54 +01:00
|
|
|
{
|
2021-05-03 09:48:00 +02:00
|
|
|
for (i = 0; i < 256; i++)
|
|
|
|
{
|
|
|
|
font_gamma_ramp.encode[i] = pow( i / 255., 1000. / gamma ) * 255. + .5;
|
|
|
|
font_gamma_ramp.decode[i] = pow( i / 255., gamma / 1000. ) * 255. + .5;
|
|
|
|
}
|
2020-11-06 12:10:54 +01:00
|
|
|
}
|
|
|
|
font_gamma_ramp.gamma = gamma;
|
|
|
|
TRACE("gamma %d\n", font_gamma_ramp.gamma);
|
2020-11-03 11:25:30 +01:00
|
|
|
}
|
|
|
|
|
2020-09-30 16:08:21 +02:00
|
|
|
|
2012-12-18 17:41:42 +01:00
|
|
|
/* compute positions for text rendering, in device coords */
|
|
|
|
static BOOL get_char_positions( DC *dc, const WCHAR *str, INT count, INT *dx, SIZE *size )
|
|
|
|
{
|
|
|
|
TEXTMETRICW tm;
|
2012-12-27 20:53:25 +01:00
|
|
|
PHYSDEV dev;
|
2012-12-18 17:41:42 +01:00
|
|
|
|
|
|
|
size->cx = size->cy = 0;
|
|
|
|
if (!count) return TRUE;
|
|
|
|
|
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
|
|
|
|
dev->funcs->pGetTextMetrics( dev, &tm );
|
|
|
|
|
2012-12-27 20:53:25 +01:00
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
|
2012-12-18 17:52:37 +01:00
|
|
|
if (!dev->funcs->pGetTextExtentExPoint( dev, str, count, dx )) return FALSE;
|
2012-12-18 17:41:42 +01:00
|
|
|
|
|
|
|
if (dc->breakExtra || dc->breakRem)
|
|
|
|
{
|
|
|
|
int i, space = 0, rem = dc->breakRem;
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
if (str[i] == tm.tmBreakChar)
|
|
|
|
{
|
|
|
|
space += dc->breakExtra;
|
|
|
|
if (rem > 0)
|
|
|
|
{
|
|
|
|
space++;
|
|
|
|
rem--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dx[i] += space;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
size->cx = dx[count - 1];
|
|
|
|
size->cy = tm.tmHeight;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* compute positions for text rendering, in device coords */
|
|
|
|
static BOOL get_char_positions_indices( DC *dc, const WORD *indices, INT count, INT *dx, SIZE *size )
|
|
|
|
{
|
|
|
|
TEXTMETRICW tm;
|
2012-12-27 20:53:25 +01:00
|
|
|
PHYSDEV dev;
|
2012-12-18 17:41:42 +01:00
|
|
|
|
|
|
|
size->cx = size->cy = 0;
|
|
|
|
if (!count) return TRUE;
|
|
|
|
|
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
|
|
|
|
dev->funcs->pGetTextMetrics( dev, &tm );
|
|
|
|
|
2013-01-22 12:13:19 +01:00
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPointI );
|
2012-12-18 17:52:37 +01:00
|
|
|
if (!dev->funcs->pGetTextExtentExPointI( dev, indices, count, dx )) return FALSE;
|
2012-12-18 17:41:42 +01:00
|
|
|
|
|
|
|
if (dc->breakExtra || dc->breakRem)
|
|
|
|
{
|
|
|
|
WORD space_index;
|
|
|
|
int i, space = 0, rem = dc->breakRem;
|
|
|
|
|
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
|
|
|
|
dev->funcs->pGetGlyphIndices( dev, &tm.tmBreakChar, 1, &space_index, 0 );
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
if (indices[i] == space_index)
|
|
|
|
{
|
|
|
|
space += dc->breakExtra;
|
|
|
|
if (rem > 0)
|
|
|
|
{
|
|
|
|
space++;
|
|
|
|
rem--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dx[i] += space;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
size->cx = dx[count - 1];
|
|
|
|
size->cy = tm.tmHeight;
|
|
|
|
return TRUE;
|
|
|
|
}
|
2012-11-05 12:32:15 +01:00
|
|
|
|
2016-07-29 14:13:06 +02:00
|
|
|
/***********************************************************************
|
|
|
|
* get_text_charset_info
|
|
|
|
*
|
|
|
|
* Internal version of GetTextCharsetInfo() that takes a DC pointer.
|
|
|
|
*/
|
|
|
|
static UINT get_text_charset_info(DC *dc, FONTSIGNATURE *fs, DWORD flags)
|
|
|
|
{
|
|
|
|
UINT ret = DEFAULT_CHARSET;
|
|
|
|
PHYSDEV dev;
|
|
|
|
|
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetTextCharsetInfo );
|
|
|
|
ret = dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
|
|
|
|
|
|
|
|
if (ret == DEFAULT_CHARSET && fs)
|
|
|
|
memset(fs, 0, sizeof(FONTSIGNATURE));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
2021-08-10 08:37:47 +02:00
|
|
|
* NtGdiGetTextCharsetInfo (win32u.@)
|
2016-07-29 14:13:06 +02:00
|
|
|
*/
|
2021-08-10 08:37:47 +02:00
|
|
|
UINT WINAPI NtGdiGetTextCharsetInfo( HDC hdc, FONTSIGNATURE *fs, DWORD flags )
|
2016-07-29 14:13:06 +02:00
|
|
|
{
|
|
|
|
UINT ret = DEFAULT_CHARSET;
|
|
|
|
DC *dc = get_dc_ptr(hdc);
|
|
|
|
|
|
|
|
if (dc)
|
|
|
|
{
|
|
|
|
ret = get_text_charset_info( dc, fs, flags );
|
|
|
|
release_dc_ptr( dc );
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2001-02-14 23:56:38 +01:00
|
|
|
/***********************************************************************
|
2021-08-20 10:42:44 +02:00
|
|
|
* NtGdiHfontCreate (win32u.@)
|
2001-02-14 23:56:38 +01:00
|
|
|
*/
|
2021-08-20 10:42:44 +02:00
|
|
|
HFONT WINAPI NtGdiHfontCreate( const ENUMLOGFONTEXDVW *penumex, ULONG size, ULONG type,
|
|
|
|
ULONG flags, void *data )
|
1993-09-04 12:09:32 +02:00
|
|
|
{
|
2008-01-04 08:47:03 +01:00
|
|
|
HFONT hFont;
|
|
|
|
FONTOBJ *fontPtr;
|
2010-06-11 17:39:40 +02:00
|
|
|
const LOGFONTW *plf;
|
2008-01-04 08:47:03 +01:00
|
|
|
|
2010-06-11 17:39:40 +02:00
|
|
|
if (!penumex) return 0;
|
|
|
|
|
|
|
|
if (penumex->elfEnumLogfontEx.elfFullName[0] ||
|
|
|
|
penumex->elfEnumLogfontEx.elfStyle[0] ||
|
|
|
|
penumex->elfEnumLogfontEx.elfScript[0])
|
|
|
|
{
|
|
|
|
FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
|
|
|
|
debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
|
|
|
|
debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
|
|
|
|
debugstr_w(penumex->elfEnumLogfontEx.elfScript));
|
|
|
|
}
|
2008-01-04 08:47:03 +01:00
|
|
|
|
2010-06-11 17:39:40 +02:00
|
|
|
plf = &penumex->elfEnumLogfontEx.elfLogFont;
|
2009-01-28 18:43:06 +01:00
|
|
|
if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
|
2008-01-04 08:47:03 +01:00
|
|
|
|
2008-02-27 18:00:06 +01:00
|
|
|
fontPtr->logfont = *plf;
|
2008-01-04 08:47:03 +01:00
|
|
|
|
2021-07-08 17:11:45 +02:00
|
|
|
if (!(hFont = alloc_gdi_handle( &fontPtr->obj, NTGDI_OBJ_FONT, &fontobj_funcs )))
|
2009-01-28 18:43:06 +01:00
|
|
|
{
|
|
|
|
HeapFree( GetProcessHeap(), 0, fontPtr );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
|
|
|
|
plf->lfHeight, plf->lfWidth,
|
|
|
|
plf->lfEscapement, plf->lfOrientation,
|
|
|
|
plf->lfPitchAndFamily,
|
|
|
|
plf->lfOutPrecision, plf->lfClipPrecision,
|
|
|
|
plf->lfQuality, plf->lfCharSet,
|
|
|
|
debugstr_w(plf->lfFaceName),
|
|
|
|
plf->lfWeight > 400 ? "Bold" : "",
|
|
|
|
plf->lfItalic ? "Italic" : "",
|
|
|
|
plf->lfUnderline ? "Underline" : "", hFont);
|
|
|
|
|
1997-06-16 19:43:53 +02:00
|
|
|
return hFont;
|
|
|
|
}
|
1993-09-04 12:09:32 +02:00
|
|
|
|
2013-02-26 02:31:20 +01:00
|
|
|
#define ASSOC_CHARSET_OEM 1
|
|
|
|
#define ASSOC_CHARSET_ANSI 2
|
|
|
|
#define ASSOC_CHARSET_SYMBOL 4
|
|
|
|
|
|
|
|
static DWORD get_associated_charset_info(void)
|
|
|
|
{
|
|
|
|
static DWORD associated_charset = -1;
|
|
|
|
|
|
|
|
if (associated_charset == -1)
|
|
|
|
{
|
|
|
|
HKEY hkey;
|
|
|
|
WCHAR dataW[32];
|
|
|
|
DWORD type, data_len;
|
|
|
|
|
|
|
|
associated_charset = 0;
|
|
|
|
|
|
|
|
if (RegOpenKeyW(HKEY_LOCAL_MACHINE,
|
2020-11-06 12:08:16 +01:00
|
|
|
L"System\\CurrentControlSet\\Control\\FontAssoc\\Associated Charset", &hkey))
|
2013-02-26 02:31:20 +01:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
data_len = sizeof(dataW);
|
2020-11-06 12:08:16 +01:00
|
|
|
if (!RegQueryValueExW(hkey, L"ANSI(00)", NULL, &type, (LPBYTE)dataW, &data_len) &&
|
|
|
|
type == REG_SZ && !wcsicmp(dataW, L"yes"))
|
2013-02-26 02:31:20 +01:00
|
|
|
associated_charset |= ASSOC_CHARSET_ANSI;
|
|
|
|
|
|
|
|
data_len = sizeof(dataW);
|
2020-11-06 12:08:16 +01:00
|
|
|
if (!RegQueryValueExW(hkey, L"OEM(FF)", NULL, &type, (LPBYTE)dataW, &data_len) &&
|
|
|
|
type == REG_SZ && !wcsicmp(dataW, L"yes"))
|
2013-02-26 02:31:20 +01:00
|
|
|
associated_charset |= ASSOC_CHARSET_OEM;
|
|
|
|
|
|
|
|
data_len = sizeof(dataW);
|
2020-11-06 12:08:16 +01:00
|
|
|
if (!RegQueryValueExW(hkey, L"SYMBOL(02)", NULL, &type, (LPBYTE)dataW, &data_len) &&
|
|
|
|
type == REG_SZ && !wcsicmp(dataW, L"yes"))
|
2013-02-26 02:31:20 +01:00
|
|
|
associated_charset |= ASSOC_CHARSET_SYMBOL;
|
|
|
|
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
|
|
|
|
TRACE("associated_charset = %d\n", associated_charset);
|
|
|
|
}
|
|
|
|
|
|
|
|
return associated_charset;
|
|
|
|
}
|
|
|
|
|
2014-06-10 10:48:38 +02:00
|
|
|
static void update_font_code_page( DC *dc, HANDLE font )
|
2009-04-06 10:16:40 +02:00
|
|
|
{
|
|
|
|
CHARSETINFO csi;
|
2016-07-29 14:13:06 +02:00
|
|
|
int charset = get_text_charset_info( dc, NULL, 0 );
|
2009-04-06 10:16:40 +02:00
|
|
|
|
2016-07-29 14:13:07 +02:00
|
|
|
if (charset == ANSI_CHARSET && get_associated_charset_info() & ASSOC_CHARSET_ANSI)
|
|
|
|
{
|
|
|
|
LOGFONTW lf;
|
2014-06-10 10:48:38 +02:00
|
|
|
|
2021-09-10 14:28:30 +02:00
|
|
|
NtGdiExtGetObjectW( font, sizeof(lf), &lf );
|
2016-07-29 14:13:07 +02:00
|
|
|
if (!(lf.lfClipPrecision & CLIP_DFA_DISABLE))
|
|
|
|
charset = DEFAULT_CHARSET;
|
|
|
|
}
|
2013-02-26 02:31:20 +01:00
|
|
|
|
2009-04-06 10:16:40 +02:00
|
|
|
/* Hmm, nicely designed api this one! */
|
2021-09-01 14:09:04 +02:00
|
|
|
if (translate_charset_info( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
|
2021-08-20 10:42:24 +02:00
|
|
|
dc->attr->font_code_page = csi.ciACP;
|
2009-04-06 10:16:40 +02:00
|
|
|
else {
|
|
|
|
switch(charset) {
|
|
|
|
case OEM_CHARSET:
|
2021-08-20 10:42:24 +02:00
|
|
|
dc->attr->font_code_page = GetOEMCP();
|
2009-04-06 10:16:40 +02:00
|
|
|
break;
|
|
|
|
case DEFAULT_CHARSET:
|
2021-08-20 10:42:24 +02:00
|
|
|
dc->attr->font_code_page = GetACP();
|
2009-04-06 10:16:40 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VISCII_CHARSET:
|
|
|
|
case TCVN_CHARSET:
|
|
|
|
case KOI8_CHARSET:
|
|
|
|
case ISO3_CHARSET:
|
|
|
|
case ISO4_CHARSET:
|
|
|
|
case ISO10_CHARSET:
|
|
|
|
case CELTIC_CHARSET:
|
|
|
|
/* FIXME: These have no place here, but because x11drv
|
|
|
|
enumerates fonts with these (made up) charsets some apps
|
|
|
|
might use them and then the FIXME below would become
|
|
|
|
annoying. Now we could pick the intended codepage for
|
|
|
|
each of these, but since it's broken anyway we'll just
|
|
|
|
use CP_ACP and hope it'll go away...
|
|
|
|
*/
|
2021-08-20 10:42:24 +02:00
|
|
|
dc->attr->font_code_page = CP_ACP;
|
2009-04-06 10:16:40 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
FIXME("Can't find codepage for charset %d\n", charset);
|
2021-08-20 10:42:24 +02:00
|
|
|
dc->attr->font_code_page = CP_ACP;
|
2009-04-06 10:16:40 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-20 10:42:24 +02:00
|
|
|
TRACE( "charset %d => cp %d\n", charset, dc->attr->font_code_page );
|
2009-04-06 10:16:40 +02:00
|
|
|
}
|
1996-07-17 22:02:21 +02:00
|
|
|
|
2002-05-31 20:43:22 +02:00
|
|
|
/***********************************************************************
|
2021-07-02 12:38:52 +02:00
|
|
|
* NtGdiSelectFont (win32u.@)
|
2002-05-31 20:43:22 +02:00
|
|
|
*/
|
2021-07-02 12:38:52 +02:00
|
|
|
HGDIOBJ WINAPI NtGdiSelectFont( HDC hdc, HGDIOBJ handle )
|
2002-05-31 20:43:22 +02:00
|
|
|
{
|
|
|
|
HGDIOBJ ret = 0;
|
2007-09-27 21:01:00 +02:00
|
|
|
DC *dc = get_dc_ptr( hdc );
|
2011-03-09 21:19:09 +01:00
|
|
|
PHYSDEV physdev;
|
2012-10-30 19:37:31 +01:00
|
|
|
UINT aa_flags = 0;
|
2002-05-31 20:43:22 +02:00
|
|
|
|
|
|
|
if (!dc) return 0;
|
|
|
|
|
2007-09-27 21:01:00 +02:00
|
|
|
if (!GDI_inc_ref_count( handle ))
|
|
|
|
{
|
|
|
|
release_dc_ptr( dc );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-03-09 21:19:09 +01:00
|
|
|
physdev = GET_DC_PHYSDEV( dc, pSelectFont );
|
2012-10-30 19:37:31 +01:00
|
|
|
if (physdev->funcs->pSelectFont( physdev, handle, &aa_flags ))
|
2002-05-31 20:43:22 +02:00
|
|
|
{
|
|
|
|
ret = dc->hFont;
|
|
|
|
dc->hFont = handle;
|
2012-10-31 15:55:29 +01:00
|
|
|
dc->aa_flags = aa_flags ? aa_flags : GGO_BITMAP;
|
2014-06-10 10:48:38 +02:00
|
|
|
update_font_code_page( dc, handle );
|
2018-10-17 03:00:53 +02:00
|
|
|
if (dc->font_gamma_ramp == NULL)
|
2020-11-06 12:10:54 +01:00
|
|
|
dc->font_gamma_ramp = &font_gamma_ramp;
|
2007-09-27 20:57:02 +02:00
|
|
|
GDI_dec_ref_count( ret );
|
2002-05-31 20:43:22 +02:00
|
|
|
}
|
2011-10-18 13:10:58 +02:00
|
|
|
else GDI_dec_ref_count( handle );
|
|
|
|
|
2007-09-27 21:01:00 +02:00
|
|
|
release_dc_ptr( dc );
|
2002-05-31 20:43:22 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-10-23 15:27:36 +02:00
|
|
|
/***********************************************************************
|
1999-07-23 21:25:11 +02:00
|
|
|
* FONT_GetObjectW
|
1998-10-23 15:27:36 +02:00
|
|
|
*/
|
2009-01-27 16:30:43 +01:00
|
|
|
static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
|
1998-10-23 15:27:36 +02:00
|
|
|
{
|
2021-07-08 17:11:45 +02:00
|
|
|
FONTOBJ *font = GDI_GetObjPtr( handle, NTGDI_OBJ_FONT );
|
2009-01-27 16:30:43 +01:00
|
|
|
|
|
|
|
if (!font) return 0;
|
|
|
|
if (buffer)
|
|
|
|
{
|
|
|
|
if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
|
|
|
|
memcpy( buffer, &font->logfont, count );
|
|
|
|
}
|
|
|
|
else count = sizeof(LOGFONTW);
|
|
|
|
GDI_ReleaseObj( handle );
|
1998-10-23 15:27:36 +02:00
|
|
|
return count;
|
|
|
|
}
|
1996-08-24 20:26:35 +02:00
|
|
|
|
|
|
|
|
2002-05-31 20:43:22 +02:00
|
|
|
/***********************************************************************
|
|
|
|
* FONT_DeleteObject
|
|
|
|
*/
|
2009-01-27 16:19:37 +01:00
|
|
|
static BOOL FONT_DeleteObject( HGDIOBJ handle )
|
2002-05-31 20:43:22 +02:00
|
|
|
{
|
2009-01-28 18:45:21 +01:00
|
|
|
FONTOBJ *obj;
|
|
|
|
|
|
|
|
if (!(obj = free_gdi_handle( handle ))) return FALSE;
|
2018-01-22 10:53:38 +01:00
|
|
|
HeapFree( GetProcessHeap(), 0, obj );
|
|
|
|
return TRUE;
|
2002-05-31 20:43:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-09-01 14:08:27 +02:00
|
|
|
struct font_enum
|
|
|
|
{
|
|
|
|
HDC hdc;
|
|
|
|
struct font_enum_entry *buf;
|
|
|
|
ULONG size;
|
|
|
|
ULONG count;
|
|
|
|
ULONG charset;
|
|
|
|
};
|
|
|
|
|
|
|
|
static INT WINAPI font_enum_proc( const LOGFONTW *lf, const TEXTMETRICW *tm,
|
|
|
|
DWORD type, LPARAM lp )
|
1997-06-16 19:43:53 +02:00
|
|
|
{
|
2021-09-01 14:08:27 +02:00
|
|
|
struct font_enum *fe = (struct font_enum *)lp;
|
1997-06-16 19:43:53 +02:00
|
|
|
|
2021-09-01 14:08:27 +02:00
|
|
|
if (fe->charset != DEFAULT_CHARSET && lf->lfCharSet != fe->charset) return 1;
|
|
|
|
if ((type & RASTER_FONTTYPE) && !(NtGdiGetDeviceCaps( fe->hdc, TEXTCAPS ) & TC_RA_ABLE))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (fe->buf && fe->count < fe->size)
|
1997-06-16 19:43:53 +02:00
|
|
|
{
|
2021-09-01 14:08:27 +02:00
|
|
|
fe->buf[fe->count].type = type;
|
|
|
|
fe->buf[fe->count].lf = *(const ENUMLOGFONTEXW *)lf;
|
|
|
|
fe->buf[fe->count].tm = *(const NEWTEXTMETRICEXW *)tm;
|
1997-06-16 19:43:53 +02:00
|
|
|
}
|
2021-09-01 14:08:27 +02:00
|
|
|
fe->count++;
|
|
|
|
return 1;
|
1997-06-16 19:43:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
2021-09-01 14:08:27 +02:00
|
|
|
* NtGdiEnumFonts (win32u.@)
|
1997-06-16 19:43:53 +02:00
|
|
|
*/
|
2021-09-01 14:08:27 +02:00
|
|
|
BOOL WINAPI NtGdiEnumFonts( HDC hdc, ULONG type, ULONG win32_compat, ULONG face_name_len,
|
|
|
|
const WCHAR *face_name, ULONG charset, ULONG *count, void *buf )
|
1997-06-16 19:43:53 +02:00
|
|
|
{
|
2011-10-19 15:34:21 +02:00
|
|
|
struct font_enum fe;
|
2021-09-01 14:08:27 +02:00
|
|
|
PHYSDEV physdev;
|
|
|
|
LOGFONTW lf;
|
|
|
|
BOOL ret;
|
|
|
|
DC *dc;
|
2000-08-19 23:38:55 +02:00
|
|
|
|
2021-09-01 14:08:27 +02:00
|
|
|
if (!(dc = get_dc_ptr( hdc ))) return 0;
|
2011-10-19 15:34:21 +02:00
|
|
|
|
2021-09-01 14:08:27 +02:00
|
|
|
memset( &lf, 0, sizeof(lf) );
|
|
|
|
lf.lfCharSet = charset;
|
|
|
|
if (face_name_len) memcpy( lf.lfFaceName, face_name, face_name_len * sizeof(WCHAR) );
|
1997-06-16 19:43:53 +02:00
|
|
|
|
2021-09-01 14:08:27 +02:00
|
|
|
fe.hdc = hdc;
|
|
|
|
fe.buf = buf;
|
|
|
|
fe.size = *count / sizeof(*fe.buf);
|
|
|
|
fe.count = 0;
|
|
|
|
fe.charset = charset;
|
|
|
|
|
|
|
|
physdev = GET_DC_PHYSDEV( dc, pEnumFonts );
|
|
|
|
ret = physdev->funcs->pEnumFonts( physdev, &lf, font_enum_proc, (LPARAM)&fe );
|
|
|
|
if (ret && buf) ret = fe.count <= fe.size;
|
|
|
|
*count = fe.count * sizeof(*fe.buf);
|
|
|
|
|
|
|
|
release_dc_ptr( dc );
|
|
|
|
return ret;
|
1997-06-16 19:43:53 +02:00
|
|
|
}
|
|
|
|
|
1993-09-04 12:09:32 +02:00
|
|
|
|
1996-12-22 19:27:48 +01:00
|
|
|
/***********************************************************************
|
2021-08-05 11:25:19 +02:00
|
|
|
* NtGdiSetTextJustification (win32u.@)
|
1996-12-22 19:27:48 +01:00
|
|
|
*/
|
2021-08-05 11:25:19 +02:00
|
|
|
BOOL WINAPI NtGdiSetTextJustification( HDC hdc, INT extra, INT breaks )
|
1993-09-04 12:09:32 +02:00
|
|
|
{
|
2021-08-05 11:25:19 +02:00
|
|
|
DC *dc;
|
2011-03-10 21:58:47 +01:00
|
|
|
|
2021-08-05 11:25:19 +02:00
|
|
|
if (!(dc = get_dc_ptr( hdc ))) return FALSE;
|
2011-03-10 21:58:47 +01:00
|
|
|
|
2021-08-05 11:25:19 +02:00
|
|
|
extra = abs( (extra * dc->attr->vport_ext.cx + dc->attr->wnd_ext.cx / 2) /
|
|
|
|
dc->attr->wnd_ext.cx );
|
|
|
|
if (!extra) breaks = 0;
|
|
|
|
if (breaks)
|
1993-09-04 12:09:32 +02:00
|
|
|
{
|
2021-08-05 11:25:19 +02:00
|
|
|
dc->breakExtra = extra / breaks;
|
|
|
|
dc->breakRem = extra - (breaks * dc->breakExtra);
|
1993-09-04 12:09:32 +02:00
|
|
|
}
|
2021-08-05 11:25:19 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
dc->breakExtra = 0;
|
|
|
|
dc->breakRem = 0;
|
|
|
|
}
|
|
|
|
|
2008-02-05 17:35:40 +01:00
|
|
|
release_dc_ptr( dc );
|
2021-08-05 11:25:19 +02:00
|
|
|
return TRUE;
|
1993-09-04 12:09:32 +02:00
|
|
|
}
|
|
|
|
|
1996-12-22 19:27:48 +01:00
|
|
|
|
1994-10-17 19:12:41 +01:00
|
|
|
/***********************************************************************
|
2021-08-20 10:41:32 +02:00
|
|
|
* NtGdiGetTextFaceW (win32u.@)
|
1994-10-17 19:12:41 +01:00
|
|
|
*/
|
2021-08-20 10:41:32 +02:00
|
|
|
INT WINAPI NtGdiGetTextFaceW( HDC hdc, INT count, WCHAR *name, BOOL alias_name )
|
1994-10-17 19:12:41 +01:00
|
|
|
{
|
2011-10-20 17:14:53 +02:00
|
|
|
PHYSDEV dev;
|
|
|
|
INT ret;
|
1994-10-17 19:12:41 +01:00
|
|
|
|
2008-02-05 21:16:27 +01:00
|
|
|
DC * dc = get_dc_ptr( hdc );
|
1994-10-17 19:12:41 +01:00
|
|
|
if (!dc) return 0;
|
2000-08-19 23:38:55 +02:00
|
|
|
|
2011-10-20 17:14:53 +02:00
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetTextFace );
|
|
|
|
ret = dev->funcs->pGetTextFace( dev, count, name );
|
2008-02-05 21:16:27 +01:00
|
|
|
release_dc_ptr( dc );
|
2000-08-19 23:38:55 +02:00
|
|
|
return ret;
|
1994-10-17 19:12:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
Release 960516
Thu May 16 13:35:31 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [*/*.c]
Renamed RECT, POINT and SIZE structures to RECT16, POINT16 and
SIZE16. Implemented Win32 version of most functions that take
these types as parameters.
* [configure]
Patched autoconf to attempt to correctly detect -lnsl and
-lsocket. Please check this out.
* [controls/button.c]
Added support for Win32 BM_* messages.
* [controls/menu.c]
Avoid sending extra WM_MENUSELECT messages. This avoids crashes
with Excel.
* [memory.heap.c] [include/heap.h]
Added support for SEGPTRs in Win32 heaps. Added a few macros to
make using SEGPTRs easier. They are a bit slower than MAKE_SEGPTR,
but they work with Win32.
* [memory/atom.c]
Implemented Win32 atom functions.
* [memory/local.c]
Fixed LocalReAlloc() changes to avoid copying the whole block twice.
* [win32/memory.c]
Use /dev/zero instead of MAP_ANON for VirtualAlloc().
* [windows/class.c]
Properly implemented the Win32 class functions.
* [windows/winproc.c] (New file)
New file handling the message translation between Win16 and Win32.
Mon May 13 18:00:00 1996 Alex Korobka <alex@phm30.pharm.sunysb.edu>
* [windows/mdi.c] [windows/menu.c]
Improved WM_MDICREATE and WM_MDICASCADE handling.
* [windows/event.c] [objects/bitblt.c]
Handle GraphicsExpose event for BitBlt from screen to screen.
* [windows/event.c] [windows/win.c] [windows/nonclient.c]
Bunch of fixes for problems with -managed.
* [windows/win.c] [windows/winpos.c]
Changed conditions for WM_SIZE, WM_MOVE, and WM_GETMINMAXINFO
in CreateWindow.
* [windows/win.c] [windows/queue.c] [misc/user.c]
Do not send WM_PARENTNOTIFY when in AppExit and call WH_SHELL
on window creation/destruction.
* [objects/palette.c]
Crude RealizePalette(). At least something is visible in LviewPro.
Sun May 12 02:05:00 1996 Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>
* [if1632/gdi32.spec]
Added Rectangle (use win16 version).
* [if1632/kernel32.spec]
Added GetWindowsDirectoryA (use win16 GetWindowsDirectory).
* [if1632/user32.spec]
Added GetSubMenu, MoveWindow, SetScrollPos, SetScrollRange (use win16
versions).
Added SetWindowsHookExA (empty stub for now).
* [include/handle32.h]
Changed #include <malloc.h> to #include <stdlib.h> to prevent
hate message from FreeBSD compiler.
* [win32/newfns.c]
Added new function SetWindowsHookEx32A (empty stub for now).
* [win32/user32.c]
Removed redundant debugging printf statement.
Sun May 12 01:24:57 1996 Huw D. M. Davies <h.davies1@physics.oxford.ac.uk>
* [memory/local.c]
Avoid creating adjacent free blocks.
Free the block in LocalReAlloc() before allocating a new one.
Fixed LocalReAlloc() for discarded blocks.
Fri May 10 23:05:12 1996 Jukka Iivonen <iivonen@cc.helsinki.fi>
* [resources/sysres_Fi.rc]
ChooseFont and ChooseColor dialogs updated.
Fri May 10 17:19:33 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [files/drive.c,if1632/kernel.spec]
GetCurrentDirectory(),SetCurrentDirectory() implemented.
* [if1632/advapi32.spec] [if1632/kernel.spec] [if1632/shell.spec]
[include/windows.h] [include/winreg.h] [loader/main.c]
[misc/main.c] [misc/shell.c] [misc/registry.c]
Registry fixes:
- loads win95 registry databases,
- save only updated keys on default,
- now adhers to the new function naming standard,
- minor cleanups.
Tue May 7 22:36:13 1996 Albrecht Kleine <kleine@ak.sax.de>
* [combo.c]
Added WM_COMMAND-handling for interaction between EDIT and COMBOLBOX
and synchronized mine with Greg Kreider's works.
* [commdlg.c]
Bugfix in ChooseFont: font size handling.
1996-05-16 20:21:06 +02:00
|
|
|
/***********************************************************************
|
2021-08-20 10:41:56 +02:00
|
|
|
* NtGdiGetTextExtentExW (win32u.@)
|
2001-08-24 21:12:56 +02:00
|
|
|
*
|
|
|
|
* Return the size of the string as it would be if it was output properly by
|
|
|
|
* e.g. TextOut.
|
1999-12-26 01:47:03 +01:00
|
|
|
*/
|
2021-08-20 10:41:56 +02:00
|
|
|
BOOL WINAPI NtGdiGetTextExtentExW( HDC hdc, const WCHAR *str, INT count, INT max_ext,
|
|
|
|
INT *nfit, INT *dxs, SIZE *size, UINT flags )
|
Release 961215
Sun Dec 15 16:18:15 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [graphics/x11drv/bitblt.c]
Fixed BITBLT_StretchImage for partially covered or inverted
bitmaps.
* [objects/dib.c]
Fixed the upside-down bitmap problem.
Sat Dec 14 02:49:57 1996 Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>
* [if1632/user32.spec]
IsMenu and RemoveMenu added (use existing Win16 functions).
* [include/windows.h]
Corrections to BITMAPINFOHEADER structure.
* [loader/module.c] [if1632/kernel32.spec]
New function GetModuleFileName32A (heavily based on original
Win16 version).
* [loader/pe_image.c]
Hack to allow files with short PE header to be loaded (e.g.
COMDLG32.DLL from Win32s).
* [misc/winsock_async.c]
#if out EIDRM case (not present in FreeBSD).
* [tools/build.c]
Remove trailing comments from .s files generated by build
as these break assembly when not run through pre-processor.
* [windows/graphics.c] [if1632/gdi32.spec]
New function Polyline32 - based on original Polyline. Needs
metafile support adding still.
Fri Dec 13 13:04:06 1996 Bruce Milner <Bruce.Milner@genetics.utah.edu>
* [win32/findfile.c] [if1632/kernel.spec]
FindFirstFile32A(): Use dos current directory for drive prefixes.
FindNextFile32A(): Fill in file attribute information.
Implement FindFirstFile16, FindNextFile16, FindClose16.
* [files/drive.c]
GetCurrentDirectory32A - Fix problem with null 3rd character in
string.
Tue Dec 10 14:49:07 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [windows/painting.c][windows/message.c]
Don't use linked lists to call SendMessage(), for it might destroy
the current listentry.
* [misc/registry.c]
Fixed temporary file saving (rename doesn't work across
partitions).
* [files/*.c]
GetFullPathName*,GetDriveType32A fixed, CreateDirectoryEx*,
GetVolumeInformation32W fixed.
* [win32/process.c][if1632/kernel.spec][if1632/kernel32.spec]
LoadLibrary* updated to new naming std., *32W added.
* [win32/console.c] [include/wincon.h]
Additions for NT commandline executables.
* [if1632/advapi32.spec][if1632/kernel32.spec][win32/init.c]
GetUserName32W added, GetComputerName32W added,
GetStartupInfo32W added, GetSystemInfo updated to NT standard.
* [windows/msgbox.c][misc/shell.c][windows/graphics.c]
MessageBox32W, ShellAbout32W, CommandLineToArgvW, Polygon32 added.
* [misc/crtdll.c][include/crtdll.h][if1632/crtdll.spec][misc/ntdll.c]
[if1632/ntdll.spec]
Lot of new unicode functions added (needed for NT).
* [loader/pe_image.c]
NtCurrentTeb added.
Tue Dec 10 22:39:33 1996 Albrecht Kleine <kleine@ak.sax.de>
* [windows/keyboard.c]
Rewrote function TranslateAccelerator().
Mon Dec 9 14:52:13 1996 Slaven Rezic <eserte@cs.tu-berlin.de>
* [windows/defwnd.c]
DEFWND_SetText(): Set icon name.
Sun Dec 8 23:30:00 1996 Alex Korobka <alex@trantor.pharm.sunysb.edu>
* [loader/signal.c] [misc/winsock.c] [misc/winsock_async.c]
[if1632/winsock.spec]
IPC resource cleanup, bugfixes.
* [windows/dialog.c] [windows/defdlg.c]
More DefDlgProc() fixes.
Sun Dec 8 14:01:42 1996 Vadim Strizhevsky <striv@ms.com>
* [misc/clipboard.c] [objects/font.c] [win32/init.c]
[win32/newfns.c] [windows/graphics.c]
Added a few WIN32 functions which needed to run some win32
accessories. Clock should now work almost as well as 16 bit version.
Add: RegisterClipboardFormat32W GetTextExtentExPoint32*
GetModuleHandleW, DisableThreadLibraryCalls (empty stub),
Polygon32
Fix: Polygon16 possible memory leak on error return.
1996-12-15 20:45:59 +01:00
|
|
|
{
|
2006-07-12 02:58:35 +02:00
|
|
|
DC *dc;
|
2012-12-18 17:41:42 +01:00
|
|
|
int i;
|
|
|
|
BOOL ret;
|
|
|
|
INT buffer[256], *pos = dxs;
|
2001-09-24 03:12:08 +02:00
|
|
|
|
2011-10-11 16:46:19 +02:00
|
|
|
if (count < 0) return FALSE;
|
|
|
|
|
2008-02-05 21:16:27 +01:00
|
|
|
dc = get_dc_ptr(hdc);
|
2011-10-11 16:46:19 +02:00
|
|
|
if (!dc) return FALSE;
|
2006-07-12 02:58:35 +02:00
|
|
|
|
2012-12-18 17:41:42 +01:00
|
|
|
if (!dxs)
|
Release 961215
Sun Dec 15 16:18:15 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [graphics/x11drv/bitblt.c]
Fixed BITBLT_StretchImage for partially covered or inverted
bitmaps.
* [objects/dib.c]
Fixed the upside-down bitmap problem.
Sat Dec 14 02:49:57 1996 Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>
* [if1632/user32.spec]
IsMenu and RemoveMenu added (use existing Win16 functions).
* [include/windows.h]
Corrections to BITMAPINFOHEADER structure.
* [loader/module.c] [if1632/kernel32.spec]
New function GetModuleFileName32A (heavily based on original
Win16 version).
* [loader/pe_image.c]
Hack to allow files with short PE header to be loaded (e.g.
COMDLG32.DLL from Win32s).
* [misc/winsock_async.c]
#if out EIDRM case (not present in FreeBSD).
* [tools/build.c]
Remove trailing comments from .s files generated by build
as these break assembly when not run through pre-processor.
* [windows/graphics.c] [if1632/gdi32.spec]
New function Polyline32 - based on original Polyline. Needs
metafile support adding still.
Fri Dec 13 13:04:06 1996 Bruce Milner <Bruce.Milner@genetics.utah.edu>
* [win32/findfile.c] [if1632/kernel.spec]
FindFirstFile32A(): Use dos current directory for drive prefixes.
FindNextFile32A(): Fill in file attribute information.
Implement FindFirstFile16, FindNextFile16, FindClose16.
* [files/drive.c]
GetCurrentDirectory32A - Fix problem with null 3rd character in
string.
Tue Dec 10 14:49:07 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [windows/painting.c][windows/message.c]
Don't use linked lists to call SendMessage(), for it might destroy
the current listentry.
* [misc/registry.c]
Fixed temporary file saving (rename doesn't work across
partitions).
* [files/*.c]
GetFullPathName*,GetDriveType32A fixed, CreateDirectoryEx*,
GetVolumeInformation32W fixed.
* [win32/process.c][if1632/kernel.spec][if1632/kernel32.spec]
LoadLibrary* updated to new naming std., *32W added.
* [win32/console.c] [include/wincon.h]
Additions for NT commandline executables.
* [if1632/advapi32.spec][if1632/kernel32.spec][win32/init.c]
GetUserName32W added, GetComputerName32W added,
GetStartupInfo32W added, GetSystemInfo updated to NT standard.
* [windows/msgbox.c][misc/shell.c][windows/graphics.c]
MessageBox32W, ShellAbout32W, CommandLineToArgvW, Polygon32 added.
* [misc/crtdll.c][include/crtdll.h][if1632/crtdll.spec][misc/ntdll.c]
[if1632/ntdll.spec]
Lot of new unicode functions added (needed for NT).
* [loader/pe_image.c]
NtCurrentTeb added.
Tue Dec 10 22:39:33 1996 Albrecht Kleine <kleine@ak.sax.de>
* [windows/keyboard.c]
Rewrote function TranslateAccelerator().
Mon Dec 9 14:52:13 1996 Slaven Rezic <eserte@cs.tu-berlin.de>
* [windows/defwnd.c]
DEFWND_SetText(): Set icon name.
Sun Dec 8 23:30:00 1996 Alex Korobka <alex@trantor.pharm.sunysb.edu>
* [loader/signal.c] [misc/winsock.c] [misc/winsock_async.c]
[if1632/winsock.spec]
IPC resource cleanup, bugfixes.
* [windows/dialog.c] [windows/defdlg.c]
More DefDlgProc() fixes.
Sun Dec 8 14:01:42 1996 Vadim Strizhevsky <striv@ms.com>
* [misc/clipboard.c] [objects/font.c] [win32/init.c]
[win32/newfns.c] [windows/graphics.c]
Added a few WIN32 functions which needed to run some win32
accessories. Clock should now work almost as well as 16 bit version.
Add: RegisterClipboardFormat32W GetTextExtentExPoint32*
GetModuleHandleW, DisableThreadLibraryCalls (empty stub),
Polygon32
Fix: Polygon16 possible memory leak on error return.
1996-12-15 20:45:59 +01:00
|
|
|
{
|
2012-12-18 17:41:42 +01:00
|
|
|
pos = buffer;
|
|
|
|
if (count > 256 && !(pos = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*pos) )))
|
|
|
|
{
|
|
|
|
release_dc_ptr( dc );
|
|
|
|
return FALSE;
|
|
|
|
}
|
Release 961215
Sun Dec 15 16:18:15 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [graphics/x11drv/bitblt.c]
Fixed BITBLT_StretchImage for partially covered or inverted
bitmaps.
* [objects/dib.c]
Fixed the upside-down bitmap problem.
Sat Dec 14 02:49:57 1996 Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>
* [if1632/user32.spec]
IsMenu and RemoveMenu added (use existing Win16 functions).
* [include/windows.h]
Corrections to BITMAPINFOHEADER structure.
* [loader/module.c] [if1632/kernel32.spec]
New function GetModuleFileName32A (heavily based on original
Win16 version).
* [loader/pe_image.c]
Hack to allow files with short PE header to be loaded (e.g.
COMDLG32.DLL from Win32s).
* [misc/winsock_async.c]
#if out EIDRM case (not present in FreeBSD).
* [tools/build.c]
Remove trailing comments from .s files generated by build
as these break assembly when not run through pre-processor.
* [windows/graphics.c] [if1632/gdi32.spec]
New function Polyline32 - based on original Polyline. Needs
metafile support adding still.
Fri Dec 13 13:04:06 1996 Bruce Milner <Bruce.Milner@genetics.utah.edu>
* [win32/findfile.c] [if1632/kernel.spec]
FindFirstFile32A(): Use dos current directory for drive prefixes.
FindNextFile32A(): Fill in file attribute information.
Implement FindFirstFile16, FindNextFile16, FindClose16.
* [files/drive.c]
GetCurrentDirectory32A - Fix problem with null 3rd character in
string.
Tue Dec 10 14:49:07 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [windows/painting.c][windows/message.c]
Don't use linked lists to call SendMessage(), for it might destroy
the current listentry.
* [misc/registry.c]
Fixed temporary file saving (rename doesn't work across
partitions).
* [files/*.c]
GetFullPathName*,GetDriveType32A fixed, CreateDirectoryEx*,
GetVolumeInformation32W fixed.
* [win32/process.c][if1632/kernel.spec][if1632/kernel32.spec]
LoadLibrary* updated to new naming std., *32W added.
* [win32/console.c] [include/wincon.h]
Additions for NT commandline executables.
* [if1632/advapi32.spec][if1632/kernel32.spec][win32/init.c]
GetUserName32W added, GetComputerName32W added,
GetStartupInfo32W added, GetSystemInfo updated to NT standard.
* [windows/msgbox.c][misc/shell.c][windows/graphics.c]
MessageBox32W, ShellAbout32W, CommandLineToArgvW, Polygon32 added.
* [misc/crtdll.c][include/crtdll.h][if1632/crtdll.spec][misc/ntdll.c]
[if1632/ntdll.spec]
Lot of new unicode functions added (needed for NT).
* [loader/pe_image.c]
NtCurrentTeb added.
Tue Dec 10 22:39:33 1996 Albrecht Kleine <kleine@ak.sax.de>
* [windows/keyboard.c]
Rewrote function TranslateAccelerator().
Mon Dec 9 14:52:13 1996 Slaven Rezic <eserte@cs.tu-berlin.de>
* [windows/defwnd.c]
DEFWND_SetText(): Set icon name.
Sun Dec 8 23:30:00 1996 Alex Korobka <alex@trantor.pharm.sunysb.edu>
* [loader/signal.c] [misc/winsock.c] [misc/winsock_async.c]
[if1632/winsock.spec]
IPC resource cleanup, bugfixes.
* [windows/dialog.c] [windows/defdlg.c]
More DefDlgProc() fixes.
Sun Dec 8 14:01:42 1996 Vadim Strizhevsky <striv@ms.com>
* [misc/clipboard.c] [objects/font.c] [win32/init.c]
[win32/newfns.c] [windows/graphics.c]
Added a few WIN32 functions which needed to run some win32
accessories. Clock should now work almost as well as 16 bit version.
Add: RegisterClipboardFormat32W GetTextExtentExPoint32*
GetModuleHandleW, DisableThreadLibraryCalls (empty stub),
Polygon32
Fix: Polygon16 possible memory leak on error return.
1996-12-15 20:45:59 +01:00
|
|
|
}
|
2000-09-24 05:05:11 +02:00
|
|
|
|
2021-08-20 10:41:56 +02:00
|
|
|
|
|
|
|
if (flags)
|
|
|
|
ret = get_char_positions_indices( dc, str, count, pos, size );
|
|
|
|
else
|
|
|
|
ret = get_char_positions( dc, str, count, pos, size );
|
2006-07-12 02:58:35 +02:00
|
|
|
if (ret)
|
|
|
|
{
|
2012-12-18 17:41:42 +01:00
|
|
|
if (dxs || nfit)
|
2007-02-08 16:12:08 +01:00
|
|
|
{
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
2021-08-05 11:26:13 +02:00
|
|
|
unsigned int dx = abs( INTERNAL_XDSTOWS( dc, pos[i] )) +
|
|
|
|
(i + 1) * dc->attr->char_extra;
|
2013-07-22 15:07:36 +02:00
|
|
|
if (nfit && dx > (unsigned int)max_ext) break;
|
2012-12-18 17:41:42 +01:00
|
|
|
if (dxs) dxs[i] = dx;
|
2007-02-08 16:12:08 +01:00
|
|
|
}
|
2012-12-18 17:41:42 +01:00
|
|
|
if (nfit) *nfit = i;
|
2007-02-08 16:12:08 +01:00
|
|
|
}
|
2006-07-12 02:58:35 +02:00
|
|
|
|
2021-08-05 11:26:13 +02:00
|
|
|
size->cx = abs( INTERNAL_XDSTOWS( dc, size->cx )) + count * dc->attr->char_extra;
|
2012-12-18 17:41:42 +01:00
|
|
|
size->cy = abs( INTERNAL_YDSTOWS( dc, size->cy ));
|
|
|
|
}
|
2006-07-12 02:58:35 +02:00
|
|
|
|
2012-12-18 17:41:42 +01:00
|
|
|
if (pos != buffer && pos != dxs) HeapFree( GetProcessHeap(), 0, pos );
|
2008-02-05 21:16:27 +01:00
|
|
|
release_dc_ptr( dc );
|
2006-07-12 02:58:35 +02:00
|
|
|
|
2012-12-18 17:41:42 +01:00
|
|
|
TRACE("(%p, %s, %d) returning %dx%d\n", hdc, debugstr_wn(str,count), max_ext, size->cx, size->cy );
|
2000-08-19 23:38:55 +02:00
|
|
|
return ret;
|
Release 961215
Sun Dec 15 16:18:15 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [graphics/x11drv/bitblt.c]
Fixed BITBLT_StretchImage for partially covered or inverted
bitmaps.
* [objects/dib.c]
Fixed the upside-down bitmap problem.
Sat Dec 14 02:49:57 1996 Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>
* [if1632/user32.spec]
IsMenu and RemoveMenu added (use existing Win16 functions).
* [include/windows.h]
Corrections to BITMAPINFOHEADER structure.
* [loader/module.c] [if1632/kernel32.spec]
New function GetModuleFileName32A (heavily based on original
Win16 version).
* [loader/pe_image.c]
Hack to allow files with short PE header to be loaded (e.g.
COMDLG32.DLL from Win32s).
* [misc/winsock_async.c]
#if out EIDRM case (not present in FreeBSD).
* [tools/build.c]
Remove trailing comments from .s files generated by build
as these break assembly when not run through pre-processor.
* [windows/graphics.c] [if1632/gdi32.spec]
New function Polyline32 - based on original Polyline. Needs
metafile support adding still.
Fri Dec 13 13:04:06 1996 Bruce Milner <Bruce.Milner@genetics.utah.edu>
* [win32/findfile.c] [if1632/kernel.spec]
FindFirstFile32A(): Use dos current directory for drive prefixes.
FindNextFile32A(): Fill in file attribute information.
Implement FindFirstFile16, FindNextFile16, FindClose16.
* [files/drive.c]
GetCurrentDirectory32A - Fix problem with null 3rd character in
string.
Tue Dec 10 14:49:07 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [windows/painting.c][windows/message.c]
Don't use linked lists to call SendMessage(), for it might destroy
the current listentry.
* [misc/registry.c]
Fixed temporary file saving (rename doesn't work across
partitions).
* [files/*.c]
GetFullPathName*,GetDriveType32A fixed, CreateDirectoryEx*,
GetVolumeInformation32W fixed.
* [win32/process.c][if1632/kernel.spec][if1632/kernel32.spec]
LoadLibrary* updated to new naming std., *32W added.
* [win32/console.c] [include/wincon.h]
Additions for NT commandline executables.
* [if1632/advapi32.spec][if1632/kernel32.spec][win32/init.c]
GetUserName32W added, GetComputerName32W added,
GetStartupInfo32W added, GetSystemInfo updated to NT standard.
* [windows/msgbox.c][misc/shell.c][windows/graphics.c]
MessageBox32W, ShellAbout32W, CommandLineToArgvW, Polygon32 added.
* [misc/crtdll.c][include/crtdll.h][if1632/crtdll.spec][misc/ntdll.c]
[if1632/ntdll.spec]
Lot of new unicode functions added (needed for NT).
* [loader/pe_image.c]
NtCurrentTeb added.
Tue Dec 10 22:39:33 1996 Albrecht Kleine <kleine@ak.sax.de>
* [windows/keyboard.c]
Rewrote function TranslateAccelerator().
Mon Dec 9 14:52:13 1996 Slaven Rezic <eserte@cs.tu-berlin.de>
* [windows/defwnd.c]
DEFWND_SetText(): Set icon name.
Sun Dec 8 23:30:00 1996 Alex Korobka <alex@trantor.pharm.sunysb.edu>
* [loader/signal.c] [misc/winsock.c] [misc/winsock_async.c]
[if1632/winsock.spec]
IPC resource cleanup, bugfixes.
* [windows/dialog.c] [windows/defdlg.c]
More DefDlgProc() fixes.
Sun Dec 8 14:01:42 1996 Vadim Strizhevsky <striv@ms.com>
* [misc/clipboard.c] [objects/font.c] [win32/init.c]
[win32/newfns.c] [windows/graphics.c]
Added a few WIN32 functions which needed to run some win32
accessories. Clock should now work almost as well as 16 bit version.
Add: RegisterClipboardFormat32W GetTextExtentExPoint32*
GetModuleHandleW, DisableThreadLibraryCalls (empty stub),
Polygon32
Fix: Polygon16 possible memory leak on error return.
1996-12-15 20:45:59 +01:00
|
|
|
}
|
|
|
|
|
Release 970120
Sun Jan 19 11:46:48 1997 Alexandre Julliard <julliard@lrc.epfl.ch>
* [loader/module.c]
Fixed LoadModule() to always call the DLL initialization code.
* [windows/event.c]
Moved all the keyboard stuff to windows/keyboard.c
* [tools/build.c]
Fixed Win32 register functions.
Sat Jan 18 22:24:41 1997 David Makepeace <D.Makepeace@mailbox.uq.oz.au>
* [tools/makedep.c]
Fixed bug which causes SEGV on Solaris x86.
Fri Jan 17 18:32:27 1997 Frans van Dorsselaer <dorssel@rulhmpc49.LeidenUniv.nl>
* [controls/edit.c]
Implemented WM_UNDO, WM_CONTEXTMENU (temporary using WM_RBUTTONUP),
WM_COMMAND, WM_INITPOPUPMENU, WM_SYSKEYDOWN.
Fixed EM_SETSEL and some minor bugs (features).
Hence: fully functional undo and a win95 menu with the right mouse
button.
* [include/resources.h] [resources/TODO] [resources/sysres_??.rc]
Added a context menu for the edit control.
Translations, please ...
Fri Jan 17 08:29:52 1997 David Faure <david.faure@ifhamy.insa-lyon.fr>
* [windows/event.c]
Move EVENT_ToAscii to windows/keyboard.c (where name ToAscii)
Fixed Keypad keys 0-9 and . in EVENT_event_to_vkey.
Added 3-state handling of toggle keys (CapsLock, NumLock) in order
to make them work with any X server.
Toggle keys now generate WM_KEYDOWN and WM_KEYUP on each pressing.
* [include/keyboard.h]
Totally replaced the file (formerly containing the vkcase definitions)
by the declaration of 'extern' variables contained by event.c and used
by keyboard.c
* [windows/keyboard.c]
Started to rewrite VkKeyScan and MapVirtualKey, to make them use the
table keyc2vkey or X functions only.
ToAscii : added keypad 0-9 and . special case.
Changed toggle keys active mask from 0x80 to 0x1.
* [misc/keyboard.c]
File deleted. Contents moved to windows/keyboard.c.
* [misc/main.c]
Added putenv XKB_DISABLE to disable XKB extension (which, when
present, causes AltGr to change keyboard group instead of being a
modifier).
Tue Jan 14 22:56:43 1997 Philippe De Muyter <phdm@info.ucl.ac.be>
* [windows/event.c]
Do not assume NumLockMask is Mod2Mask, but compute it by scanning
output of XGetModifierMapping for XK_Num_Lock.
Tue Jan 14 15:49:49 1997 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [loader/pe_*.c] [include/peexe.h] [include/resource32.h]
[debugger/*.c]
General clean up.
Changed defines/structures to match Windows NT SDK.
* [loader/main.c]
Don't crash on empty command-line.
* [windows/winpos.c]
winpos.c made win32 clean.
* [misc/ntdll.c]
Some string conversion additions.
* [files/file.c]
GetFileAttributes/GetTempFileName fixed.
* [misc/ver.c]
VerInstallFile implemented.
Mon Jan 13 15:03:11 1997 Philippe De Muyter <phdm@info.ucl.ac.be>
* [tools/build.c]: Use PREFIX also in stabs messages.
Mon Jan 13 10:40:33 1997 John Harvey <john@division.co.uk>
* [graphics/win16drv/*] [include/win16drv.h]
Many fixes and some new features.
* [graphics/x11drv/font.c] [graphics/x11drv/init.c]
[include/x11drv.h] [objects/font.c]
GetTextMetrics() moved to graphics driver.
* [if1632/gdi.spec] [misc/fontengine.c] [misc/Makefile.in]
New dummy EngineEnumerateFont, EngineRealizeFont functions.
* [include/windows.h]
TEXTFORM16 and FONTINFO16 structure definitions moved here from
include/win16drv.h
1997-01-20 20:43:45 +01:00
|
|
|
/***********************************************************************
|
2021-08-20 10:42:10 +02:00
|
|
|
* NtGdiGetTextMetricsW (win32u.@)
|
Release 970120
Sun Jan 19 11:46:48 1997 Alexandre Julliard <julliard@lrc.epfl.ch>
* [loader/module.c]
Fixed LoadModule() to always call the DLL initialization code.
* [windows/event.c]
Moved all the keyboard stuff to windows/keyboard.c
* [tools/build.c]
Fixed Win32 register functions.
Sat Jan 18 22:24:41 1997 David Makepeace <D.Makepeace@mailbox.uq.oz.au>
* [tools/makedep.c]
Fixed bug which causes SEGV on Solaris x86.
Fri Jan 17 18:32:27 1997 Frans van Dorsselaer <dorssel@rulhmpc49.LeidenUniv.nl>
* [controls/edit.c]
Implemented WM_UNDO, WM_CONTEXTMENU (temporary using WM_RBUTTONUP),
WM_COMMAND, WM_INITPOPUPMENU, WM_SYSKEYDOWN.
Fixed EM_SETSEL and some minor bugs (features).
Hence: fully functional undo and a win95 menu with the right mouse
button.
* [include/resources.h] [resources/TODO] [resources/sysres_??.rc]
Added a context menu for the edit control.
Translations, please ...
Fri Jan 17 08:29:52 1997 David Faure <david.faure@ifhamy.insa-lyon.fr>
* [windows/event.c]
Move EVENT_ToAscii to windows/keyboard.c (where name ToAscii)
Fixed Keypad keys 0-9 and . in EVENT_event_to_vkey.
Added 3-state handling of toggle keys (CapsLock, NumLock) in order
to make them work with any X server.
Toggle keys now generate WM_KEYDOWN and WM_KEYUP on each pressing.
* [include/keyboard.h]
Totally replaced the file (formerly containing the vkcase definitions)
by the declaration of 'extern' variables contained by event.c and used
by keyboard.c
* [windows/keyboard.c]
Started to rewrite VkKeyScan and MapVirtualKey, to make them use the
table keyc2vkey or X functions only.
ToAscii : added keypad 0-9 and . special case.
Changed toggle keys active mask from 0x80 to 0x1.
* [misc/keyboard.c]
File deleted. Contents moved to windows/keyboard.c.
* [misc/main.c]
Added putenv XKB_DISABLE to disable XKB extension (which, when
present, causes AltGr to change keyboard group instead of being a
modifier).
Tue Jan 14 22:56:43 1997 Philippe De Muyter <phdm@info.ucl.ac.be>
* [windows/event.c]
Do not assume NumLockMask is Mod2Mask, but compute it by scanning
output of XGetModifierMapping for XK_Num_Lock.
Tue Jan 14 15:49:49 1997 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [loader/pe_*.c] [include/peexe.h] [include/resource32.h]
[debugger/*.c]
General clean up.
Changed defines/structures to match Windows NT SDK.
* [loader/main.c]
Don't crash on empty command-line.
* [windows/winpos.c]
winpos.c made win32 clean.
* [misc/ntdll.c]
Some string conversion additions.
* [files/file.c]
GetFileAttributes/GetTempFileName fixed.
* [misc/ver.c]
VerInstallFile implemented.
Mon Jan 13 15:03:11 1997 Philippe De Muyter <phdm@info.ucl.ac.be>
* [tools/build.c]: Use PREFIX also in stabs messages.
Mon Jan 13 10:40:33 1997 John Harvey <john@division.co.uk>
* [graphics/win16drv/*] [include/win16drv.h]
Many fixes and some new features.
* [graphics/x11drv/font.c] [graphics/x11drv/init.c]
[include/x11drv.h] [objects/font.c]
GetTextMetrics() moved to graphics driver.
* [if1632/gdi.spec] [misc/fontengine.c] [misc/Makefile.in]
New dummy EngineEnumerateFont, EngineRealizeFont functions.
* [include/windows.h]
TEXTFORM16 and FONTINFO16 structure definitions moved here from
include/win16drv.h
1997-01-20 20:43:45 +01:00
|
|
|
*/
|
2021-08-20 10:42:10 +02:00
|
|
|
BOOL WINAPI NtGdiGetTextMetricsW( HDC hdc, TEXTMETRICW *metrics, ULONG flags )
|
2001-03-16 17:43:14 +01:00
|
|
|
{
|
2011-10-19 14:12:23 +02:00
|
|
|
PHYSDEV physdev;
|
2000-08-19 23:38:55 +02:00
|
|
|
BOOL ret = FALSE;
|
2008-02-05 21:16:27 +01:00
|
|
|
DC * dc = get_dc_ptr( hdc );
|
2000-08-19 23:38:55 +02:00
|
|
|
if (!dc) return FALSE;
|
Release 970914
Thu Sep 11 18:24:56 1997 Philippe De Muyter <phdm@info.ucl.ac.be>
* [objects/dc.c]
In DC_SetupGCForPatBlt, replace R2_NOT by GXxor with (black xor white).
Tue Sep 9 23:04:02 1997 U. Bonnes <bon@elektron.ikp.physik.th-darmstadt.de>
* [memory/virtual.c]
Do not write debugging info unconditionally to stderr.
* [files/profile.c]
Call PROFILE_GetSection in PROFILE_GetString for key_name "" too.
* [misc/crtdll.c]
Many new functions.
* [include/windows.h] [windows/winpos.c]
ClientToScreen16 doesn't have a return value.
Sun Sep 7 10:06:39 1997 Alexandre Julliard <julliard@lrc.epfl.ch>
* [misc/main.c] [AUTHORS]
Update the list of contributors. Please let me know if I forgot
someone.
* [if1632/*.spec] [if1632/builtin.c] [tools/build.c]
Ordinal base for Win32 DLLs is now computed automatically from the
lowest ordinal found.
* [include/wintypes.h]
WINAPI is now defined as attribute((stdcall)). This will require
gcc to compile.
* [if1632/thunk.c]
Removed Win32 thunks (no longer needed with stdcall).
* [if1632/crtdll.spec] [misc/crtdll.c]
Make sure we only reference cdecl functions in the spec file.
* [objects/dc.c]
Use CapNotLast drawing style for 1-pixel wide lines.
* [tools/build.c]
Added 'double' argument type.
Added 'varargs' function type for Win32.
Made CallTo16_xxx functions stdcall.
Fri Sep 5 14:50:49 1997 Alex Korobka <alex@trantor.pharm.sunysb.edu>
* [tools/build.c] [windows/win.c] [windows/event.c] [windows/message.c]
More fixes to get message exchange closer to the original.
* [misc/spy.c]
Message logs now contain window names.
* [loader/resource.c] [loader/ne_resource.c] [loader/task.c]
[objects/cursoricon.c] [windows/user.c]
Added some obscure features to fix memory leaks.
Fri Sep 5 00:46:28 1997 Jan Willamowius <jan@janhh.shnet.org>
* [if1632/kernel32.spec] [win32/newfns.c]
Added stub for UTRegister() and UTUnRegister().
Thu Sep 4 12:03:12 1997 Frans van Dorsselaer <dorssel@rulhmpc49.LeidenUniv.nl>
* [controls/edit.c]
Allow ASCII codes > 127 in WM_CHAR.
Mon Sep 1 17:23:24 1997 Dimitrie O. Paun <dimi@mail.cs.toronto.edu>
* [controls/widgets.c]
In InitCommonControls, remember the name of the class
because lpszClassName was made to point to a local array
Added the ProgressBar to the list of implemented controls.
Call InitCommonControls from WIDGETS_Init to register all
implemented Common Controls.
* [include/commctrl.h]
Added misc decl for the Progress Bar.
* [controls/progress.c] [include/progress.h]
First attempt at implementiong the Progress Bar class.
* [objects/brush.h]
Implementation for GetSysColorBrush[16|32]
* [controls/status.c]
Use DrawEdge to draw the borders and fill the background
* [controls/uitools.c]
Added DrawDiagEdge32 and DrawRectEdge32
* [graphics/painting.c]
Implement DrawEdge[16|32]
Started DrawFrameControl32
Mon Sep 1 10:07:09 1997 Lawson Whitney <lawson_whitney@juno.com>
* [misc/comm.c] [include/windows.h]
SetCommEventMask returns a SEGPTR.
Sun Aug 31 23:28:32 1997 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [loader/pe_image.c][loader/module.c][include/pe_image.h]
[include/module.h]
Cleaned up the whole Win32 library mess (a bit).
* [debugger/stabs.c]
If 'wine' has no absolute path and isn't found, check $PATH too.
* [misc/ole2nls.c]
Some fixes.
* [misc/ver.c]
Added support for PE style version resources.
* [memory/string.c]
Check for NULL pointers to _lstr* functions, just as Windows95 does.
* [multimedia/time.c]
Made list of timers a simple linked list.
* [loader/resource.c]
Netscape 3 seems to pass NEGATIVE resource Ids (in an
unsigned int, yes). Don't know why, fixed it anyway.
* [objects/bitmap.c]
LoadImageW added.
* [include/win.h][windows/win.c]
Change wIDmenu from UINT16 to UINT32 and changed the
SetWindow(Long|Word) accordingly.
Thu Aug 28 19:30:08 1997 Morten Welinder <terra@diku.dk>
* [include/windows.h]
Add a few more colors defined for Win95.
Add a few more brush styles.
* [windows/syscolor.c]
Add error checks for SYSCOLOR_SetColor, SYSCOLOR_Init,
GetSysColor16, GetSysColor32. Add support for above colors.
Sun Aug 24 16:22:57 1997 Andrew Taylor <andrew@riscan.com>
* [multimedia/mmsystem.c]
Changed mmioDescend to use mmio functions for file I/O, neccessary
for memory files.
1997-09-14 19:17:23 +02:00
|
|
|
|
2011-10-19 14:12:23 +02:00
|
|
|
physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
|
|
|
|
ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
|
2001-09-12 22:21:06 +02:00
|
|
|
|
|
|
|
if (ret)
|
2000-08-19 23:38:55 +02:00
|
|
|
{
|
Release 970914
Thu Sep 11 18:24:56 1997 Philippe De Muyter <phdm@info.ucl.ac.be>
* [objects/dc.c]
In DC_SetupGCForPatBlt, replace R2_NOT by GXxor with (black xor white).
Tue Sep 9 23:04:02 1997 U. Bonnes <bon@elektron.ikp.physik.th-darmstadt.de>
* [memory/virtual.c]
Do not write debugging info unconditionally to stderr.
* [files/profile.c]
Call PROFILE_GetSection in PROFILE_GetString for key_name "" too.
* [misc/crtdll.c]
Many new functions.
* [include/windows.h] [windows/winpos.c]
ClientToScreen16 doesn't have a return value.
Sun Sep 7 10:06:39 1997 Alexandre Julliard <julliard@lrc.epfl.ch>
* [misc/main.c] [AUTHORS]
Update the list of contributors. Please let me know if I forgot
someone.
* [if1632/*.spec] [if1632/builtin.c] [tools/build.c]
Ordinal base for Win32 DLLs is now computed automatically from the
lowest ordinal found.
* [include/wintypes.h]
WINAPI is now defined as attribute((stdcall)). This will require
gcc to compile.
* [if1632/thunk.c]
Removed Win32 thunks (no longer needed with stdcall).
* [if1632/crtdll.spec] [misc/crtdll.c]
Make sure we only reference cdecl functions in the spec file.
* [objects/dc.c]
Use CapNotLast drawing style for 1-pixel wide lines.
* [tools/build.c]
Added 'double' argument type.
Added 'varargs' function type for Win32.
Made CallTo16_xxx functions stdcall.
Fri Sep 5 14:50:49 1997 Alex Korobka <alex@trantor.pharm.sunysb.edu>
* [tools/build.c] [windows/win.c] [windows/event.c] [windows/message.c]
More fixes to get message exchange closer to the original.
* [misc/spy.c]
Message logs now contain window names.
* [loader/resource.c] [loader/ne_resource.c] [loader/task.c]
[objects/cursoricon.c] [windows/user.c]
Added some obscure features to fix memory leaks.
Fri Sep 5 00:46:28 1997 Jan Willamowius <jan@janhh.shnet.org>
* [if1632/kernel32.spec] [win32/newfns.c]
Added stub for UTRegister() and UTUnRegister().
Thu Sep 4 12:03:12 1997 Frans van Dorsselaer <dorssel@rulhmpc49.LeidenUniv.nl>
* [controls/edit.c]
Allow ASCII codes > 127 in WM_CHAR.
Mon Sep 1 17:23:24 1997 Dimitrie O. Paun <dimi@mail.cs.toronto.edu>
* [controls/widgets.c]
In InitCommonControls, remember the name of the class
because lpszClassName was made to point to a local array
Added the ProgressBar to the list of implemented controls.
Call InitCommonControls from WIDGETS_Init to register all
implemented Common Controls.
* [include/commctrl.h]
Added misc decl for the Progress Bar.
* [controls/progress.c] [include/progress.h]
First attempt at implementiong the Progress Bar class.
* [objects/brush.h]
Implementation for GetSysColorBrush[16|32]
* [controls/status.c]
Use DrawEdge to draw the borders and fill the background
* [controls/uitools.c]
Added DrawDiagEdge32 and DrawRectEdge32
* [graphics/painting.c]
Implement DrawEdge[16|32]
Started DrawFrameControl32
Mon Sep 1 10:07:09 1997 Lawson Whitney <lawson_whitney@juno.com>
* [misc/comm.c] [include/windows.h]
SetCommEventMask returns a SEGPTR.
Sun Aug 31 23:28:32 1997 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [loader/pe_image.c][loader/module.c][include/pe_image.h]
[include/module.h]
Cleaned up the whole Win32 library mess (a bit).
* [debugger/stabs.c]
If 'wine' has no absolute path and isn't found, check $PATH too.
* [misc/ole2nls.c]
Some fixes.
* [misc/ver.c]
Added support for PE style version resources.
* [memory/string.c]
Check for NULL pointers to _lstr* functions, just as Windows95 does.
* [multimedia/time.c]
Made list of timers a simple linked list.
* [loader/resource.c]
Netscape 3 seems to pass NEGATIVE resource Ids (in an
unsigned int, yes). Don't know why, fixed it anyway.
* [objects/bitmap.c]
LoadImageW added.
* [include/win.h][windows/win.c]
Change wIDmenu from UINT16 to UINT32 and changed the
SetWindow(Long|Word) accordingly.
Thu Aug 28 19:30:08 1997 Morten Welinder <terra@diku.dk>
* [include/windows.h]
Add a few more colors defined for Win95.
Add a few more brush styles.
* [windows/syscolor.c]
Add error checks for SYSCOLOR_SetColor, SYSCOLOR_Init,
GetSysColor16, GetSysColor32. Add support for above colors.
Sun Aug 24 16:22:57 1997 Andrew Taylor <andrew@riscan.com>
* [multimedia/mmsystem.c]
Changed mmioDescend to use mmio functions for file I/O, neccessary
for memory files.
1997-09-14 19:17:23 +02:00
|
|
|
/* device layer returns values in device units
|
|
|
|
* therefore we have to convert them to logical */
|
|
|
|
|
2021-09-10 14:28:30 +02:00
|
|
|
metrics->tmDigitizedAspectX = NtGdiGetDeviceCaps(hdc, LOGPIXELSX);
|
|
|
|
metrics->tmDigitizedAspectY = NtGdiGetDeviceCaps(hdc, LOGPIXELSY);
|
2013-09-11 18:31:01 +02:00
|
|
|
metrics->tmHeight = height_to_LP( dc, metrics->tmHeight );
|
|
|
|
metrics->tmAscent = height_to_LP( dc, metrics->tmAscent );
|
|
|
|
metrics->tmDescent = height_to_LP( dc, metrics->tmDescent );
|
|
|
|
metrics->tmInternalLeading = height_to_LP( dc, metrics->tmInternalLeading );
|
|
|
|
metrics->tmExternalLeading = height_to_LP( dc, metrics->tmExternalLeading );
|
|
|
|
metrics->tmAveCharWidth = width_to_LP( dc, metrics->tmAveCharWidth );
|
|
|
|
metrics->tmMaxCharWidth = width_to_LP( dc, metrics->tmMaxCharWidth );
|
|
|
|
metrics->tmOverhang = width_to_LP( dc, metrics->tmOverhang );
|
2000-08-19 23:38:55 +02:00
|
|
|
ret = TRUE;
|
2013-09-11 18:31:01 +02:00
|
|
|
|
|
|
|
TRACE("text metrics:\n"
|
2006-10-12 22:56:56 +02:00
|
|
|
" Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
|
|
|
|
" Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
|
|
|
|
" UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
|
2001-03-16 17:43:14 +01:00
|
|
|
" StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
|
1999-12-08 04:56:23 +01:00
|
|
|
" PitchAndFamily = %02x\n"
|
|
|
|
" --------------------\n"
|
2006-10-12 22:56:56 +02:00
|
|
|
" InternalLeading = %i\n"
|
|
|
|
" Ascent = %i\n"
|
|
|
|
" Descent = %i\n"
|
|
|
|
" Height = %i\n",
|
1999-12-08 04:56:23 +01:00
|
|
|
metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
|
|
|
|
metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
|
|
|
|
metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
|
|
|
|
metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
|
|
|
|
metrics->tmPitchAndFamily,
|
|
|
|
metrics->tmInternalLeading,
|
|
|
|
metrics->tmAscent,
|
|
|
|
metrics->tmDescent,
|
|
|
|
metrics->tmHeight );
|
2000-08-19 23:38:55 +02:00
|
|
|
}
|
2008-02-05 21:16:27 +01:00
|
|
|
release_dc_ptr( dc );
|
2000-08-19 23:38:55 +02:00
|
|
|
return ret;
|
1996-07-05 19:14:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-10-14 20:15:43 +02:00
|
|
|
/***********************************************************************
|
2021-08-20 10:43:13 +02:00
|
|
|
* NtGdiGetOutlineTextMetricsInternalW (win32u.@)
|
1998-12-10 16:49:22 +01:00
|
|
|
*/
|
2021-08-20 10:43:13 +02:00
|
|
|
UINT WINAPI NtGdiGetOutlineTextMetricsInternalW( HDC hdc, UINT cbData,
|
|
|
|
OUTLINETEXTMETRICW *lpOTM, ULONG opts )
|
1998-12-10 16:49:22 +01:00
|
|
|
{
|
2008-02-05 21:16:27 +01:00
|
|
|
DC *dc = get_dc_ptr( hdc );
|
2003-11-11 21:39:54 +01:00
|
|
|
OUTLINETEXTMETRICW *output = lpOTM;
|
2011-10-20 16:49:18 +02:00
|
|
|
PHYSDEV dev;
|
2001-09-12 22:21:06 +02:00
|
|
|
UINT ret;
|
|
|
|
|
2002-11-22 23:16:53 +01:00
|
|
|
TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
|
2001-09-12 22:21:06 +02:00
|
|
|
if(!dc) return 0;
|
|
|
|
|
2011-10-20 16:49:18 +02:00
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetOutlineTextMetrics );
|
|
|
|
ret = dev->funcs->pGetOutlineTextMetrics( dev, cbData, output );
|
2003-11-11 21:39:54 +01:00
|
|
|
|
2011-10-20 16:49:18 +02:00
|
|
|
if (lpOTM && ret > cbData)
|
|
|
|
{
|
|
|
|
output = HeapAlloc(GetProcessHeap(), 0, ret);
|
|
|
|
ret = dev->funcs->pGetOutlineTextMetrics( dev, ret, output );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lpOTM && ret)
|
|
|
|
{
|
2021-09-10 14:28:30 +02:00
|
|
|
output->otmTextMetrics.tmDigitizedAspectX = NtGdiGetDeviceCaps(hdc, LOGPIXELSX);
|
|
|
|
output->otmTextMetrics.tmDigitizedAspectY = NtGdiGetDeviceCaps(hdc, LOGPIXELSY);
|
2013-09-11 18:31:01 +02:00
|
|
|
output->otmTextMetrics.tmHeight = height_to_LP( dc, output->otmTextMetrics.tmHeight );
|
|
|
|
output->otmTextMetrics.tmAscent = height_to_LP( dc, output->otmTextMetrics.tmAscent );
|
|
|
|
output->otmTextMetrics.tmDescent = height_to_LP( dc, output->otmTextMetrics.tmDescent );
|
|
|
|
output->otmTextMetrics.tmInternalLeading = height_to_LP( dc, output->otmTextMetrics.tmInternalLeading );
|
|
|
|
output->otmTextMetrics.tmExternalLeading = height_to_LP( dc, output->otmTextMetrics.tmExternalLeading );
|
|
|
|
output->otmTextMetrics.tmAveCharWidth = width_to_LP( dc, output->otmTextMetrics.tmAveCharWidth );
|
|
|
|
output->otmTextMetrics.tmMaxCharWidth = width_to_LP( dc, output->otmTextMetrics.tmMaxCharWidth );
|
|
|
|
output->otmTextMetrics.tmOverhang = width_to_LP( dc, output->otmTextMetrics.tmOverhang );
|
|
|
|
output->otmAscent = height_to_LP( dc, output->otmAscent);
|
|
|
|
output->otmDescent = height_to_LP( dc, output->otmDescent);
|
2017-12-19 04:31:06 +01:00
|
|
|
output->otmLineGap = INTERNAL_YDSTOWS(dc, output->otmLineGap);
|
|
|
|
output->otmsCapEmHeight = INTERNAL_YDSTOWS(dc, output->otmsCapEmHeight);
|
|
|
|
output->otmsXHeight = INTERNAL_YDSTOWS(dc, output->otmsXHeight);
|
2013-09-11 18:31:01 +02:00
|
|
|
output->otmrcFontBox.top = height_to_LP( dc, output->otmrcFontBox.top);
|
|
|
|
output->otmrcFontBox.bottom = height_to_LP( dc, output->otmrcFontBox.bottom);
|
|
|
|
output->otmrcFontBox.left = width_to_LP( dc, output->otmrcFontBox.left);
|
|
|
|
output->otmrcFontBox.right = width_to_LP( dc, output->otmrcFontBox.right);
|
|
|
|
output->otmMacAscent = height_to_LP( dc, output->otmMacAscent);
|
|
|
|
output->otmMacDescent = height_to_LP( dc, output->otmMacDescent);
|
2017-12-19 04:31:06 +01:00
|
|
|
output->otmMacLineGap = INTERNAL_YDSTOWS(dc, output->otmMacLineGap);
|
2013-09-11 18:31:01 +02:00
|
|
|
output->otmptSubscriptSize.x = width_to_LP( dc, output->otmptSubscriptSize.x);
|
|
|
|
output->otmptSubscriptSize.y = height_to_LP( dc, output->otmptSubscriptSize.y);
|
|
|
|
output->otmptSubscriptOffset.x = width_to_LP( dc, output->otmptSubscriptOffset.x);
|
|
|
|
output->otmptSubscriptOffset.y = height_to_LP( dc, output->otmptSubscriptOffset.y);
|
|
|
|
output->otmptSuperscriptSize.x = width_to_LP( dc, output->otmptSuperscriptSize.x);
|
|
|
|
output->otmptSuperscriptSize.y = height_to_LP( dc, output->otmptSuperscriptSize.y);
|
|
|
|
output->otmptSuperscriptOffset.x = width_to_LP( dc, output->otmptSuperscriptOffset.x);
|
|
|
|
output->otmptSuperscriptOffset.y = height_to_LP( dc, output->otmptSuperscriptOffset.y);
|
2017-12-19 04:31:06 +01:00
|
|
|
output->otmsStrikeoutSize = INTERNAL_YDSTOWS(dc, output->otmsStrikeoutSize);
|
2013-09-11 18:31:01 +02:00
|
|
|
output->otmsStrikeoutPosition = height_to_LP( dc, output->otmsStrikeoutPosition);
|
|
|
|
output->otmsUnderscoreSize = height_to_LP( dc, output->otmsUnderscoreSize);
|
|
|
|
output->otmsUnderscorePosition = height_to_LP( dc, output->otmsUnderscorePosition);
|
2014-11-24 14:23:11 +01:00
|
|
|
|
2011-10-20 16:49:18 +02:00
|
|
|
if(output != lpOTM)
|
|
|
|
{
|
|
|
|
memcpy(lpOTM, output, cbData);
|
|
|
|
HeapFree(GetProcessHeap(), 0, output);
|
|
|
|
ret = cbData;
|
|
|
|
}
|
2001-09-12 22:21:06 +02:00
|
|
|
}
|
2008-02-05 21:16:27 +01:00
|
|
|
release_dc_ptr(dc);
|
2001-09-12 22:21:06 +02:00
|
|
|
return ret;
|
1998-12-10 16:49:22 +01:00
|
|
|
}
|
1998-10-14 20:15:43 +02:00
|
|
|
|
1996-12-22 19:27:48 +01:00
|
|
|
/***********************************************************************
|
2021-08-26 14:45:14 +02:00
|
|
|
* NtGdiGetCharWidthW (win32u.@)
|
Release 0.4.7
Mon Nov 1 14:40:21 1993 julliard@di.epfl.ch (Alexandre Julliard)
* [if1632/user.spec]
Removed some duplicate entries.
* [include/dialog.h] [windows/dialog.c]
Implemented dialog units and fonts.
Added preliminary loading of dialog resources.
Preliminary implementation of DialogBox().
Implemented Get/SetDlgItem* functions.
* [windows/win.c]
Implemented WM_PARENTNOTIFY message.
Implemented CreateWindowEx() and GetWindow().
Completed DestroyWindow().
Mon Nov 1 18:19:34 1993 Erik Bos
* [loader/signal.c]
Added support for int 0x11 & 0x12.
* [loader/int21.c]
Improved function handling.
Sun Oct 31 12:38:09 1993 David Metcalfe <david@prism.demon.co.uk>
* [objects/font.c]
Implemented GetCharWidth().
Wed Oct 27 09:56:06 1993 John Brezak <brezak@ch.hp.com>
* [Makefile]
Use GNU malloc.
* [include/int21.h include/wine.h]
Change sc_eflags to sc_efl .
* [include/wine.h]
Fix misplaced #endif
Include <signal.h> for NetBSD
* [loader/int21.c]
Don't include <sys/vfs.h> in NetBSD
Do include <sys/mount.h> in NetBSD
Cleanup some lint.
Mon Oct 26 17:59:01 1993 Erik Bos
* [include/int21.h]
Added.
* [loader/int21.c]
Added support for many dos ints.
* [misc/file.c] [include/files.h]
Moved OPEN_MAX and DosDriveStruct to files.h.
Sun Oct 24 13:36:50 1993 David Metcalfe <david@prism.demon.co.uk>
* [controls/button.c]
Implemented CHECKBOX, AUTOCHECKBOX, 3STATE, AUTO3STATE,
RADIOBUTTON, AUTORADIOBUTTON, GROUPBOX controls, together with
a preliminary USERBUTTON control.
* [objects/text.c]
Corrected bugs in TEXT_NextLine() and added handling of prefix
character.
* [controls/button.c]
Disabled focus handling by commenting out SetFocus() calls until
serious bug can be found.
Oct 20, 93 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
* [controls/listbox.c]
Listbox control window
Painting cleanup, new messages processed.
* [controls/scroll.c]
Scroll bar control window
Painting cleanup.
* [controls/combo.c]
Combo box control window
Painting cleanup.
Tue Oct 12 17:50:11 1993 julliard@di.epfl.ch (Alexandre Julliard)
* [objects/color.c] [objects/palette.c] [windows/syscolor.c]
Better support for the private color map.
Using a private map is now the default.
* [windows/win.c]
Bug fix.
* [include/dialog.h] [windows/dialog.c]
Implemented CreateDialog*() and IsDialogMessage().
* [misc/xt.c] [windows/defwnd.c]
Moved DefWindowProc() to defwnd.c.
Added WM_NCCREATE, WM_NCDESTROY and WM_CTLCOLOR handling.
* [windows/defdlg.c]
Started the implementation of DefDlgProc().
* [windows/win.c]
Added WM_NCCREATE and WM_NCDESTROY messages.
Implemented IsChild().
Tue Oct 12 17:50:20 1993 David Metcalfe <david@prism.demon.co.uk>
* [windows/focus.c]
Implemented GetFocus() and SetFocus().
* [windows/event.c]
Added processing of FocusIn and FocusOut events.
* [windows/graphics.c]
Added DrawFocusRect().
Sat Oct 9 14:36:57 1993 Erik Bos
* [loader/int1a.c]
Added more function handling.
Wed Oct 6 12:21:22 1993 Erik Bos
* [loader/signal.c]
Split signal.c into int1a.c, int21.c and signal.c.
Tue Oct 5 22:12:40 1993 David Metcalfe
* [controls/static.c] [control/widgets.c]
Static control class.
* [objects/text.c]
Added processing of additional DT_ flags to DrawText().
* [windows/win.c] [misc/xt.c]
Added SetWindowText() and WM_SETTEXT processing.
Tue Oct 5 22:12:40 1993 Martin Ayotte
* [controls/listbox.c]
Listbox control window
* [controls/scroll.c]
Scroll bar control window
* [controls/combo.c]
Combo box control window
* [include/combo.h]
Combo box definitions
* [include/listbox.h]
Listbox definitions
* [include/scroll.h]
Scroll bar definitions
Sat Oct 2 09:35:54 1993 Bob Amstadt (bob at pooh)
* [if1632/callback.c]
Fixed bug in MakeProcInstance().
* [debugger/info.c]
Changed x/w and x/b to display in hex.
* [debugger/i386-pinsn.c]
Added code to properly unassemble 16-bit indexing.
Fri Oct 1 08:29:05 1993 Bob Amstadt (bob at pooh)
* [loader/files.c] [misc/profile.c]
System initialization file is now called "wine.ini" and can
be located in the current directory, the user's home directory,
or any directories specified in the WINEPATH environment variable.
* [tools/build.c] [if1632/call.S] [include/regfunc.h]
Changed register function stack to match sigcontext structure.
Thu Sep 30 22:30:21 1993 Bob Amstadt (bob at pooh)
* [loader/files.c]
Created function to search a path for files to load.
* [loader/wine.c]
Modified exe and dll file loading to search through path
specified by the environment variable WINEPATH.
Thu Sep 30 22:30:21 1993 Eric Youngdale
* [loader/signal.c]
Bug fix.
Thu Sep 30 22:30:21 1993 John Brezak
* [debugger/dbg.y] [debugger/debug.l] [debugger/dtest.c]
[debugger/obstack.h]
Updates to allow debugger to function under NetBSD.
1993-11-03 20:23:37 +01:00
|
|
|
*/
|
2021-08-26 14:45:15 +02:00
|
|
|
BOOL WINAPI NtGdiGetCharWidthW( HDC hdc, UINT first, UINT last, WCHAR *chars,
|
2021-08-26 14:45:14 +02:00
|
|
|
ULONG flags, void *buf )
|
Release 0.4.7
Mon Nov 1 14:40:21 1993 julliard@di.epfl.ch (Alexandre Julliard)
* [if1632/user.spec]
Removed some duplicate entries.
* [include/dialog.h] [windows/dialog.c]
Implemented dialog units and fonts.
Added preliminary loading of dialog resources.
Preliminary implementation of DialogBox().
Implemented Get/SetDlgItem* functions.
* [windows/win.c]
Implemented WM_PARENTNOTIFY message.
Implemented CreateWindowEx() and GetWindow().
Completed DestroyWindow().
Mon Nov 1 18:19:34 1993 Erik Bos
* [loader/signal.c]
Added support for int 0x11 & 0x12.
* [loader/int21.c]
Improved function handling.
Sun Oct 31 12:38:09 1993 David Metcalfe <david@prism.demon.co.uk>
* [objects/font.c]
Implemented GetCharWidth().
Wed Oct 27 09:56:06 1993 John Brezak <brezak@ch.hp.com>
* [Makefile]
Use GNU malloc.
* [include/int21.h include/wine.h]
Change sc_eflags to sc_efl .
* [include/wine.h]
Fix misplaced #endif
Include <signal.h> for NetBSD
* [loader/int21.c]
Don't include <sys/vfs.h> in NetBSD
Do include <sys/mount.h> in NetBSD
Cleanup some lint.
Mon Oct 26 17:59:01 1993 Erik Bos
* [include/int21.h]
Added.
* [loader/int21.c]
Added support for many dos ints.
* [misc/file.c] [include/files.h]
Moved OPEN_MAX and DosDriveStruct to files.h.
Sun Oct 24 13:36:50 1993 David Metcalfe <david@prism.demon.co.uk>
* [controls/button.c]
Implemented CHECKBOX, AUTOCHECKBOX, 3STATE, AUTO3STATE,
RADIOBUTTON, AUTORADIOBUTTON, GROUPBOX controls, together with
a preliminary USERBUTTON control.
* [objects/text.c]
Corrected bugs in TEXT_NextLine() and added handling of prefix
character.
* [controls/button.c]
Disabled focus handling by commenting out SetFocus() calls until
serious bug can be found.
Oct 20, 93 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
* [controls/listbox.c]
Listbox control window
Painting cleanup, new messages processed.
* [controls/scroll.c]
Scroll bar control window
Painting cleanup.
* [controls/combo.c]
Combo box control window
Painting cleanup.
Tue Oct 12 17:50:11 1993 julliard@di.epfl.ch (Alexandre Julliard)
* [objects/color.c] [objects/palette.c] [windows/syscolor.c]
Better support for the private color map.
Using a private map is now the default.
* [windows/win.c]
Bug fix.
* [include/dialog.h] [windows/dialog.c]
Implemented CreateDialog*() and IsDialogMessage().
* [misc/xt.c] [windows/defwnd.c]
Moved DefWindowProc() to defwnd.c.
Added WM_NCCREATE, WM_NCDESTROY and WM_CTLCOLOR handling.
* [windows/defdlg.c]
Started the implementation of DefDlgProc().
* [windows/win.c]
Added WM_NCCREATE and WM_NCDESTROY messages.
Implemented IsChild().
Tue Oct 12 17:50:20 1993 David Metcalfe <david@prism.demon.co.uk>
* [windows/focus.c]
Implemented GetFocus() and SetFocus().
* [windows/event.c]
Added processing of FocusIn and FocusOut events.
* [windows/graphics.c]
Added DrawFocusRect().
Sat Oct 9 14:36:57 1993 Erik Bos
* [loader/int1a.c]
Added more function handling.
Wed Oct 6 12:21:22 1993 Erik Bos
* [loader/signal.c]
Split signal.c into int1a.c, int21.c and signal.c.
Tue Oct 5 22:12:40 1993 David Metcalfe
* [controls/static.c] [control/widgets.c]
Static control class.
* [objects/text.c]
Added processing of additional DT_ flags to DrawText().
* [windows/win.c] [misc/xt.c]
Added SetWindowText() and WM_SETTEXT processing.
Tue Oct 5 22:12:40 1993 Martin Ayotte
* [controls/listbox.c]
Listbox control window
* [controls/scroll.c]
Scroll bar control window
* [controls/combo.c]
Combo box control window
* [include/combo.h]
Combo box definitions
* [include/listbox.h]
Listbox definitions
* [include/scroll.h]
Scroll bar definitions
Sat Oct 2 09:35:54 1993 Bob Amstadt (bob at pooh)
* [if1632/callback.c]
Fixed bug in MakeProcInstance().
* [debugger/info.c]
Changed x/w and x/b to display in hex.
* [debugger/i386-pinsn.c]
Added code to properly unassemble 16-bit indexing.
Fri Oct 1 08:29:05 1993 Bob Amstadt (bob at pooh)
* [loader/files.c] [misc/profile.c]
System initialization file is now called "wine.ini" and can
be located in the current directory, the user's home directory,
or any directories specified in the WINEPATH environment variable.
* [tools/build.c] [if1632/call.S] [include/regfunc.h]
Changed register function stack to match sigcontext structure.
Thu Sep 30 22:30:21 1993 Bob Amstadt (bob at pooh)
* [loader/files.c]
Created function to search a path for files to load.
* [loader/wine.c]
Modified exe and dll file loading to search through path
specified by the environment variable WINEPATH.
Thu Sep 30 22:30:21 1993 Eric Youngdale
* [loader/signal.c]
Bug fix.
Thu Sep 30 22:30:21 1993 John Brezak
* [debugger/dbg.y] [debugger/debug.l] [debugger/dtest.c]
[debugger/obstack.h]
Updates to allow debugger to function under NetBSD.
1993-11-03 20:23:37 +01:00
|
|
|
{
|
2021-08-26 14:45:15 +02:00
|
|
|
UINT i, count = last;
|
2011-03-15 20:42:49 +01:00
|
|
|
BOOL ret;
|
2011-10-19 13:38:10 +02:00
|
|
|
PHYSDEV dev;
|
2021-08-26 14:45:18 +02:00
|
|
|
DC *dc;
|
2011-10-19 13:38:10 +02:00
|
|
|
|
2021-08-26 14:45:18 +02:00
|
|
|
if (flags & NTGDI_GETCHARWIDTH_INDICES)
|
|
|
|
{
|
|
|
|
ABC *abc;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
|
|
|
|
return FALSE;
|
|
|
|
|
2021-08-27 14:51:50 +02:00
|
|
|
if (!NtGdiGetCharABCWidthsW( hdc, first, last, chars,
|
|
|
|
NTGDI_GETCHARABCWIDTHS_INT | NTGDI_GETCHARABCWIDTHS_INDICES,
|
|
|
|
abc ))
|
2021-08-26 14:45:18 +02:00
|
|
|
{
|
|
|
|
HeapFree( GetProcessHeap(), 0, abc );
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
((INT *)buf)[i] = abc[i].abcA + abc[i].abcB + abc[i].abcC;
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, abc);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(dc = get_dc_ptr( hdc ))) return FALSE;
|
1997-06-29 20:08:02 +02:00
|
|
|
|
2021-08-26 14:45:15 +02:00
|
|
|
if (!chars) count = last - first + 1;
|
2011-10-19 13:38:10 +02:00
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
|
2021-08-26 14:45:15 +02:00
|
|
|
ret = dev->funcs->pGetCharWidth( dev, first, count, chars, buf );
|
2001-09-12 22:21:06 +02:00
|
|
|
|
|
|
|
if (ret)
|
2000-08-19 23:38:55 +02:00
|
|
|
{
|
2021-08-26 14:45:16 +02:00
|
|
|
if (flags & NTGDI_GETCHARWIDTH_INT)
|
|
|
|
{
|
|
|
|
INT *buffer = buf;
|
|
|
|
/* convert device units to logical */
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
buffer[i] = width_to_LP( dc, buffer[i] );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
float scale = fabs( dc->xformVport2World.eM11 ) / 16.0f;
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
((float *)buf)[i] = ((int *)buf)[i] * scale;
|
|
|
|
}
|
2000-08-19 23:38:55 +02:00
|
|
|
}
|
2008-02-05 21:16:27 +01:00
|
|
|
release_dc_ptr( dc );
|
2000-08-19 23:38:55 +02:00
|
|
|
return ret;
|
Release 0.4.7
Mon Nov 1 14:40:21 1993 julliard@di.epfl.ch (Alexandre Julliard)
* [if1632/user.spec]
Removed some duplicate entries.
* [include/dialog.h] [windows/dialog.c]
Implemented dialog units and fonts.
Added preliminary loading of dialog resources.
Preliminary implementation of DialogBox().
Implemented Get/SetDlgItem* functions.
* [windows/win.c]
Implemented WM_PARENTNOTIFY message.
Implemented CreateWindowEx() and GetWindow().
Completed DestroyWindow().
Mon Nov 1 18:19:34 1993 Erik Bos
* [loader/signal.c]
Added support for int 0x11 & 0x12.
* [loader/int21.c]
Improved function handling.
Sun Oct 31 12:38:09 1993 David Metcalfe <david@prism.demon.co.uk>
* [objects/font.c]
Implemented GetCharWidth().
Wed Oct 27 09:56:06 1993 John Brezak <brezak@ch.hp.com>
* [Makefile]
Use GNU malloc.
* [include/int21.h include/wine.h]
Change sc_eflags to sc_efl .
* [include/wine.h]
Fix misplaced #endif
Include <signal.h> for NetBSD
* [loader/int21.c]
Don't include <sys/vfs.h> in NetBSD
Do include <sys/mount.h> in NetBSD
Cleanup some lint.
Mon Oct 26 17:59:01 1993 Erik Bos
* [include/int21.h]
Added.
* [loader/int21.c]
Added support for many dos ints.
* [misc/file.c] [include/files.h]
Moved OPEN_MAX and DosDriveStruct to files.h.
Sun Oct 24 13:36:50 1993 David Metcalfe <david@prism.demon.co.uk>
* [controls/button.c]
Implemented CHECKBOX, AUTOCHECKBOX, 3STATE, AUTO3STATE,
RADIOBUTTON, AUTORADIOBUTTON, GROUPBOX controls, together with
a preliminary USERBUTTON control.
* [objects/text.c]
Corrected bugs in TEXT_NextLine() and added handling of prefix
character.
* [controls/button.c]
Disabled focus handling by commenting out SetFocus() calls until
serious bug can be found.
Oct 20, 93 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
* [controls/listbox.c]
Listbox control window
Painting cleanup, new messages processed.
* [controls/scroll.c]
Scroll bar control window
Painting cleanup.
* [controls/combo.c]
Combo box control window
Painting cleanup.
Tue Oct 12 17:50:11 1993 julliard@di.epfl.ch (Alexandre Julliard)
* [objects/color.c] [objects/palette.c] [windows/syscolor.c]
Better support for the private color map.
Using a private map is now the default.
* [windows/win.c]
Bug fix.
* [include/dialog.h] [windows/dialog.c]
Implemented CreateDialog*() and IsDialogMessage().
* [misc/xt.c] [windows/defwnd.c]
Moved DefWindowProc() to defwnd.c.
Added WM_NCCREATE, WM_NCDESTROY and WM_CTLCOLOR handling.
* [windows/defdlg.c]
Started the implementation of DefDlgProc().
* [windows/win.c]
Added WM_NCCREATE and WM_NCDESTROY messages.
Implemented IsChild().
Tue Oct 12 17:50:20 1993 David Metcalfe <david@prism.demon.co.uk>
* [windows/focus.c]
Implemented GetFocus() and SetFocus().
* [windows/event.c]
Added processing of FocusIn and FocusOut events.
* [windows/graphics.c]
Added DrawFocusRect().
Sat Oct 9 14:36:57 1993 Erik Bos
* [loader/int1a.c]
Added more function handling.
Wed Oct 6 12:21:22 1993 Erik Bos
* [loader/signal.c]
Split signal.c into int1a.c, int21.c and signal.c.
Tue Oct 5 22:12:40 1993 David Metcalfe
* [controls/static.c] [control/widgets.c]
Static control class.
* [objects/text.c]
Added processing of additional DT_ flags to DrawText().
* [windows/win.c] [misc/xt.c]
Added SetWindowText() and WM_SETTEXT processing.
Tue Oct 5 22:12:40 1993 Martin Ayotte
* [controls/listbox.c]
Listbox control window
* [controls/scroll.c]
Scroll bar control window
* [controls/combo.c]
Combo box control window
* [include/combo.h]
Combo box definitions
* [include/listbox.h]
Listbox definitions
* [include/scroll.h]
Scroll bar definitions
Sat Oct 2 09:35:54 1993 Bob Amstadt (bob at pooh)
* [if1632/callback.c]
Fixed bug in MakeProcInstance().
* [debugger/info.c]
Changed x/w and x/b to display in hex.
* [debugger/i386-pinsn.c]
Added code to properly unassemble 16-bit indexing.
Fri Oct 1 08:29:05 1993 Bob Amstadt (bob at pooh)
* [loader/files.c] [misc/profile.c]
System initialization file is now called "wine.ini" and can
be located in the current directory, the user's home directory,
or any directories specified in the WINEPATH environment variable.
* [tools/build.c] [if1632/call.S] [include/regfunc.h]
Changed register function stack to match sigcontext structure.
Thu Sep 30 22:30:21 1993 Bob Amstadt (bob at pooh)
* [loader/files.c]
Created function to search a path for files to load.
* [loader/wine.c]
Modified exe and dll file loading to search through path
specified by the environment variable WINEPATH.
Thu Sep 30 22:30:21 1993 Eric Youngdale
* [loader/signal.c]
Bug fix.
Thu Sep 30 22:30:21 1993 John Brezak
* [debugger/dbg.y] [debugger/debug.l] [debugger/dtest.c]
[debugger/obstack.h]
Updates to allow debugger to function under NetBSD.
1993-11-03 20:23:37 +01:00
|
|
|
}
|
Release 940420
Wed Apr 20 14:53:35 1994 Bob Amstadt (bob@pooh)
* [tools/build.c] [if1632/call.S] [if1632/Imakefile]
Fixed bug for non-Linux systems.
Apr 18, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
* [windows/win.c]
Bug fixed in CreateWindowEx() : Now use SetMenu() for menubar setup.
New empty stub for function SetSysModalWindow().
* [misc/exec.c]
New empty stub for function ExitWindows().
* [objects/font.c]
New empty stub for function EnumFonts().
* New file [misc/property.c]
New functions RemoveProp(), GetProp(), SetProp() & EnumProps().
* New file [misc/shell.c]
New empty stubs for function RegisterShellProc(),
ShellExecute() & ShellProc().
* New files [loader/task.c] & [include/task.h]
Move functions GetWindowTask(), GetNumTask(), EnumTaskWindows()
from 'loader/library.c'.
* [if1632/user.c] [if1632/kernel.c]
Put Atoms functions entries.
* [controls/combo.c]
New functions DirDlgSelectComboBox() & DirDlgListComboBox().
* [controls/listbox.c]
New functions DirDlgSelect() & DirDlgList().
Sun Apr 17 20:57:59 1994 Erik Bos (erik@trashcan.hacktic.nl)
* [objects/test.c]
GrayString() added.
* [if1632/callback.c]
CallGrayStringProc() added.
* [if1632/relay.c] [if1632/mmsystem.spec]
Added.
* [if1632/kernel.spec] [if1632/user.spec]
Added forgotten specs for atom functions.
Tue Apr 12 00:05:31 1994 Bob Amstadt (bob@pooh)
* misc/spy.c (SpyInit): Added more message types
* [windows/mdi.c] [include/mdi.h]
Maximizing and restoring child windows.
Tiling of child windows.
Mon Apr 11 20:48:28 1994 Alexandre Julliard (julliard@lamisun.epfl.ch)
* [windows/winpos.c]
Revert focus and activation to previous window when hiding a window.
* [windows/syscolor.c]
Implemented system color objects (brushes and pens created at
SetSysColor() time for better performance).
* [windows/graphics.c] [windows/nonclient.c] [controls/button.c]
Changed painting code to use system color objects.
* [windows/message.c]
New function MSG_InternalGetMessage() for internal messages
loops (e.g. for dialogs or menus).
* [windows/hook.c] [include/hook.h] (New files)
Beginning of the window hooks implementation.
* [windows/dialog.c]
Use new function MSG_InternalGetMessage() in DialogBox().
* [if1632/callback.c]
Added function CallHookProc().
Apr 11, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
* [windows/event.c]
Bug fix : WM_CHARs are sent to focused window like WM_KEY???.
* [misc/exec.c]
Nothing much more than a stub for LoadModule(), I saw there a lot
to be done in that corner, I will come back later ...
* [loader/library.c]
New functions GetWindowTask(), GetNumTask(), EnumTaskWindows()
and associated modules & tasks linked-lists.
(it's only an 'emerging bud', more to come next weeks).
* [loader/wine.c]
Use LoadLibrary() instead of LoadImage() for 'sysres.dll'.
* [control/menu.c]
You can now click outside menu region without problem.
Keyboard navig more smootly, even if a child has the focus.
Bug fix in InsertItem(), (bad linklist when insert point not found).
change Realloc for Free & Alloc in ModifyItem().
MF_STRING now set BLACK_PEN to fix bug of bad color of the underscores
done by DrawText(), (maybe it should done in DrawText() itself ?).
Sun Apr 10 14:06:08 1994 Erik Bos (erik@trashcan.hacktic.nl)
* [misc/profile.c]
.INI files will now be stored in / loaded from the windows dir
if no path is supplied.
* [if1632/kernel.spec]
Fixed GetDriveType's prototype.
* [if1632/winsock.spec] [include/winsock.h] [misc/winsocket.c]
Fixed prototypes: winsock uses a word as socket handle not an int.
* [misc/winsocket.c]
Added heap allocation for returned structures.
Added non-blocking WSAAsyncGetXbyY() functions as blocking ones.
* [loader/wine.c]
Added IsDLLLoaded(), used in LoadImage() to prevent loading
a dll multiple times.
Directory is added to wine's path when a fullpath is supplied when
starting wine.
LoadImage(): DLL filename used instead DLL's own internal name,
fixes 'Bad DLL name' errors.
Sat Apr 9 08:26:03 1994 David Metcalfe <david@prism.demon.co.uk>
* [controls/edit.c] [controls/widgets.c]
First release of edit control.
1994-04-21 03:20:00 +02:00
|
|
|
|
1994-11-07 19:20:42 +01:00
|
|
|
|
2011-11-17 11:57:53 +01:00
|
|
|
/* helper for nulldrv_ExtTextOut */
|
2012-12-05 16:41:08 +01:00
|
|
|
static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT flags, UINT aa_flags,
|
2011-11-17 11:57:53 +01:00
|
|
|
GLYPHMETRICS *metrics, struct gdi_image_bits *image )
|
|
|
|
{
|
|
|
|
UINT indices[3] = {0, 0, 0x20};
|
2013-01-20 00:12:49 +01:00
|
|
|
unsigned int i;
|
2011-11-17 11:57:53 +01:00
|
|
|
DWORD ret, size;
|
|
|
|
int stride;
|
|
|
|
|
|
|
|
indices[0] = index;
|
2012-12-05 16:41:08 +01:00
|
|
|
if (flags & ETO_GLYPH_INDEX) aa_flags |= GGO_GLYPH_INDEX;
|
2011-11-17 11:57:53 +01:00
|
|
|
|
2018-10-05 21:35:35 +02:00
|
|
|
for (i = 0; i < ARRAY_SIZE( indices ); i++)
|
2011-11-17 11:57:53 +01:00
|
|
|
{
|
2011-11-24 10:26:45 +01:00
|
|
|
index = indices[i];
|
2021-09-10 14:28:30 +02:00
|
|
|
ret = NtGdiGetGlyphOutline( hdc, index, aa_flags, metrics, 0, NULL, &identity, FALSE );
|
2011-11-17 11:57:53 +01:00
|
|
|
if (ret != GDI_ERROR) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret == GDI_ERROR) return ERROR_NOT_FOUND;
|
|
|
|
if (!image) return ERROR_SUCCESS;
|
|
|
|
|
|
|
|
image->ptr = NULL;
|
|
|
|
image->free = NULL;
|
2013-09-19 17:57:53 +02:00
|
|
|
if (!ret) /* empty glyph */
|
|
|
|
{
|
|
|
|
metrics->gmBlackBoxX = metrics->gmBlackBoxY = 0;
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
2011-11-17 11:57:53 +01:00
|
|
|
|
|
|
|
stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
|
|
|
|
size = metrics->gmBlackBoxY * stride;
|
|
|
|
|
|
|
|
if (!(image->ptr = HeapAlloc( GetProcessHeap(), 0, size ))) return ERROR_OUTOFMEMORY;
|
|
|
|
image->is_copy = TRUE;
|
|
|
|
image->free = free_heap_bits;
|
|
|
|
|
2021-09-10 14:28:30 +02:00
|
|
|
ret = NtGdiGetGlyphOutline( hdc, index, aa_flags, metrics, size, image->ptr,
|
|
|
|
&identity, FALSE );
|
2011-11-17 11:57:53 +01:00
|
|
|
if (ret == GDI_ERROR)
|
|
|
|
{
|
|
|
|
HeapFree( GetProcessHeap(), 0, image->ptr );
|
|
|
|
return ERROR_NOT_FOUND;
|
|
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2011-11-17 16:55:16 +01:00
|
|
|
/* helper for nulldrv_ExtTextOut */
|
|
|
|
static RECT get_total_extents( HDC hdc, INT x, INT y, UINT flags, UINT aa_flags,
|
|
|
|
LPCWSTR str, UINT count, const INT *dx )
|
|
|
|
{
|
2013-01-20 00:12:49 +01:00
|
|
|
UINT i;
|
2012-04-10 16:04:39 +02:00
|
|
|
RECT rect, bounds;
|
2011-11-17 16:55:16 +01:00
|
|
|
|
2012-04-10 16:04:39 +02:00
|
|
|
reset_bounds( &bounds );
|
2011-11-17 16:55:16 +01:00
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
GLYPHMETRICS metrics;
|
|
|
|
|
2012-12-05 16:41:08 +01:00
|
|
|
if (get_glyph_bitmap( hdc, str[i], flags, aa_flags, &metrics, NULL )) continue;
|
2011-11-17 16:55:16 +01:00
|
|
|
|
2012-04-10 16:04:39 +02:00
|
|
|
rect.left = x + metrics.gmptGlyphOrigin.x;
|
|
|
|
rect.top = y - metrics.gmptGlyphOrigin.y;
|
|
|
|
rect.right = rect.left + metrics.gmBlackBoxX;
|
|
|
|
rect.bottom = rect.top + metrics.gmBlackBoxY;
|
|
|
|
add_bounds_rect( &bounds, &rect );
|
2011-11-17 16:55:16 +01:00
|
|
|
|
|
|
|
if (dx)
|
|
|
|
{
|
|
|
|
if (flags & ETO_PDY)
|
|
|
|
{
|
|
|
|
x += dx[ i * 2 ];
|
|
|
|
y += dx[ i * 2 + 1];
|
|
|
|
}
|
|
|
|
else x += dx[ i ];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x += metrics.gmCellIncX;
|
|
|
|
y += metrics.gmCellIncY;
|
|
|
|
}
|
|
|
|
}
|
2012-04-10 16:04:39 +02:00
|
|
|
return bounds;
|
2011-11-17 16:55:16 +01:00
|
|
|
}
|
|
|
|
|
2011-11-17 11:57:53 +01:00
|
|
|
/* helper for nulldrv_ExtTextOut */
|
2016-07-29 16:09:32 +02:00
|
|
|
static void draw_glyph( DC *dc, INT origin_x, INT origin_y, const GLYPHMETRICS *metrics,
|
2011-11-17 11:57:53 +01:00
|
|
|
const struct gdi_image_bits *image, const RECT *clip )
|
|
|
|
{
|
|
|
|
static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
|
2013-01-20 00:12:49 +01:00
|
|
|
UINT i, count, max_count;
|
|
|
|
LONG x, y;
|
2011-11-17 11:57:53 +01:00
|
|
|
BYTE *ptr = image->ptr;
|
|
|
|
int stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
|
|
|
|
POINT *pts;
|
|
|
|
RECT rect, clipped_rect;
|
|
|
|
|
|
|
|
rect.left = origin_x + metrics->gmptGlyphOrigin.x;
|
|
|
|
rect.top = origin_y - metrics->gmptGlyphOrigin.y;
|
|
|
|
rect.right = rect.left + metrics->gmBlackBoxX;
|
|
|
|
rect.bottom = rect.top + metrics->gmBlackBoxY;
|
|
|
|
if (!clip) clipped_rect = rect;
|
|
|
|
else if (!intersect_rect( &clipped_rect, &rect, clip )) return;
|
|
|
|
|
2012-07-02 10:58:23 +02:00
|
|
|
max_count = (metrics->gmBlackBoxX + 1) * metrics->gmBlackBoxY;
|
|
|
|
pts = HeapAlloc( GetProcessHeap(), 0, max_count * sizeof(*pts) );
|
2011-11-17 11:57:53 +01:00
|
|
|
if (!pts) return;
|
|
|
|
|
|
|
|
count = 0;
|
|
|
|
ptr += (clipped_rect.top - rect.top) * stride;
|
|
|
|
for (y = clipped_rect.top; y < clipped_rect.bottom; y++, ptr += stride)
|
|
|
|
{
|
|
|
|
for (x = clipped_rect.left - rect.left; x < clipped_rect.right - rect.left; x++)
|
|
|
|
{
|
|
|
|
while (x < clipped_rect.right - rect.left && !(ptr[x / 8] & masks[x % 8])) x++;
|
|
|
|
pts[count].x = rect.left + x;
|
|
|
|
while (x < clipped_rect.right - rect.left && (ptr[x / 8] & masks[x % 8])) x++;
|
|
|
|
pts[count + 1].x = rect.left + x;
|
|
|
|
if (pts[count + 1].x > pts[count].x)
|
|
|
|
{
|
|
|
|
pts[count].y = pts[count + 1].y = y;
|
|
|
|
count += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-07-02 10:58:23 +02:00
|
|
|
assert( count <= max_count );
|
2016-07-29 16:09:32 +02:00
|
|
|
dp_to_lp( dc, pts, count );
|
2021-09-10 14:28:30 +02:00
|
|
|
for (i = 0; i < count; i += 2)
|
|
|
|
{
|
|
|
|
const UINT pts_count = 2;
|
|
|
|
NtGdiPolyPolyDraw( dc->hSelf, pts + i, &pts_count, 1, NtGdiPolyPolyline );
|
|
|
|
}
|
2011-11-17 11:57:53 +01:00
|
|
|
HeapFree( GetProcessHeap(), 0, pts );
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* nulldrv_ExtTextOut
|
|
|
|
*/
|
2019-07-06 20:45:50 +02:00
|
|
|
BOOL CDECL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect,
|
|
|
|
LPCWSTR str, UINT count, const INT *dx )
|
2011-11-17 11:57:53 +01:00
|
|
|
{
|
2011-11-17 16:55:16 +01:00
|
|
|
DC *dc = get_nulldrv_dc( dev );
|
2012-10-31 15:55:29 +01:00
|
|
|
UINT i;
|
2011-11-17 11:57:53 +01:00
|
|
|
DWORD err;
|
|
|
|
HGDIOBJ orig;
|
|
|
|
HPEN pen;
|
|
|
|
|
|
|
|
if (flags & ETO_OPAQUE)
|
|
|
|
{
|
|
|
|
RECT rc = *rect;
|
2021-09-10 14:28:30 +02:00
|
|
|
COLORREF brush_color = NtGdiGetNearestColor( dev->hdc, dc->attr->background_color );
|
|
|
|
HBRUSH brush = NtGdiCreateSolidBrush( brush_color, NULL);
|
2011-11-17 11:57:53 +01:00
|
|
|
|
|
|
|
if (brush)
|
|
|
|
{
|
2021-07-02 12:41:27 +02:00
|
|
|
orig = NtGdiSelectBrush( dev->hdc, brush );
|
2016-07-29 16:09:32 +02:00
|
|
|
dp_to_lp( dc, (POINT *)&rc, 2 );
|
2021-08-03 12:56:49 +02:00
|
|
|
NtGdiPatBlt( dev->hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY );
|
2021-07-02 12:41:27 +02:00
|
|
|
NtGdiSelectBrush( dev->hdc, orig );
|
2021-09-03 14:59:52 +02:00
|
|
|
NtGdiDeleteObjectApp( brush );
|
2011-11-17 11:57:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!count) return TRUE;
|
|
|
|
|
2012-10-31 15:55:29 +01:00
|
|
|
if (dc->aa_flags != GGO_BITMAP)
|
2011-11-17 16:55:16 +01:00
|
|
|
{
|
|
|
|
char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
|
|
|
|
BITMAPINFO *info = (BITMAPINFO *)buffer;
|
|
|
|
struct gdi_image_bits bits;
|
|
|
|
struct bitblt_coords src, dst;
|
|
|
|
PHYSDEV dst_dev;
|
2012-10-30 14:22:16 +01:00
|
|
|
/* FIXME Subpixel modes */
|
2012-10-31 15:55:29 +01:00
|
|
|
UINT aa_flags = GGO_GRAY4_BITMAP;
|
2012-10-30 14:22:16 +01:00
|
|
|
|
2011-11-17 16:55:16 +01:00
|
|
|
dst_dev = GET_DC_PHYSDEV( dc, pPutImage );
|
|
|
|
src.visrect = get_total_extents( dev->hdc, x, y, flags, aa_flags, str, count, dx );
|
|
|
|
if (flags & ETO_CLIPPED) intersect_rect( &src.visrect, &src.visrect, rect );
|
2011-12-06 12:57:30 +01:00
|
|
|
if (!clip_visrect( dc, &src.visrect, &src.visrect )) return TRUE;
|
2011-11-17 16:55:16 +01:00
|
|
|
|
|
|
|
/* FIXME: check for ETO_OPAQUE and avoid GetImage */
|
|
|
|
src.x = src.visrect.left;
|
|
|
|
src.y = src.visrect.top;
|
|
|
|
src.width = src.visrect.right - src.visrect.left;
|
|
|
|
src.height = src.visrect.bottom - src.visrect.top;
|
|
|
|
dst = src;
|
|
|
|
if ((flags & ETO_OPAQUE) && (src.visrect.left >= rect->left) && (src.visrect.top >= rect->top) &&
|
|
|
|
(src.visrect.right <= rect->right) && (src.visrect.bottom <= rect->bottom))
|
|
|
|
{
|
|
|
|
/* we can avoid the GetImage, just query the needed format */
|
|
|
|
memset( &info->bmiHeader, 0, sizeof(info->bmiHeader) );
|
|
|
|
info->bmiHeader.biSize = sizeof(info->bmiHeader);
|
|
|
|
info->bmiHeader.biWidth = src.width;
|
|
|
|
info->bmiHeader.biHeight = -src.height;
|
2017-02-13 15:07:59 +01:00
|
|
|
info->bmiHeader.biSizeImage = get_dib_image_size( info );
|
2012-05-23 23:36:20 +02:00
|
|
|
err = dst_dev->funcs->pPutImage( dst_dev, 0, info, NULL, NULL, NULL, 0 );
|
2011-11-17 16:55:16 +01:00
|
|
|
if (!err || err == ERROR_BAD_FORMAT)
|
|
|
|
{
|
|
|
|
/* make the source rectangle relative to the source bits */
|
|
|
|
src.x = src.y = 0;
|
|
|
|
src.visrect.left = src.visrect.top = 0;
|
|
|
|
src.visrect.right = src.width;
|
|
|
|
src.visrect.bottom = src.height;
|
|
|
|
|
2017-02-13 15:07:59 +01:00
|
|
|
bits.ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage );
|
2011-11-17 16:55:16 +01:00
|
|
|
if (!bits.ptr) return ERROR_OUTOFMEMORY;
|
|
|
|
bits.is_copy = TRUE;
|
|
|
|
bits.free = free_heap_bits;
|
|
|
|
err = ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PHYSDEV src_dev = GET_DC_PHYSDEV( dc, pGetImage );
|
2012-05-23 23:36:20 +02:00
|
|
|
err = src_dev->funcs->pGetImage( src_dev, info, &bits, &src );
|
2011-11-17 16:55:16 +01:00
|
|
|
if (!err && !bits.is_copy)
|
|
|
|
{
|
2017-02-13 15:07:59 +01:00
|
|
|
void *ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage );
|
2011-11-17 16:55:16 +01:00
|
|
|
if (!ptr)
|
|
|
|
{
|
|
|
|
if (bits.free) bits.free( &bits );
|
|
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
}
|
2017-02-13 15:07:59 +01:00
|
|
|
memcpy( ptr, bits.ptr, info->bmiHeader.biSizeImage );
|
2011-11-17 16:55:16 +01:00
|
|
|
if (bits.free) bits.free( &bits );
|
|
|
|
bits.ptr = ptr;
|
|
|
|
bits.is_copy = TRUE;
|
|
|
|
bits.free = free_heap_bits;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!err)
|
|
|
|
{
|
|
|
|
/* make x,y relative to the image bits */
|
|
|
|
x += src.visrect.left - dst.visrect.left;
|
|
|
|
y += src.visrect.top - dst.visrect.top;
|
2016-07-28 11:49:47 +02:00
|
|
|
render_aa_text_bitmapinfo( dc, info, &bits, &src, x, y, flags,
|
2011-11-17 16:55:16 +01:00
|
|
|
aa_flags, str, count, dx );
|
2012-05-23 23:36:20 +02:00
|
|
|
err = dst_dev->funcs->pPutImage( dst_dev, 0, info, &bits, &src, &dst, SRCCOPY );
|
2011-11-17 16:55:16 +01:00
|
|
|
if (bits.free) bits.free( &bits );
|
|
|
|
return !err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-10 14:28:30 +02:00
|
|
|
pen = NtGdiCreatePen( PS_SOLID, 1, dc->attr->text_color, NULL );
|
2021-07-02 12:41:27 +02:00
|
|
|
orig = NtGdiSelectPen( dev->hdc, pen );
|
2011-11-17 11:57:53 +01:00
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
GLYPHMETRICS metrics;
|
|
|
|
struct gdi_image_bits image;
|
|
|
|
|
2012-12-05 16:41:08 +01:00
|
|
|
err = get_glyph_bitmap( dev->hdc, str[i], flags, GGO_BITMAP, &metrics, &image );
|
2011-11-17 11:57:53 +01:00
|
|
|
if (err) continue;
|
|
|
|
|
2016-07-29 16:09:32 +02:00
|
|
|
if (image.ptr) draw_glyph( dc, x, y, &metrics, &image, (flags & ETO_CLIPPED) ? rect : NULL );
|
2011-11-17 11:57:53 +01:00
|
|
|
if (image.free) image.free( &image );
|
|
|
|
|
|
|
|
if (dx)
|
|
|
|
{
|
|
|
|
if (flags & ETO_PDY)
|
|
|
|
{
|
|
|
|
x += dx[ i * 2 ];
|
|
|
|
y += dx[ i * 2 + 1];
|
|
|
|
}
|
|
|
|
else x += dx[ i ];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x += metrics.gmCellIncX;
|
|
|
|
y += metrics.gmCellIncY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-02 12:41:27 +02:00
|
|
|
NtGdiSelectPen( dev->hdc, orig );
|
2021-09-03 14:59:52 +02:00
|
|
|
NtGdiDeleteObjectApp( pen );
|
2011-11-17 11:57:53 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2015-05-19 09:58:24 +02:00
|
|
|
/***********************************************************************
|
|
|
|
* get_line_width
|
|
|
|
*
|
|
|
|
* Scale the underline / strikeout line width.
|
|
|
|
*/
|
|
|
|
static inline int get_line_width( DC *dc, int metric_size )
|
|
|
|
{
|
|
|
|
int width = abs( INTERNAL_YWSTODS( dc, metric_size ));
|
|
|
|
if (width == 0) width = 1;
|
|
|
|
if (metric_size < 0) width = -width;
|
|
|
|
return width;
|
|
|
|
}
|
2004-07-21 06:07:28 +02:00
|
|
|
|
|
|
|
/***********************************************************************
|
2021-07-23 10:49:42 +02:00
|
|
|
* NtGdiExtTextOutW (win32u.@)
|
2005-01-05 14:24:52 +01:00
|
|
|
*
|
|
|
|
* Draws text using the currently selected font, background color, and text color.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* PARAMS
|
|
|
|
* x,y [I] coordinates of string
|
|
|
|
* flags [I]
|
|
|
|
* ETO_GRAYED - undocumented on MSDN
|
|
|
|
* ETO_OPAQUE - use background color for fill the rectangle
|
|
|
|
* ETO_CLIPPED - clipping text to the rectangle
|
|
|
|
* ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
|
|
|
|
* than encoded characters. Implies ETO_IGNORELANGUAGE
|
|
|
|
* ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
|
|
|
|
* Affects BiDi ordering
|
|
|
|
* ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
|
|
|
|
* ETO_PDY - unimplemented
|
|
|
|
* ETO_NUMERICSLATIN - unimplemented always assumed -
|
|
|
|
* do not translate numbers into locale representations
|
|
|
|
* ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
|
|
|
|
* lprect [I] dimensions for clipping or/and opaquing
|
|
|
|
* str [I] text string
|
|
|
|
* count [I] number of symbols in string
|
|
|
|
* lpDx [I] optional parameter with distance between drawing characters
|
|
|
|
*
|
|
|
|
* RETURNS
|
|
|
|
* Success: TRUE
|
|
|
|
* Failure: FALSE
|
2004-07-21 06:07:28 +02:00
|
|
|
*/
|
2021-07-23 10:49:42 +02:00
|
|
|
BOOL WINAPI NtGdiExtTextOutW( HDC hdc, INT x, INT y, UINT flags, const RECT *lprect,
|
|
|
|
const WCHAR *str, UINT count, const INT *lpDx, DWORD cp )
|
2004-07-21 06:07:28 +02:00
|
|
|
{
|
|
|
|
BOOL ret = FALSE;
|
2016-07-29 16:09:35 +02:00
|
|
|
UINT align;
|
|
|
|
DWORD layout;
|
2005-08-23 11:38:58 +02:00
|
|
|
POINT pt;
|
|
|
|
TEXTMETRICW tm;
|
|
|
|
LOGFONTW lf;
|
|
|
|
double cosEsc, sinEsc;
|
2010-05-06 15:05:39 +02:00
|
|
|
INT char_extra;
|
2005-08-23 11:38:58 +02:00
|
|
|
SIZE sz;
|
|
|
|
RECT rc;
|
2010-05-06 15:05:39 +02:00
|
|
|
POINT *deltas = NULL, width = {0, 0};
|
2007-09-17 16:49:37 +02:00
|
|
|
DC * dc = get_dc_ptr( hdc );
|
2011-03-15 20:42:49 +01:00
|
|
|
PHYSDEV physdev;
|
2007-02-08 16:12:08 +01:00
|
|
|
INT breakRem;
|
2008-10-17 02:09:56 +02:00
|
|
|
static int quietfixme = 0;
|
2005-08-23 11:38:58 +02:00
|
|
|
|
|
|
|
if (!dc) return FALSE;
|
2021-02-03 14:36:09 +01:00
|
|
|
if (count > INT_MAX) return FALSE;
|
2005-08-23 11:38:58 +02:00
|
|
|
|
2021-07-23 10:49:19 +02:00
|
|
|
align = dc->attr->text_align;
|
2007-02-08 16:12:08 +01:00
|
|
|
breakRem = dc->breakRem;
|
2021-07-28 11:39:26 +02:00
|
|
|
layout = dc->attr->layout;
|
2007-02-08 16:12:08 +01:00
|
|
|
|
2010-05-06 15:05:39 +02:00
|
|
|
if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
|
2008-10-17 02:09:56 +02:00
|
|
|
{
|
2010-05-06 15:05:39 +02:00
|
|
|
FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
|
2008-10-17 02:09:56 +02:00
|
|
|
quietfixme = 1;
|
|
|
|
}
|
2005-08-23 11:38:58 +02:00
|
|
|
|
2007-09-17 16:49:37 +02:00
|
|
|
update_dc( dc );
|
2011-03-15 20:42:49 +01:00
|
|
|
physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
|
2006-06-06 05:42:45 +02:00
|
|
|
|
2010-07-29 13:37:20 +02:00
|
|
|
if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
|
|
|
|
if (layout & LAYOUT_RTL)
|
|
|
|
{
|
|
|
|
if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
|
|
|
|
align ^= TA_RTLREADING;
|
|
|
|
}
|
|
|
|
|
2010-07-28 23:15:01 +02:00
|
|
|
TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
|
|
|
|
wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
|
2021-07-29 14:22:04 +02:00
|
|
|
TRACE("align = %x bkmode = %x mapmode = %x\n", align, dc->attr->background_mode,
|
|
|
|
dc->attr->map_mode);
|
2005-08-23 11:38:58 +02:00
|
|
|
|
|
|
|
if(align & TA_UPDATECP)
|
|
|
|
{
|
2021-07-17 17:01:49 +02:00
|
|
|
pt = dc->attr->cur_pos;
|
2005-08-23 11:38:58 +02:00
|
|
|
x = pt.x;
|
|
|
|
y = pt.y;
|
|
|
|
}
|
|
|
|
|
2021-09-10 14:28:30 +02:00
|
|
|
NtGdiGetTextMetricsW( hdc, &tm, 0 );
|
|
|
|
NtGdiExtGetObjectW( dc->hFont, sizeof(lf), &lf );
|
2005-08-23 11:38:58 +02:00
|
|
|
|
|
|
|
if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
|
|
|
|
lf.lfEscapement = 0;
|
|
|
|
|
2021-07-20 09:19:14 +02:00
|
|
|
if ((dc->attr->graphics_mode == GM_COMPATIBLE) &&
|
2011-02-25 13:19:55 +01:00
|
|
|
(dc->vport2WorldValid && dc->xformWorld2Vport.eM11 * dc->xformWorld2Vport.eM22 < 0))
|
|
|
|
{
|
|
|
|
lf.lfEscapement = -lf.lfEscapement;
|
|
|
|
}
|
|
|
|
|
2005-08-23 11:38:58 +02:00
|
|
|
if(lf.lfEscapement != 0)
|
|
|
|
{
|
|
|
|
cosEsc = cos(lf.lfEscapement * M_PI / 1800);
|
|
|
|
sinEsc = sin(lf.lfEscapement * M_PI / 1800);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cosEsc = 1;
|
|
|
|
sinEsc = 0;
|
|
|
|
}
|
|
|
|
|
2015-06-04 01:22:53 +02:00
|
|
|
if (lprect && (flags & (ETO_OPAQUE | ETO_CLIPPED)))
|
2005-08-23 11:38:58 +02:00
|
|
|
{
|
2012-12-20 15:08:23 +01:00
|
|
|
rc = *lprect;
|
2016-07-18 12:32:56 +02:00
|
|
|
lp_to_dp(dc, (POINT*)&rc, 2);
|
2012-12-14 16:55:56 +01:00
|
|
|
order_rect( &rc );
|
2012-12-20 15:08:23 +01:00
|
|
|
if (flags & ETO_OPAQUE)
|
|
|
|
physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
|
2005-08-23 11:38:58 +02:00
|
|
|
}
|
2012-12-20 15:08:23 +01:00
|
|
|
else flags &= ~ETO_CLIPPED;
|
2005-01-05 14:24:52 +01:00
|
|
|
|
2005-08-23 11:38:58 +02:00
|
|
|
if(count == 0)
|
2005-09-08 20:55:07 +02:00
|
|
|
{
|
|
|
|
ret = TRUE;
|
2005-08-23 11:38:58 +02:00
|
|
|
goto done;
|
2005-09-08 20:55:07 +02:00
|
|
|
}
|
2005-08-23 11:38:58 +02:00
|
|
|
|
|
|
|
pt.x = x;
|
|
|
|
pt.y = y;
|
2016-07-18 12:32:56 +02:00
|
|
|
lp_to_dp(dc, &pt, 1);
|
2005-08-23 11:38:58 +02:00
|
|
|
x = pt.x;
|
|
|
|
y = pt.y;
|
|
|
|
|
2021-09-10 14:28:30 +02:00
|
|
|
char_extra = dc->attr->char_extra;
|
|
|
|
if (char_extra && lpDx && NtGdiGetDeviceCaps( hdc, TECHNOLOGY ) == DT_RASPRINTER)
|
2013-03-26 12:14:26 +01:00
|
|
|
char_extra = 0; /* Printer drivers don't add char_extra if lpDx is supplied */
|
|
|
|
|
2007-05-31 13:47:19 +02:00
|
|
|
if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
|
2005-08-23 11:38:58 +02:00
|
|
|
{
|
|
|
|
UINT i;
|
2010-05-06 15:05:39 +02:00
|
|
|
POINT total = {0, 0}, desired[2];
|
|
|
|
|
|
|
|
deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
|
2012-12-20 14:32:58 +01:00
|
|
|
if (lpDx)
|
2004-07-21 06:07:28 +02:00
|
|
|
{
|
2012-12-20 14:32:58 +01:00
|
|
|
if (flags & ETO_PDY)
|
2010-05-06 15:05:39 +02:00
|
|
|
{
|
2012-12-20 14:32:58 +01:00
|
|
|
for (i = 0; i < count; i++)
|
2010-05-06 15:05:39 +02:00
|
|
|
{
|
|
|
|
deltas[i].x = lpDx[i * 2] + char_extra;
|
|
|
|
deltas[i].y = -lpDx[i * 2 + 1];
|
|
|
|
}
|
2012-12-20 14:32:58 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0; i < count; i++)
|
2010-05-06 15:05:39 +02:00
|
|
|
{
|
|
|
|
deltas[i].x = lpDx[i] + char_extra;
|
|
|
|
deltas[i].y = 0;
|
|
|
|
}
|
|
|
|
}
|
2012-12-20 14:32:58 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
INT *dx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*dx) );
|
|
|
|
|
2021-08-20 10:41:56 +02:00
|
|
|
NtGdiGetTextExtentExW( hdc, str, count, -1, NULL, dx, &sz, !!(flags & ETO_GLYPH_INDEX) );
|
2004-07-21 06:07:28 +02:00
|
|
|
|
2012-12-20 14:32:58 +01:00
|
|
|
deltas[0].x = dx[0];
|
|
|
|
deltas[0].y = 0;
|
|
|
|
for (i = 1; i < count; i++)
|
2005-08-23 11:38:58 +02:00
|
|
|
{
|
2012-12-20 14:32:58 +01:00
|
|
|
deltas[i].x = dx[i] - dx[i - 1];
|
|
|
|
deltas[i].y = 0;
|
2005-08-23 11:38:58 +02:00
|
|
|
}
|
2012-12-20 14:32:58 +01:00
|
|
|
HeapFree( GetProcessHeap(), 0, dx );
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i = 0; i < count; i++)
|
|
|
|
{
|
2010-05-06 15:05:39 +02:00
|
|
|
total.x += deltas[i].x;
|
|
|
|
total.y += deltas[i].y;
|
|
|
|
|
|
|
|
desired[0].x = desired[0].y = 0;
|
|
|
|
|
|
|
|
desired[1].x = cosEsc * total.x + sinEsc * total.y;
|
|
|
|
desired[1].y = -sinEsc * total.x + cosEsc * total.y;
|
|
|
|
|
2016-07-18 12:32:56 +02:00
|
|
|
lp_to_dp(dc, desired, 2);
|
2010-05-06 15:05:39 +02:00
|
|
|
desired[1].x -= desired[0].x;
|
|
|
|
desired[1].y -= desired[0].y;
|
2011-02-25 13:19:55 +01:00
|
|
|
|
2021-07-20 09:19:14 +02:00
|
|
|
if (dc->attr->graphics_mode == GM_COMPATIBLE)
|
2011-02-25 13:19:55 +01:00
|
|
|
{
|
|
|
|
if (dc->vport2WorldValid && dc->xformWorld2Vport.eM11 < 0)
|
|
|
|
desired[1].x = -desired[1].x;
|
|
|
|
if (dc->vport2WorldValid && dc->xformWorld2Vport.eM22 < 0)
|
|
|
|
desired[1].y = -desired[1].y;
|
|
|
|
}
|
2010-05-06 15:05:39 +02:00
|
|
|
|
|
|
|
deltas[i].x = desired[1].x - width.x;
|
|
|
|
deltas[i].y = desired[1].y - width.y;
|
|
|
|
|
|
|
|
width = desired[1];
|
2005-08-23 11:38:58 +02:00
|
|
|
}
|
2010-05-06 15:05:39 +02:00
|
|
|
flags |= ETO_PDY;
|
2005-08-23 11:38:58 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-12-10 14:33:53 +01:00
|
|
|
POINT desired[2];
|
|
|
|
|
2021-09-10 14:28:30 +02:00
|
|
|
NtGdiGetTextExtentExW( hdc, str, count, 0, NULL, NULL, &sz, !!(flags & ETO_GLYPH_INDEX) );
|
2012-12-10 14:33:53 +01:00
|
|
|
desired[0].x = desired[0].y = 0;
|
|
|
|
desired[1].x = sz.cx;
|
|
|
|
desired[1].y = 0;
|
2016-07-18 12:32:56 +02:00
|
|
|
lp_to_dp(dc, desired, 2);
|
2012-12-10 14:33:53 +01:00
|
|
|
desired[1].x -= desired[0].x;
|
|
|
|
desired[1].y -= desired[0].y;
|
|
|
|
|
2021-07-20 09:19:14 +02:00
|
|
|
if (dc->attr->graphics_mode == GM_COMPATIBLE)
|
2012-12-10 14:33:53 +01:00
|
|
|
{
|
|
|
|
if (dc->vport2WorldValid && dc->xformWorld2Vport.eM11 < 0)
|
|
|
|
desired[1].x = -desired[1].x;
|
|
|
|
if (dc->vport2WorldValid && dc->xformWorld2Vport.eM22 < 0)
|
|
|
|
desired[1].y = -desired[1].y;
|
|
|
|
}
|
|
|
|
width = desired[1];
|
2005-08-23 11:38:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
|
|
|
|
tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
|
|
|
|
switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
|
|
|
|
{
|
|
|
|
case TA_LEFT:
|
|
|
|
if (align & TA_UPDATECP)
|
|
|
|
{
|
2010-05-06 15:05:39 +02:00
|
|
|
pt.x = x + width.x;
|
2010-06-17 17:25:04 +02:00
|
|
|
pt.y = y + width.y;
|
2016-07-29 16:09:32 +02:00
|
|
|
dp_to_lp(dc, &pt, 1);
|
2021-09-10 14:28:30 +02:00
|
|
|
NtGdiMoveTo( hdc, pt.x, pt.y, NULL );
|
2005-08-23 11:38:58 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TA_CENTER:
|
2010-05-06 15:05:39 +02:00
|
|
|
x -= width.x / 2;
|
2010-06-17 17:25:04 +02:00
|
|
|
y -= width.y / 2;
|
2005-08-23 11:38:58 +02:00
|
|
|
break;
|
2005-08-19 11:58:57 +02:00
|
|
|
|
2005-08-23 11:38:58 +02:00
|
|
|
case TA_RIGHT:
|
2010-05-06 15:05:39 +02:00
|
|
|
x -= width.x;
|
2010-06-17 17:25:04 +02:00
|
|
|
y -= width.y;
|
2005-08-23 11:38:58 +02:00
|
|
|
if (align & TA_UPDATECP)
|
|
|
|
{
|
|
|
|
pt.x = x;
|
|
|
|
pt.y = y;
|
2016-07-29 16:09:32 +02:00
|
|
|
dp_to_lp(dc, &pt, 1);
|
2021-09-10 14:28:30 +02:00
|
|
|
NtGdiMoveTo( hdc, pt.x, pt.y, NULL );
|
2005-08-23 11:38:58 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
|
|
|
|
{
|
|
|
|
case TA_TOP:
|
|
|
|
y += tm.tmAscent * cosEsc;
|
|
|
|
x += tm.tmAscent * sinEsc;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TA_BOTTOM:
|
|
|
|
y -= tm.tmDescent * cosEsc;
|
|
|
|
x -= tm.tmDescent * sinEsc;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TA_BASELINE:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-07-26 23:29:51 +02:00
|
|
|
if (dc->attr->background_mode != TRANSPARENT)
|
2005-08-23 11:38:58 +02:00
|
|
|
{
|
|
|
|
if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
|
|
|
|
{
|
2012-02-21 17:20:48 +01:00
|
|
|
if(!(flags & ETO_OPAQUE) || !lprect ||
|
|
|
|
x < rc.left || x + width.x >= rc.right ||
|
2005-08-23 11:38:58 +02:00
|
|
|
y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
|
|
|
|
{
|
2012-02-09 12:19:01 +01:00
|
|
|
RECT text_box;
|
|
|
|
text_box.left = x;
|
|
|
|
text_box.right = x + width.x;
|
|
|
|
text_box.top = y - tm.tmAscent;
|
|
|
|
text_box.bottom = y + tm.tmDescent;
|
2011-01-30 13:47:55 +01:00
|
|
|
|
2012-02-09 12:19:02 +01:00
|
|
|
if (flags & ETO_CLIPPED) intersect_rect( &text_box, &text_box, &rc );
|
|
|
|
if (!is_rect_empty( &text_box ))
|
2012-02-09 12:19:01 +01:00
|
|
|
physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &text_box, NULL, 0, NULL );
|
2005-08-19 11:58:57 +02:00
|
|
|
}
|
2005-08-23 11:38:58 +02:00
|
|
|
}
|
|
|
|
}
|
2005-08-19 11:58:57 +02:00
|
|
|
|
2012-12-05 16:44:15 +01:00
|
|
|
ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
|
2021-08-19 10:25:33 +02:00
|
|
|
str, count, (INT*)deltas );
|
2005-08-23 11:38:58 +02:00
|
|
|
|
2005-09-21 11:41:13 +02:00
|
|
|
done:
|
|
|
|
HeapFree(GetProcessHeap(), 0, deltas);
|
|
|
|
|
|
|
|
if (ret && (lf.lfUnderline || lf.lfStrikeOut))
|
2005-08-23 11:38:58 +02:00
|
|
|
{
|
|
|
|
int underlinePos, strikeoutPos;
|
|
|
|
int underlineWidth, strikeoutWidth;
|
2021-08-20 10:43:13 +02:00
|
|
|
UINT size = NtGdiGetOutlineTextMetricsInternalW( hdc, 0, NULL, 0 );
|
2005-08-23 11:38:58 +02:00
|
|
|
OUTLINETEXTMETRICW* otm = NULL;
|
2011-10-25 18:14:04 +02:00
|
|
|
POINT pts[5];
|
2021-09-03 14:59:51 +02:00
|
|
|
HPEN hpen = NtGdiSelectPen( hdc, get_stock_object(NULL_PEN) );
|
2021-09-10 14:28:30 +02:00
|
|
|
HBRUSH hbrush = NtGdiCreateSolidBrush( dc->attr->text_color, NULL );
|
2011-10-25 18:14:04 +02:00
|
|
|
|
2021-07-02 12:41:27 +02:00
|
|
|
hbrush = NtGdiSelectBrush(hdc, hbrush);
|
2005-08-23 11:38:58 +02:00
|
|
|
|
2005-09-21 11:41:13 +02:00
|
|
|
if(!size)
|
2005-08-23 11:38:58 +02:00
|
|
|
{
|
|
|
|
underlinePos = 0;
|
|
|
|
underlineWidth = tm.tmAscent / 20 + 1;
|
|
|
|
strikeoutPos = tm.tmAscent / 2;
|
|
|
|
strikeoutWidth = underlineWidth;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-09-21 11:41:13 +02:00
|
|
|
otm = HeapAlloc(GetProcessHeap(), 0, size);
|
2021-08-20 10:43:13 +02:00
|
|
|
NtGdiGetOutlineTextMetricsInternalW( hdc, size, otm, 0 );
|
2011-11-07 13:41:18 +01:00
|
|
|
underlinePos = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition ));
|
|
|
|
if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos;
|
2015-05-19 09:58:24 +02:00
|
|
|
underlineWidth = get_line_width( dc, otm->otmsUnderscoreSize );
|
2011-11-07 13:41:18 +01:00
|
|
|
strikeoutPos = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutPosition ));
|
|
|
|
if (otm->otmsStrikeoutPosition < 0) strikeoutPos = -strikeoutPos;
|
2015-05-19 09:58:24 +02:00
|
|
|
strikeoutWidth = get_line_width( dc, otm->otmsStrikeoutSize );
|
2005-09-21 11:41:13 +02:00
|
|
|
HeapFree(GetProcessHeap(), 0, otm);
|
2005-08-23 11:38:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-25 18:14:04 +02:00
|
|
|
if (lf.lfUnderline)
|
2005-08-23 11:38:58 +02:00
|
|
|
{
|
2021-07-22 11:26:00 +02:00
|
|
|
const UINT cnt = 5;
|
2011-11-07 13:41:18 +01:00
|
|
|
pts[0].x = x - (underlinePos + underlineWidth / 2) * sinEsc;
|
|
|
|
pts[0].y = y - (underlinePos + underlineWidth / 2) * cosEsc;
|
|
|
|
pts[1].x = x + width.x - (underlinePos + underlineWidth / 2) * sinEsc;
|
|
|
|
pts[1].y = y + width.y - (underlinePos + underlineWidth / 2) * cosEsc;
|
2011-10-25 18:14:04 +02:00
|
|
|
pts[2].x = pts[1].x + underlineWidth * sinEsc;
|
|
|
|
pts[2].y = pts[1].y + underlineWidth * cosEsc;
|
|
|
|
pts[3].x = pts[0].x + underlineWidth * sinEsc;
|
|
|
|
pts[3].y = pts[0].y + underlineWidth * cosEsc;
|
|
|
|
pts[4].x = pts[0].x;
|
|
|
|
pts[4].y = pts[0].y;
|
2016-07-29 16:09:32 +02:00
|
|
|
dp_to_lp(dc, pts, 5);
|
2021-07-22 11:26:00 +02:00
|
|
|
NtGdiPolyPolyDraw( hdc, pts, &cnt, 1, NtGdiPolyPolygon );
|
2011-10-25 18:14:04 +02:00
|
|
|
}
|
2005-09-28 12:14:45 +02:00
|
|
|
|
2011-10-25 18:14:04 +02:00
|
|
|
if (lf.lfStrikeOut)
|
|
|
|
{
|
2021-07-22 11:26:00 +02:00
|
|
|
const UINT cnt = 5;
|
2011-11-07 13:41:18 +01:00
|
|
|
pts[0].x = x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
|
|
|
|
pts[0].y = y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
|
|
|
|
pts[1].x = x + width.x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
|
|
|
|
pts[1].y = y + width.y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
|
2011-10-25 18:14:04 +02:00
|
|
|
pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
|
|
|
|
pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
|
|
|
|
pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
|
|
|
|
pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
|
|
|
|
pts[4].x = pts[0].x;
|
|
|
|
pts[4].y = pts[0].y;
|
2016-07-29 16:09:32 +02:00
|
|
|
dp_to_lp(dc, pts, 5);
|
2021-07-22 11:26:00 +02:00
|
|
|
NtGdiPolyPolyDraw( hdc, pts, &cnt, 1, NtGdiPolyPolygon );
|
2004-07-21 06:07:28 +02:00
|
|
|
}
|
2011-10-25 18:14:04 +02:00
|
|
|
|
2021-07-02 12:41:27 +02:00
|
|
|
NtGdiSelectPen(hdc, hpen);
|
|
|
|
hbrush = NtGdiSelectBrush(hdc, hbrush);
|
2021-09-03 14:59:52 +02:00
|
|
|
NtGdiDeleteObjectApp( hbrush );
|
2004-07-21 06:07:28 +02:00
|
|
|
}
|
2005-08-23 11:38:58 +02:00
|
|
|
|
2016-07-29 16:09:32 +02:00
|
|
|
release_dc_ptr( dc );
|
|
|
|
|
2004-07-21 06:07:28 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Release 980503
Thu Apr 30 16:28:12 1998 James Juran <jrj120@psu.edu>
* [scheduler/process.c]
Implemented GetExitCodeProcess. The code is a direct translation
of GetExitCodeThread.
Mon Apr 27 22:20:25 1998 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
* [loader/pe_image.c]
Unload dummy module when PE_LoadLibraryEx32A fails with
PE_LoadImage (makes Encarta 98 installer proceed).
* [files/drive.c]
Make GetDriveType16 return DRIVE_REMOVABLE for TYPE_CDROM.
Make GetCurrentDirectory32 behave like the code does and not
like the help describes.
* [files/profile.c]
Revoke recent change in PROFILE_GetSection and try better
handling of special case.
* [include/windows.h]
Change definition of ACCEL32.
* [misc/commdlg.c]
Replace the GetXXXFilename32 macros by normal code.
Fix two reported bugs in my changes to commdlg.
* [windows/win.c]
Add a hook to catch bogus WM_SIZE messages by emitting a warning
in the appropriate case.
* [objects/bitmap.c]
Reject unreasonbable large size arguments in
CreateCompatibleBitmap32 and add an fixme for that situation.
Sun Apr 26 18:30:07 1998 Alexandre Julliard <julliard@lrc.epfl.ch>
* [include/ldt.h] [debugger/*.c] [miscemu/instr.c]
Added IS_SELECTOR_SYSTEM and IS_SELECTOR_32BIT macros.
Make instruction emulation support system selectors.
* [loader/*.c]
Started moving NE specific functions to the new loader/ne
directory.
* [memory/environ.c]
Enforce the 127 chars limit only when creating the environment of
a Win16 process.
Sun Apr 26 12:22:23 1998 Andreas Mohr <100.30936@germany.net>
* [files/file.c]
Fixed an incredible typo in CopyFile32A that made it unusable
since a rewrite in 970112 (!!).
* [files/directory.c]
Fixed GetTempPath32A/W to include trailing backslash.
* [misc/ver.c]
Make find_pe_resource "work" with corrupt files.
* [misc/wsprintf.c]
Altered WPRINTF_ParseFormatA/W to treat invalid format chars
as normal output, too.
* [msdos/dpmi.c]
Implemented "Allocate/Free real mode callback" (0x0303/0x0304).
Cross your fingers if you need to use it ;) (completely untested)
Implemented "Call real mode proc with far return" (0x0301, tested).
* [msdos/int21.c]
Fixed ioctlGenericBlkDevReq/0x60.
* [relay32/dplayx.spec] [relay32/builtin32.c] [relay32/Makefile.in]
Added built-in DPLAYX.DLL.
* [windows/win.c]
Fixed GetWindowWord()/GWW_HWNDPARENT to return the window's owner
if it has no parent (SDK).
Sat Apr 25 15:09:53 1998 M.T.Fortescue <mark@mtfhpc.demon.co.uk>
* [debugger/db_disasm.c]
Fixed disassemble bug for no-display option and 'lock',
'repne' and 'repe' prefixes.
* [debugger/registers.c]
Added textual flag description output on 'info regs'.
Sat Apr 25 14:18:26 1998 Matthew Becker <mbecker@glasscity.net>
* [*/*.c]
Added stubs and/or documentation for the following functions:
LookupPrivilegeValue, OpenService, ControlService, RegGetKeySecurity,
StartService, SetComputerName, DeleteService, CloseServiceHandle,
OpenProcessToken, OpenSCManager, DeregisterEventSource,
WaitForDebugEvent, WaitForInputIdle, RegisterEventSource,
SetDebugErrorLevel, SetConsoleCursorPosition, ChoosePixelFormat,
SetPixelFormat, GetPixelFormat, DescribePixelFormat, SwapBuffers,
PolyBezier, AbortPath, DestroyAcceleratorTable, HeapWalk,
DdeInitialize, DdeUninitialize, DdeConnectList, DdeDisconnectList,
DdeCreateStringHandle, DdePostAdvise, DdeGetData, DdeNameService,
DdeGetLastError, WNetGetDirectoryType, EnumPrinters, RegFlushKey,
RegGetKeySecurity, DllGetClassObject, DllCanUnloadNow, CreateBitmap,
CreateCompatibleBitmap, CreateBitmapIndirect, GetBitmapBits,
SetBitmapBits, LoadImage, CopyImage, LoadBitmap, DrawIcon,
CreateDiscardableBitmap, SetDIBits, GetCharABCWidths, LoadTypeLib,
SetConsoleCtrlHandler, CreateConsoleScreenBuffer, ReadConsoleInput,
GetConsoleCursorInfo, SetConsoleCursorInfo, SetConsoleWindowInfo,
SetConsoleTextAttribute, SetConsoleScreenBufferSize,
FillConsoleOutputCharacter, FillConsoleOutputAttribute,
CreateMailslot, GetMailslotInfo, GetCompressedFileSize,
GetProcessWindowStation, GetThreadDesktop, SetDebugErrorLevel,
WaitForDebugEvent, SetComputerName, CreateMDIWindow.
Thu Apr 23 23:54:04 1998 Douglas Ridgway <ridgway@winehq.com>
* [include/windows.h] [objects/enhmetafile.c] [relay32/gdi32.spec]
Implement CopyEnhMetaFile, Get/SetEnhMetaFileBits, other fixes.
* [include/windows.h] [objects/metafile.c] [relay32/gdi32.spec]
32-bit metafile fixes, implement EnumMetaFile32, GetMetaFileBitsEx.
* [objects/font.c] [graphics/x11drv/xfont.c] [graphics/x11drv/text.c]
Some rotated text support for X11R6 displays.
* [win32/newfns.c] [ole/ole2nls.c]
Moved GetNumberFormat32A.
Wed Apr 22 17:38:20 1998 David Lee Lambert <lamber45@egr.msu.edu>
* [ole/ole2nls.c] [misc/network.c]
Changed some function documentation to the new style.
* [misc/network.c] [include/windows.h] [if1632/user.spec]
[relay32/mpr.spec] [misc/mpr.c]
Added stubs for some Win32 network functions; renamed some
16-bit ones with 32-bit counterparts, as well as
WNetGetDirectoryType; moved the stubs in misc/mpr.c (three of
them!) to misc/network.c.
* [ole/compobj.c] [ole/storage.c] [ole/ole2disp.c]
[ole/ole2nls.c] [ole/folders.c] [ole/moniker.c] [ole/ole2.c]
[graphics/fontengine.c] [graphics/ddraw.c] [graphics/env.c]
[graphics/driver.c] [graphics/escape.c]
Changed fprintf's to proper debug-macros.
* [include/winnls.h]
Added some flags (for internal use).
* [ole/ole2nls.c]
Added the Unicode core function, and worked out a way to hide
the commonality of the core.
* [relay32/kernel32.spec]
Added support for GetDate/Time32A/W.
Wed Apr 22 09:16:03 1998 Gordon Chaffee <chaffee@cs.berkeley.edu>
* [win32/code_page.c]
Fixed problem with MultiByteToWideChar that was introduced in
last release. Made MultiByteToWideChar more compatible with Win32.
* [graphics/x11drv/graphics.c]
Fixed problem with drawing arcs.
Tue Apr 21 11:24:58 1998 Constantine Sapuntzakis <csapuntz@tma-1.lcs.mit.edu>
* [ole/ole2nls.c]
Move stuff from 0x409 case to Lang_En.
* [relay32/user32.spec] [windows/winpos.c]
Added stubs for GetWindowRgn32 and SetWindowRgn32. Makes Office
Paperclip happy.
Tue Apr 21 11:16:16 1998 Constantine Sapuntzakis <csapuntz@tma-1.lcs.mit.edu>
* [loader/pe_image.c]
If image is relocated, TLS addresses need to be adjusted.
* [debugger/*.c]
Generalized tests for 32-bit segments.
Tue Apr 21 02:04:59 1998 James Juran <jrj120@psu.edu>
* [misc/*.c] [miscemu/*.c] [msdos/*.c] [if1632/*.c]
[include/*.h] [loader/*.c] [memory/*.c] [multimedia/*.c]
[objects/*.c]
Almost all fprintf statements converted to appropriate
debug messages.
* [README]
Updated "GETTING MORE INFORMATION" section to include WineHQ.
* [documentation/debugger]
Fixed typo.
* [windows/defwnd.c]
Added function documentation.
Sun Apr 19 16:30:58 1998 Marcus Meissner <marcus@mud.de>
* [Make.rules.in]
Added lint target (using lclint).
* [relay32/oleaut32.spec][relay32/Makefile.in][ole/typelib.c]
[ole/ole2disp.c]
Added oleaut32 spec, added some SysString functions.
* [if1632/signal.c]
Added printing of faultaddress in Linux (using CR2 debug register).
* [configure.in]
Added <sys/types.h> for statfs checks.
* [loader/*.c][debugger/break.c][debugger/hash.c]
Started to split win32/win16 module handling, preparing support
for other binary formats (like ELF).
Sat Apr 18 10:07:41 1998 Rein Klazes <rklazes@casema.net>
* [misc/registry.c]
Fixed a bug that made RegQueryValuexxx returning
incorrect registry values.
Fri Apr 17 22:59:22 1998 Alexander V. Lukyanov <lav@long.yar.ru>
* [misc/lstr.c]
FormatMessage32*: remove linefeed when nolinefeed set;
check for target underflow.
Fri Apr 17 00:38:14 1998 Alexander V. Lukyanov <lav@long.yar.ru>
* [misc/crtdll.c]
Implement xlat_file_ptr for CRT stdin/stdout/stderr address
translation.
Wed Apr 15 20:43:56 1998 Jim Peterson <jspeter@birch.ee.vt.edu>
* [controls/menu.c]
Added 'odaction' parameter to MENU_DrawMenuItem() and redirected
WM_DRAWITEM messages to GetWindow(hwnd,GW_OWNER).
Tue Apr 14 16:17:55 1998 Berend Reitsma <berend@united-info.com>
* [graphics/metafiledrv/init.c] [graphics/painting.c]
[graphics/win16drv/init.c] [graphics/x11drv/graphics.c]
[graphics/x11drv/init.c] [include/gdi.h] [include/x11drv.h]
[relay32/gdi32.spec]
Added PolyPolyline routine.
* [windows/winproc.c]
Changed WINPROC_GetProc() to return proc instead of &(jmp proc).
1998-05-03 21:01:20 +02:00
|
|
|
/******************************************************************************
|
2021-08-27 14:51:48 +02:00
|
|
|
* NtGdiGetCharABCWidthsW (win32u.@)
|
2004-02-09 21:47:42 +01:00
|
|
|
*
|
|
|
|
* Retrieves widths of characters in range.
|
Release 980503
Thu Apr 30 16:28:12 1998 James Juran <jrj120@psu.edu>
* [scheduler/process.c]
Implemented GetExitCodeProcess. The code is a direct translation
of GetExitCodeThread.
Mon Apr 27 22:20:25 1998 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
* [loader/pe_image.c]
Unload dummy module when PE_LoadLibraryEx32A fails with
PE_LoadImage (makes Encarta 98 installer proceed).
* [files/drive.c]
Make GetDriveType16 return DRIVE_REMOVABLE for TYPE_CDROM.
Make GetCurrentDirectory32 behave like the code does and not
like the help describes.
* [files/profile.c]
Revoke recent change in PROFILE_GetSection and try better
handling of special case.
* [include/windows.h]
Change definition of ACCEL32.
* [misc/commdlg.c]
Replace the GetXXXFilename32 macros by normal code.
Fix two reported bugs in my changes to commdlg.
* [windows/win.c]
Add a hook to catch bogus WM_SIZE messages by emitting a warning
in the appropriate case.
* [objects/bitmap.c]
Reject unreasonbable large size arguments in
CreateCompatibleBitmap32 and add an fixme for that situation.
Sun Apr 26 18:30:07 1998 Alexandre Julliard <julliard@lrc.epfl.ch>
* [include/ldt.h] [debugger/*.c] [miscemu/instr.c]
Added IS_SELECTOR_SYSTEM and IS_SELECTOR_32BIT macros.
Make instruction emulation support system selectors.
* [loader/*.c]
Started moving NE specific functions to the new loader/ne
directory.
* [memory/environ.c]
Enforce the 127 chars limit only when creating the environment of
a Win16 process.
Sun Apr 26 12:22:23 1998 Andreas Mohr <100.30936@germany.net>
* [files/file.c]
Fixed an incredible typo in CopyFile32A that made it unusable
since a rewrite in 970112 (!!).
* [files/directory.c]
Fixed GetTempPath32A/W to include trailing backslash.
* [misc/ver.c]
Make find_pe_resource "work" with corrupt files.
* [misc/wsprintf.c]
Altered WPRINTF_ParseFormatA/W to treat invalid format chars
as normal output, too.
* [msdos/dpmi.c]
Implemented "Allocate/Free real mode callback" (0x0303/0x0304).
Cross your fingers if you need to use it ;) (completely untested)
Implemented "Call real mode proc with far return" (0x0301, tested).
* [msdos/int21.c]
Fixed ioctlGenericBlkDevReq/0x60.
* [relay32/dplayx.spec] [relay32/builtin32.c] [relay32/Makefile.in]
Added built-in DPLAYX.DLL.
* [windows/win.c]
Fixed GetWindowWord()/GWW_HWNDPARENT to return the window's owner
if it has no parent (SDK).
Sat Apr 25 15:09:53 1998 M.T.Fortescue <mark@mtfhpc.demon.co.uk>
* [debugger/db_disasm.c]
Fixed disassemble bug for no-display option and 'lock',
'repne' and 'repe' prefixes.
* [debugger/registers.c]
Added textual flag description output on 'info regs'.
Sat Apr 25 14:18:26 1998 Matthew Becker <mbecker@glasscity.net>
* [*/*.c]
Added stubs and/or documentation for the following functions:
LookupPrivilegeValue, OpenService, ControlService, RegGetKeySecurity,
StartService, SetComputerName, DeleteService, CloseServiceHandle,
OpenProcessToken, OpenSCManager, DeregisterEventSource,
WaitForDebugEvent, WaitForInputIdle, RegisterEventSource,
SetDebugErrorLevel, SetConsoleCursorPosition, ChoosePixelFormat,
SetPixelFormat, GetPixelFormat, DescribePixelFormat, SwapBuffers,
PolyBezier, AbortPath, DestroyAcceleratorTable, HeapWalk,
DdeInitialize, DdeUninitialize, DdeConnectList, DdeDisconnectList,
DdeCreateStringHandle, DdePostAdvise, DdeGetData, DdeNameService,
DdeGetLastError, WNetGetDirectoryType, EnumPrinters, RegFlushKey,
RegGetKeySecurity, DllGetClassObject, DllCanUnloadNow, CreateBitmap,
CreateCompatibleBitmap, CreateBitmapIndirect, GetBitmapBits,
SetBitmapBits, LoadImage, CopyImage, LoadBitmap, DrawIcon,
CreateDiscardableBitmap, SetDIBits, GetCharABCWidths, LoadTypeLib,
SetConsoleCtrlHandler, CreateConsoleScreenBuffer, ReadConsoleInput,
GetConsoleCursorInfo, SetConsoleCursorInfo, SetConsoleWindowInfo,
SetConsoleTextAttribute, SetConsoleScreenBufferSize,
FillConsoleOutputCharacter, FillConsoleOutputAttribute,
CreateMailslot, GetMailslotInfo, GetCompressedFileSize,
GetProcessWindowStation, GetThreadDesktop, SetDebugErrorLevel,
WaitForDebugEvent, SetComputerName, CreateMDIWindow.
Thu Apr 23 23:54:04 1998 Douglas Ridgway <ridgway@winehq.com>
* [include/windows.h] [objects/enhmetafile.c] [relay32/gdi32.spec]
Implement CopyEnhMetaFile, Get/SetEnhMetaFileBits, other fixes.
* [include/windows.h] [objects/metafile.c] [relay32/gdi32.spec]
32-bit metafile fixes, implement EnumMetaFile32, GetMetaFileBitsEx.
* [objects/font.c] [graphics/x11drv/xfont.c] [graphics/x11drv/text.c]
Some rotated text support for X11R6 displays.
* [win32/newfns.c] [ole/ole2nls.c]
Moved GetNumberFormat32A.
Wed Apr 22 17:38:20 1998 David Lee Lambert <lamber45@egr.msu.edu>
* [ole/ole2nls.c] [misc/network.c]
Changed some function documentation to the new style.
* [misc/network.c] [include/windows.h] [if1632/user.spec]
[relay32/mpr.spec] [misc/mpr.c]
Added stubs for some Win32 network functions; renamed some
16-bit ones with 32-bit counterparts, as well as
WNetGetDirectoryType; moved the stubs in misc/mpr.c (three of
them!) to misc/network.c.
* [ole/compobj.c] [ole/storage.c] [ole/ole2disp.c]
[ole/ole2nls.c] [ole/folders.c] [ole/moniker.c] [ole/ole2.c]
[graphics/fontengine.c] [graphics/ddraw.c] [graphics/env.c]
[graphics/driver.c] [graphics/escape.c]
Changed fprintf's to proper debug-macros.
* [include/winnls.h]
Added some flags (for internal use).
* [ole/ole2nls.c]
Added the Unicode core function, and worked out a way to hide
the commonality of the core.
* [relay32/kernel32.spec]
Added support for GetDate/Time32A/W.
Wed Apr 22 09:16:03 1998 Gordon Chaffee <chaffee@cs.berkeley.edu>
* [win32/code_page.c]
Fixed problem with MultiByteToWideChar that was introduced in
last release. Made MultiByteToWideChar more compatible with Win32.
* [graphics/x11drv/graphics.c]
Fixed problem with drawing arcs.
Tue Apr 21 11:24:58 1998 Constantine Sapuntzakis <csapuntz@tma-1.lcs.mit.edu>
* [ole/ole2nls.c]
Move stuff from 0x409 case to Lang_En.
* [relay32/user32.spec] [windows/winpos.c]
Added stubs for GetWindowRgn32 and SetWindowRgn32. Makes Office
Paperclip happy.
Tue Apr 21 11:16:16 1998 Constantine Sapuntzakis <csapuntz@tma-1.lcs.mit.edu>
* [loader/pe_image.c]
If image is relocated, TLS addresses need to be adjusted.
* [debugger/*.c]
Generalized tests for 32-bit segments.
Tue Apr 21 02:04:59 1998 James Juran <jrj120@psu.edu>
* [misc/*.c] [miscemu/*.c] [msdos/*.c] [if1632/*.c]
[include/*.h] [loader/*.c] [memory/*.c] [multimedia/*.c]
[objects/*.c]
Almost all fprintf statements converted to appropriate
debug messages.
* [README]
Updated "GETTING MORE INFORMATION" section to include WineHQ.
* [documentation/debugger]
Fixed typo.
* [windows/defwnd.c]
Added function documentation.
Sun Apr 19 16:30:58 1998 Marcus Meissner <marcus@mud.de>
* [Make.rules.in]
Added lint target (using lclint).
* [relay32/oleaut32.spec][relay32/Makefile.in][ole/typelib.c]
[ole/ole2disp.c]
Added oleaut32 spec, added some SysString functions.
* [if1632/signal.c]
Added printing of faultaddress in Linux (using CR2 debug register).
* [configure.in]
Added <sys/types.h> for statfs checks.
* [loader/*.c][debugger/break.c][debugger/hash.c]
Started to split win32/win16 module handling, preparing support
for other binary formats (like ELF).
Sat Apr 18 10:07:41 1998 Rein Klazes <rklazes@casema.net>
* [misc/registry.c]
Fixed a bug that made RegQueryValuexxx returning
incorrect registry values.
Fri Apr 17 22:59:22 1998 Alexander V. Lukyanov <lav@long.yar.ru>
* [misc/lstr.c]
FormatMessage32*: remove linefeed when nolinefeed set;
check for target underflow.
Fri Apr 17 00:38:14 1998 Alexander V. Lukyanov <lav@long.yar.ru>
* [misc/crtdll.c]
Implement xlat_file_ptr for CRT stdin/stdout/stderr address
translation.
Wed Apr 15 20:43:56 1998 Jim Peterson <jspeter@birch.ee.vt.edu>
* [controls/menu.c]
Added 'odaction' parameter to MENU_DrawMenuItem() and redirected
WM_DRAWITEM messages to GetWindow(hwnd,GW_OWNER).
Tue Apr 14 16:17:55 1998 Berend Reitsma <berend@united-info.com>
* [graphics/metafiledrv/init.c] [graphics/painting.c]
[graphics/win16drv/init.c] [graphics/x11drv/graphics.c]
[graphics/x11drv/init.c] [include/gdi.h] [include/x11drv.h]
[relay32/gdi32.spec]
Added PolyPolyline routine.
* [windows/winproc.c]
Changed WINPROC_GetProc() to return proc instead of &(jmp proc).
1998-05-03 21:01:20 +02:00
|
|
|
*
|
|
|
|
* PARAMS
|
|
|
|
* hdc [I] Handle of device context
|
|
|
|
* firstChar [I] First character in range to query
|
|
|
|
* lastChar [I] Last character in range to query
|
|
|
|
* abc [O] Address of character-width structure
|
|
|
|
*
|
|
|
|
* NOTES
|
|
|
|
* Only works with TrueType fonts
|
1997-03-05 09:22:35 +01:00
|
|
|
*/
|
2021-08-27 14:51:49 +02:00
|
|
|
BOOL WINAPI NtGdiGetCharABCWidthsW( HDC hdc, UINT first, UINT last, WCHAR *chars,
|
2021-08-27 14:51:48 +02:00
|
|
|
ULONG flags, void *buffer )
|
1994-11-07 19:20:42 +01:00
|
|
|
{
|
2008-02-05 21:16:27 +01:00
|
|
|
DC *dc = get_dc_ptr(hdc);
|
2011-10-21 11:33:04 +02:00
|
|
|
PHYSDEV dev;
|
2021-08-27 14:51:49 +02:00
|
|
|
unsigned int i, count = last;
|
2011-10-21 11:33:04 +02:00
|
|
|
BOOL ret;
|
2011-12-12 11:14:09 +01:00
|
|
|
TEXTMETRICW tm;
|
2001-04-23 20:11:58 +02:00
|
|
|
|
2006-04-08 22:27:34 +02:00
|
|
|
if (!dc) return FALSE;
|
|
|
|
|
2021-08-27 14:51:48 +02:00
|
|
|
if (!buffer)
|
2007-12-08 22:55:01 +01:00
|
|
|
{
|
2008-02-05 21:16:27 +01:00
|
|
|
release_dc_ptr( dc );
|
2007-12-08 22:55:01 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2021-08-27 14:51:50 +02:00
|
|
|
if (flags & NTGDI_GETCHARABCWIDTHS_INDICES)
|
2011-12-12 11:14:09 +01:00
|
|
|
{
|
2021-08-27 14:51:50 +02:00
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
|
|
|
|
ret = dev->funcs->pGetCharABCWidthsI( dev, first, count, chars, buffer );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-08-27 14:51:51 +02:00
|
|
|
if (flags & NTGDI_GETCHARABCWIDTHS_INT)
|
2021-08-27 14:51:50 +02:00
|
|
|
{
|
2021-08-27 14:51:51 +02:00
|
|
|
/* unlike float variant, this one is supposed to fail on non-scalable fonts */
|
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
|
|
|
|
if (!dev->funcs->pGetTextMetrics( dev, &tm ) || !(tm.tmPitchAndFamily & TMPF_VECTOR))
|
|
|
|
{
|
|
|
|
release_dc_ptr( dc );
|
|
|
|
return FALSE;
|
|
|
|
}
|
2021-08-27 14:51:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!chars) count = last - first + 1;
|
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
|
|
|
|
ret = dev->funcs->pGetCharABCWidths( dev, first, count, chars, buffer );
|
2011-12-12 11:14:09 +01:00
|
|
|
}
|
|
|
|
|
2004-02-12 21:05:47 +01:00
|
|
|
if (ret)
|
|
|
|
{
|
2021-08-27 14:51:48 +02:00
|
|
|
ABC *abc = buffer;
|
2021-08-27 14:51:51 +02:00
|
|
|
if (flags & NTGDI_GETCHARABCWIDTHS_INT)
|
2021-08-27 14:51:49 +02:00
|
|
|
{
|
2021-08-27 14:51:51 +02:00
|
|
|
/* convert device units to logical */
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
abc[i].abcA = width_to_LP( dc, abc[i].abcA );
|
|
|
|
abc[i].abcB = width_to_LP( dc, abc[i].abcB );
|
|
|
|
abc[i].abcC = width_to_LP( dc, abc[i].abcC );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* convert device units to logical */
|
|
|
|
FLOAT scale = fabs( dc->xformVport2World.eM11 );
|
|
|
|
ABCFLOAT *abcf = buffer;
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
abcf[i].abcfA = abc[i].abcA * scale;
|
|
|
|
abcf[i].abcfB = abc[i].abcB * scale;
|
|
|
|
abcf[i].abcfC = abc[i].abcC * scale;
|
|
|
|
}
|
|
|
|
}
|
2006-04-19 11:20:50 +02:00
|
|
|
}
|
|
|
|
|
2008-02-05 21:16:27 +01:00
|
|
|
release_dc_ptr( dc );
|
2006-04-19 11:20:50 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1997-06-16 19:43:53 +02:00
|
|
|
/***********************************************************************
|
2021-09-10 14:28:04 +02:00
|
|
|
* NtGdiGetGlyphOutline (win32u.@)
|
Release 961201
Sat Nov 30 19:21:17 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [configure]
Re-generated with autoconf 2.11. Let me know if you have
problems.
* [controls/listbox.c] [controls/oldlbox.c]
Listboxes rewritten from scratch. Moved old code still used by
comboboxes to oldlbox.c
* [misc/registry.c]
Use temporary file when saving registry.
* [windows/dialog.c]
Implemented Win32 version of DlgDirList() and DlgDirListComboBox().
* [windows/winproc.c]
Added translation for listbox Win32 messages.
Sat Nov 30 21:00:00 Alex Korobka <alex@trantor.pharm.sunysb.edu>
* [controls/widgets.c] [controls/button.c]
Fixed some incompatibilities with CTL3D DLL.
* [windows/dialog.c]
Made dialog windows fit into the desktop.
* [misc/winsock.c] [misc/winsock_async.c]
New Winsock engine.
* [windows/message.c]
GetMessage() fixes.
* [windows/queue.c] [windows/hook.c] [windows/win.c]
SetMessageQueue() fixes.
Fri Nov 29 10:25:12 1996 Slaven Rezic <eserte@cs.tu-berlin.de>
* [objects/text.c]
DrawText16(): Fixed return value.
Tue Nov 26 14:47:09 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [files/profile.c] [*/*]
Added Win32 profile functions, updated to new naming standard.
* [objects/font.c] [if1632/thunk.c] [include/windows.h]
Added EnumFonts32*, EnumFontFamiliesEx*, changed prototypes and
structures.
* [misc/ole2nls.c] [if1632/thunk.c]
Added EnumSystemLocales() (winhelp.exe).
* [misc/registry.c]
Added Windows 3.1 registry loader supplied by Tor Sjxwall, tor@sn.no
* [win32/file.c]
Partially fixed CreateFileMapping(), added UnmapViewOfFile().
Sat Nov 23 23:36:05 1996 Ronan Waide <waider@waider.ie>
* [misc/shell.c]
Fixed some FIXMEs relating to ShellExec() and FindExecutable().
* [misc/main.c]
Implemented a few more of the SystemParametersInfo() cases.
Tue Nov 19 01:24:34 1996 Philippe De Muyter <phdm@info.ucl.ac.be>
* [include/keyboard.h]
New file, new macro WINE_VKEY_MAPPINGS (using code taken from event.c).
* [include/windows.h]
New [VK_A, VK_Z] and [VK_0, VK9] macros.
* [misc/keyboard.c]
Fixes in KeyTable and ToAscii.
* [objects/font.c]
FONT_init : Give default value for MSWIN "system" font.
FONT_MatchFont : Do not try every size of a font family if the
family does not exist.
* [windows/event.c]
lastEventChar hack removed.
KeyStateTable replaced by InputKeyStateTable (maintained in event.c)
and QueueKeyStateTable (maintained in message.c).
EVENT_key : Corrections to the extended bit setting.
* [windows/message.c] [windows/keyboard.c]
Implementation of a new QueueKeyStateTable : table of key states
valid when messages are retrieved by GetMessage or PeekMessage,
and valid for TranslateMessage.
TranslateMessage : Convert WM*KEY messages using QueueKeyStateTable
and ToAscii.
Mon Nov 18 16:59:01 1996 Robert Pouliot <krynos@clic.net>
* [graphics/Makefile.in] [graphics/wing.c]
[if1632/wing.spec]
Some functions for WinG support, mostly empty stubs.
* [misc/crtdll.c] [if1632/crtdll.spec]
Many functions added to CRTDLL, mostly calls to Unix C library.
1996-12-01 18:17:47 +01:00
|
|
|
*/
|
2021-09-10 14:28:04 +02:00
|
|
|
DWORD WINAPI NtGdiGetGlyphOutline( HDC hdc, UINT ch, UINT format, GLYPHMETRICS *metrics,
|
|
|
|
DWORD size, void *buffer, const MAT2 *mat2,
|
|
|
|
BOOL ignore_rotation )
|
Release 961201
Sat Nov 30 19:21:17 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [configure]
Re-generated with autoconf 2.11. Let me know if you have
problems.
* [controls/listbox.c] [controls/oldlbox.c]
Listboxes rewritten from scratch. Moved old code still used by
comboboxes to oldlbox.c
* [misc/registry.c]
Use temporary file when saving registry.
* [windows/dialog.c]
Implemented Win32 version of DlgDirList() and DlgDirListComboBox().
* [windows/winproc.c]
Added translation for listbox Win32 messages.
Sat Nov 30 21:00:00 Alex Korobka <alex@trantor.pharm.sunysb.edu>
* [controls/widgets.c] [controls/button.c]
Fixed some incompatibilities with CTL3D DLL.
* [windows/dialog.c]
Made dialog windows fit into the desktop.
* [misc/winsock.c] [misc/winsock_async.c]
New Winsock engine.
* [windows/message.c]
GetMessage() fixes.
* [windows/queue.c] [windows/hook.c] [windows/win.c]
SetMessageQueue() fixes.
Fri Nov 29 10:25:12 1996 Slaven Rezic <eserte@cs.tu-berlin.de>
* [objects/text.c]
DrawText16(): Fixed return value.
Tue Nov 26 14:47:09 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [files/profile.c] [*/*]
Added Win32 profile functions, updated to new naming standard.
* [objects/font.c] [if1632/thunk.c] [include/windows.h]
Added EnumFonts32*, EnumFontFamiliesEx*, changed prototypes and
structures.
* [misc/ole2nls.c] [if1632/thunk.c]
Added EnumSystemLocales() (winhelp.exe).
* [misc/registry.c]
Added Windows 3.1 registry loader supplied by Tor Sjxwall, tor@sn.no
* [win32/file.c]
Partially fixed CreateFileMapping(), added UnmapViewOfFile().
Sat Nov 23 23:36:05 1996 Ronan Waide <waider@waider.ie>
* [misc/shell.c]
Fixed some FIXMEs relating to ShellExec() and FindExecutable().
* [misc/main.c]
Implemented a few more of the SystemParametersInfo() cases.
Tue Nov 19 01:24:34 1996 Philippe De Muyter <phdm@info.ucl.ac.be>
* [include/keyboard.h]
New file, new macro WINE_VKEY_MAPPINGS (using code taken from event.c).
* [include/windows.h]
New [VK_A, VK_Z] and [VK_0, VK9] macros.
* [misc/keyboard.c]
Fixes in KeyTable and ToAscii.
* [objects/font.c]
FONT_init : Give default value for MSWIN "system" font.
FONT_MatchFont : Do not try every size of a font family if the
family does not exist.
* [windows/event.c]
lastEventChar hack removed.
KeyStateTable replaced by InputKeyStateTable (maintained in event.c)
and QueueKeyStateTable (maintained in message.c).
EVENT_key : Corrections to the extended bit setting.
* [windows/message.c] [windows/keyboard.c]
Implementation of a new QueueKeyStateTable : table of key states
valid when messages are retrieved by GetMessage or PeekMessage,
and valid for TranslateMessage.
TranslateMessage : Convert WM*KEY messages using QueueKeyStateTable
and ToAscii.
Mon Nov 18 16:59:01 1996 Robert Pouliot <krynos@clic.net>
* [graphics/Makefile.in] [graphics/wing.c]
[if1632/wing.spec]
Some functions for WinG support, mostly empty stubs.
* [misc/crtdll.c] [if1632/crtdll.spec]
Many functions added to CRTDLL, mostly calls to Unix C library.
1996-12-01 18:17:47 +01:00
|
|
|
{
|
2009-02-03 10:55:19 +01:00
|
|
|
DC *dc;
|
2001-09-12 22:21:06 +02:00
|
|
|
DWORD ret;
|
2011-10-20 16:34:08 +02:00
|
|
|
PHYSDEV dev;
|
2001-09-12 22:21:06 +02:00
|
|
|
|
2021-08-27 14:51:53 +02:00
|
|
|
TRACE( "(%p, %04x, %04x, %p, %d, %p, %p)\n", hdc, ch, format, metrics, size, buffer, mat2 );
|
2001-09-12 22:21:06 +02:00
|
|
|
|
2021-08-27 14:51:53 +02:00
|
|
|
if (!mat2) return GDI_ERROR;
|
2009-02-03 10:55:19 +01:00
|
|
|
|
|
|
|
dc = get_dc_ptr(hdc);
|
2001-09-12 22:21:06 +02:00
|
|
|
if(!dc) return GDI_ERROR;
|
|
|
|
|
2011-10-20 16:34:08 +02:00
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline );
|
2021-08-27 14:51:53 +02:00
|
|
|
ret = dev->funcs->pGetGlyphOutline( dev, ch & 0xffff, format, metrics, size, buffer, mat2 );
|
2008-02-05 21:16:27 +01:00
|
|
|
release_dc_ptr( dc );
|
2001-09-12 22:21:06 +02:00
|
|
|
return ret;
|
Release 961201
Sat Nov 30 19:21:17 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [configure]
Re-generated with autoconf 2.11. Let me know if you have
problems.
* [controls/listbox.c] [controls/oldlbox.c]
Listboxes rewritten from scratch. Moved old code still used by
comboboxes to oldlbox.c
* [misc/registry.c]
Use temporary file when saving registry.
* [windows/dialog.c]
Implemented Win32 version of DlgDirList() and DlgDirListComboBox().
* [windows/winproc.c]
Added translation for listbox Win32 messages.
Sat Nov 30 21:00:00 Alex Korobka <alex@trantor.pharm.sunysb.edu>
* [controls/widgets.c] [controls/button.c]
Fixed some incompatibilities with CTL3D DLL.
* [windows/dialog.c]
Made dialog windows fit into the desktop.
* [misc/winsock.c] [misc/winsock_async.c]
New Winsock engine.
* [windows/message.c]
GetMessage() fixes.
* [windows/queue.c] [windows/hook.c] [windows/win.c]
SetMessageQueue() fixes.
Fri Nov 29 10:25:12 1996 Slaven Rezic <eserte@cs.tu-berlin.de>
* [objects/text.c]
DrawText16(): Fixed return value.
Tue Nov 26 14:47:09 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [files/profile.c] [*/*]
Added Win32 profile functions, updated to new naming standard.
* [objects/font.c] [if1632/thunk.c] [include/windows.h]
Added EnumFonts32*, EnumFontFamiliesEx*, changed prototypes and
structures.
* [misc/ole2nls.c] [if1632/thunk.c]
Added EnumSystemLocales() (winhelp.exe).
* [misc/registry.c]
Added Windows 3.1 registry loader supplied by Tor Sjxwall, tor@sn.no
* [win32/file.c]
Partially fixed CreateFileMapping(), added UnmapViewOfFile().
Sat Nov 23 23:36:05 1996 Ronan Waide <waider@waider.ie>
* [misc/shell.c]
Fixed some FIXMEs relating to ShellExec() and FindExecutable().
* [misc/main.c]
Implemented a few more of the SystemParametersInfo() cases.
Tue Nov 19 01:24:34 1996 Philippe De Muyter <phdm@info.ucl.ac.be>
* [include/keyboard.h]
New file, new macro WINE_VKEY_MAPPINGS (using code taken from event.c).
* [include/windows.h]
New [VK_A, VK_Z] and [VK_0, VK9] macros.
* [misc/keyboard.c]
Fixes in KeyTable and ToAscii.
* [objects/font.c]
FONT_init : Give default value for MSWIN "system" font.
FONT_MatchFont : Do not try every size of a font family if the
family does not exist.
* [windows/event.c]
lastEventChar hack removed.
KeyStateTable replaced by InputKeyStateTable (maintained in event.c)
and QueueKeyStateTable (maintained in message.c).
EVENT_key : Corrections to the extended bit setting.
* [windows/message.c] [windows/keyboard.c]
Implementation of a new QueueKeyStateTable : table of key states
valid when messages are retrieved by GetMessage or PeekMessage,
and valid for TranslateMessage.
TranslateMessage : Convert WM*KEY messages using QueueKeyStateTable
and ToAscii.
Mon Nov 18 16:59:01 1996 Robert Pouliot <krynos@clic.net>
* [graphics/Makefile.in] [graphics/wing.c]
[if1632/wing.spec]
Some functions for WinG support, mostly empty stubs.
* [misc/crtdll.c] [if1632/crtdll.spec]
Many functions added to CRTDLL, mostly calls to Unix C library.
1996-12-01 18:17:47 +01:00
|
|
|
}
|
1994-05-18 20:29:32 +02:00
|
|
|
|
Release 961201
Sat Nov 30 19:21:17 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [configure]
Re-generated with autoconf 2.11. Let me know if you have
problems.
* [controls/listbox.c] [controls/oldlbox.c]
Listboxes rewritten from scratch. Moved old code still used by
comboboxes to oldlbox.c
* [misc/registry.c]
Use temporary file when saving registry.
* [windows/dialog.c]
Implemented Win32 version of DlgDirList() and DlgDirListComboBox().
* [windows/winproc.c]
Added translation for listbox Win32 messages.
Sat Nov 30 21:00:00 Alex Korobka <alex@trantor.pharm.sunysb.edu>
* [controls/widgets.c] [controls/button.c]
Fixed some incompatibilities with CTL3D DLL.
* [windows/dialog.c]
Made dialog windows fit into the desktop.
* [misc/winsock.c] [misc/winsock_async.c]
New Winsock engine.
* [windows/message.c]
GetMessage() fixes.
* [windows/queue.c] [windows/hook.c] [windows/win.c]
SetMessageQueue() fixes.
Fri Nov 29 10:25:12 1996 Slaven Rezic <eserte@cs.tu-berlin.de>
* [objects/text.c]
DrawText16(): Fixed return value.
Tue Nov 26 14:47:09 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [files/profile.c] [*/*]
Added Win32 profile functions, updated to new naming standard.
* [objects/font.c] [if1632/thunk.c] [include/windows.h]
Added EnumFonts32*, EnumFontFamiliesEx*, changed prototypes and
structures.
* [misc/ole2nls.c] [if1632/thunk.c]
Added EnumSystemLocales() (winhelp.exe).
* [misc/registry.c]
Added Windows 3.1 registry loader supplied by Tor Sjxwall, tor@sn.no
* [win32/file.c]
Partially fixed CreateFileMapping(), added UnmapViewOfFile().
Sat Nov 23 23:36:05 1996 Ronan Waide <waider@waider.ie>
* [misc/shell.c]
Fixed some FIXMEs relating to ShellExec() and FindExecutable().
* [misc/main.c]
Implemented a few more of the SystemParametersInfo() cases.
Tue Nov 19 01:24:34 1996 Philippe De Muyter <phdm@info.ucl.ac.be>
* [include/keyboard.h]
New file, new macro WINE_VKEY_MAPPINGS (using code taken from event.c).
* [include/windows.h]
New [VK_A, VK_Z] and [VK_0, VK9] macros.
* [misc/keyboard.c]
Fixes in KeyTable and ToAscii.
* [objects/font.c]
FONT_init : Give default value for MSWIN "system" font.
FONT_MatchFont : Do not try every size of a font family if the
family does not exist.
* [windows/event.c]
lastEventChar hack removed.
KeyStateTable replaced by InputKeyStateTable (maintained in event.c)
and QueueKeyStateTable (maintained in message.c).
EVENT_key : Corrections to the extended bit setting.
* [windows/message.c] [windows/keyboard.c]
Implementation of a new QueueKeyStateTable : table of key states
valid when messages are retrieved by GetMessage or PeekMessage,
and valid for TranslateMessage.
TranslateMessage : Convert WM*KEY messages using QueueKeyStateTable
and ToAscii.
Mon Nov 18 16:59:01 1996 Robert Pouliot <krynos@clic.net>
* [graphics/Makefile.in] [graphics/wing.c]
[if1632/wing.spec]
Some functions for WinG support, mostly empty stubs.
* [misc/crtdll.c] [if1632/crtdll.spec]
Many functions added to CRTDLL, mostly calls to Unix C library.
1996-12-01 18:17:47 +01:00
|
|
|
|
2020-10-27 14:25:47 +01:00
|
|
|
#define NE_FFLAGS_LIBMODULE 0x8000
|
|
|
|
#define NE_OSFLAGS_WINDOWS 0x02
|
|
|
|
|
|
|
|
static const char dos_string[0x40] = "This is a TrueType resource file";
|
|
|
|
static const char FONTRES[] = {'F','O','N','T','R','E','S',':'};
|
|
|
|
|
|
|
|
#include <pshpack1.h>
|
|
|
|
struct fontdir
|
|
|
|
{
|
|
|
|
WORD num_of_resources;
|
|
|
|
WORD res_id;
|
|
|
|
WORD dfVersion;
|
|
|
|
DWORD dfSize;
|
|
|
|
CHAR dfCopyright[60];
|
|
|
|
WORD dfType;
|
|
|
|
WORD dfPoints;
|
|
|
|
WORD dfVertRes;
|
|
|
|
WORD dfHorizRes;
|
|
|
|
WORD dfAscent;
|
|
|
|
WORD dfInternalLeading;
|
|
|
|
WORD dfExternalLeading;
|
|
|
|
BYTE dfItalic;
|
|
|
|
BYTE dfUnderline;
|
|
|
|
BYTE dfStrikeOut;
|
|
|
|
WORD dfWeight;
|
|
|
|
BYTE dfCharSet;
|
|
|
|
WORD dfPixWidth;
|
|
|
|
WORD dfPixHeight;
|
|
|
|
BYTE dfPitchAndFamily;
|
|
|
|
WORD dfAvgWidth;
|
|
|
|
WORD dfMaxWidth;
|
|
|
|
BYTE dfFirstChar;
|
|
|
|
BYTE dfLastChar;
|
|
|
|
BYTE dfDefaultChar;
|
|
|
|
BYTE dfBreakChar;
|
|
|
|
WORD dfWidthBytes;
|
|
|
|
DWORD dfDevice;
|
|
|
|
DWORD dfFace;
|
|
|
|
DWORD dfReserved;
|
|
|
|
CHAR szFaceName[LF_FACESIZE];
|
|
|
|
};
|
|
|
|
#include <poppack.h>
|
|
|
|
|
|
|
|
#include <pshpack2.h>
|
|
|
|
|
|
|
|
struct ne_typeinfo
|
|
|
|
{
|
|
|
|
WORD type_id;
|
|
|
|
WORD count;
|
|
|
|
DWORD res;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ne_nameinfo
|
|
|
|
{
|
|
|
|
WORD off;
|
|
|
|
WORD len;
|
|
|
|
WORD flags;
|
|
|
|
WORD id;
|
|
|
|
DWORD res;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct rsrc_tab
|
|
|
|
{
|
|
|
|
WORD align;
|
|
|
|
struct ne_typeinfo fontdir_type;
|
|
|
|
struct ne_nameinfo fontdir_name;
|
|
|
|
struct ne_typeinfo scalable_type;
|
|
|
|
struct ne_nameinfo scalable_name;
|
|
|
|
WORD end_of_rsrc;
|
|
|
|
BYTE fontdir_res_name[8];
|
|
|
|
};
|
|
|
|
|
|
|
|
#include <poppack.h>
|
|
|
|
|
|
|
|
static BOOL create_fot( const WCHAR *resource, const WCHAR *font_file, const struct fontdir *fontdir )
|
|
|
|
{
|
|
|
|
BOOL ret = FALSE;
|
|
|
|
HANDLE file;
|
|
|
|
DWORD size, written;
|
|
|
|
BYTE *ptr, *start;
|
|
|
|
BYTE import_name_len, res_name_len, non_res_name_len, font_file_len;
|
|
|
|
char *font_fileA, *last_part, *ext;
|
|
|
|
IMAGE_DOS_HEADER dos;
|
|
|
|
IMAGE_OS2_HEADER ne =
|
|
|
|
{
|
|
|
|
IMAGE_OS2_SIGNATURE, 5, 1, 0, 0, 0, NE_FFLAGS_LIBMODULE, 0,
|
|
|
|
0, 0, 0, 0, 0, 0,
|
|
|
|
0, sizeof(ne), sizeof(ne), 0, 0, 0, 0,
|
|
|
|
0, 4, 2, NE_OSFLAGS_WINDOWS, 0, 0, 0, 0, 0x300
|
|
|
|
};
|
|
|
|
struct rsrc_tab rsrc_tab =
|
|
|
|
{
|
|
|
|
4,
|
|
|
|
{ 0x8007, 1, 0 },
|
|
|
|
{ 0, 0, 0x0c50, 0x2c, 0 },
|
|
|
|
{ 0x80cc, 1, 0 },
|
|
|
|
{ 0, 0, 0x0c50, 0x8001, 0 },
|
|
|
|
0,
|
|
|
|
{ 7,'F','O','N','T','D','I','R'}
|
|
|
|
};
|
|
|
|
|
|
|
|
memset( &dos, 0, sizeof(dos) );
|
|
|
|
dos.e_magic = IMAGE_DOS_SIGNATURE;
|
|
|
|
dos.e_lfanew = sizeof(dos) + sizeof(dos_string);
|
|
|
|
|
|
|
|
/* import name is last part\0, resident name is last part without extension
|
|
|
|
non-resident name is "FONTRES:" + lfFaceName */
|
|
|
|
|
|
|
|
font_file_len = WideCharToMultiByte( CP_ACP, 0, font_file, -1, NULL, 0, NULL, NULL );
|
|
|
|
font_fileA = HeapAlloc( GetProcessHeap(), 0, font_file_len );
|
|
|
|
WideCharToMultiByte( CP_ACP, 0, font_file, -1, font_fileA, font_file_len, NULL, NULL );
|
|
|
|
|
|
|
|
last_part = strrchr( font_fileA, '\\' );
|
|
|
|
if (last_part) last_part++;
|
|
|
|
else last_part = font_fileA;
|
|
|
|
import_name_len = strlen( last_part ) + 1;
|
|
|
|
|
|
|
|
ext = strchr( last_part, '.' );
|
|
|
|
if (ext) res_name_len = ext - last_part;
|
|
|
|
else res_name_len = import_name_len - 1;
|
|
|
|
|
|
|
|
non_res_name_len = sizeof( FONTRES ) + strlen( fontdir->szFaceName );
|
|
|
|
|
|
|
|
ne.ne_cbnrestab = 1 + non_res_name_len + 2 + 1; /* len + string + (WORD) ord_num + 1 byte eod */
|
|
|
|
ne.ne_restab = ne.ne_rsrctab + sizeof(rsrc_tab);
|
|
|
|
ne.ne_modtab = ne.ne_imptab = ne.ne_restab + 1 + res_name_len + 2 + 3; /* len + string + (WORD) ord_num + 3 bytes eod */
|
|
|
|
ne.ne_enttab = ne.ne_imptab + 1 + import_name_len; /* len + string */
|
|
|
|
ne.ne_cbenttab = 2;
|
|
|
|
ne.ne_nrestab = ne.ne_enttab + ne.ne_cbenttab + 2 + dos.e_lfanew; /* there are 2 bytes of 0 after entry tab */
|
|
|
|
|
|
|
|
rsrc_tab.scalable_name.off = (ne.ne_nrestab + ne.ne_cbnrestab + 0xf) >> 4;
|
|
|
|
rsrc_tab.scalable_name.len = (font_file_len + 0xf) >> 4;
|
|
|
|
rsrc_tab.fontdir_name.off = rsrc_tab.scalable_name.off + rsrc_tab.scalable_name.len;
|
|
|
|
rsrc_tab.fontdir_name.len = (fontdir->dfSize + 0xf) >> 4;
|
|
|
|
|
|
|
|
size = (rsrc_tab.fontdir_name.off + rsrc_tab.fontdir_name.len) << 4;
|
|
|
|
start = ptr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
|
|
|
|
|
|
|
|
if (!ptr)
|
|
|
|
{
|
|
|
|
HeapFree( GetProcessHeap(), 0, font_fileA );
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy( ptr, &dos, sizeof(dos) );
|
|
|
|
memcpy( ptr + sizeof(dos), dos_string, sizeof(dos_string) );
|
|
|
|
memcpy( ptr + dos.e_lfanew, &ne, sizeof(ne) );
|
|
|
|
|
|
|
|
ptr = start + dos.e_lfanew + ne.ne_rsrctab;
|
|
|
|
memcpy( ptr, &rsrc_tab, sizeof(rsrc_tab) );
|
|
|
|
|
|
|
|
ptr = start + dos.e_lfanew + ne.ne_restab;
|
|
|
|
*ptr++ = res_name_len;
|
|
|
|
memcpy( ptr, last_part, res_name_len );
|
|
|
|
|
|
|
|
ptr = start + dos.e_lfanew + ne.ne_imptab;
|
|
|
|
*ptr++ = import_name_len;
|
|
|
|
memcpy( ptr, last_part, import_name_len );
|
|
|
|
|
|
|
|
ptr = start + ne.ne_nrestab;
|
|
|
|
*ptr++ = non_res_name_len;
|
|
|
|
memcpy( ptr, FONTRES, sizeof(FONTRES) );
|
|
|
|
memcpy( ptr + sizeof(FONTRES), fontdir->szFaceName, strlen( fontdir->szFaceName ) );
|
|
|
|
|
|
|
|
ptr = start + (rsrc_tab.scalable_name.off << 4);
|
|
|
|
memcpy( ptr, font_fileA, font_file_len );
|
|
|
|
|
|
|
|
ptr = start + (rsrc_tab.fontdir_name.off << 4);
|
|
|
|
memcpy( ptr, fontdir, fontdir->dfSize );
|
|
|
|
|
|
|
|
file = CreateFileW( resource, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
|
|
|
|
if (file != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
if (WriteFile( file, start, size, &written, NULL ) && written == size)
|
|
|
|
ret = TRUE;
|
|
|
|
CloseHandle( file );
|
|
|
|
}
|
|
|
|
|
|
|
|
HeapFree( GetProcessHeap(), 0, start );
|
|
|
|
HeapFree( GetProcessHeap(), 0, font_fileA );
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
1997-06-16 19:43:53 +02:00
|
|
|
/***********************************************************************
|
2001-02-14 23:56:38 +01:00
|
|
|
* CreateScalableFontResourceW (GDI32.@)
|
Release 961201
Sat Nov 30 19:21:17 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [configure]
Re-generated with autoconf 2.11. Let me know if you have
problems.
* [controls/listbox.c] [controls/oldlbox.c]
Listboxes rewritten from scratch. Moved old code still used by
comboboxes to oldlbox.c
* [misc/registry.c]
Use temporary file when saving registry.
* [windows/dialog.c]
Implemented Win32 version of DlgDirList() and DlgDirListComboBox().
* [windows/winproc.c]
Added translation for listbox Win32 messages.
Sat Nov 30 21:00:00 Alex Korobka <alex@trantor.pharm.sunysb.edu>
* [controls/widgets.c] [controls/button.c]
Fixed some incompatibilities with CTL3D DLL.
* [windows/dialog.c]
Made dialog windows fit into the desktop.
* [misc/winsock.c] [misc/winsock_async.c]
New Winsock engine.
* [windows/message.c]
GetMessage() fixes.
* [windows/queue.c] [windows/hook.c] [windows/win.c]
SetMessageQueue() fixes.
Fri Nov 29 10:25:12 1996 Slaven Rezic <eserte@cs.tu-berlin.de>
* [objects/text.c]
DrawText16(): Fixed return value.
Tue Nov 26 14:47:09 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [files/profile.c] [*/*]
Added Win32 profile functions, updated to new naming standard.
* [objects/font.c] [if1632/thunk.c] [include/windows.h]
Added EnumFonts32*, EnumFontFamiliesEx*, changed prototypes and
structures.
* [misc/ole2nls.c] [if1632/thunk.c]
Added EnumSystemLocales() (winhelp.exe).
* [misc/registry.c]
Added Windows 3.1 registry loader supplied by Tor Sjxwall, tor@sn.no
* [win32/file.c]
Partially fixed CreateFileMapping(), added UnmapViewOfFile().
Sat Nov 23 23:36:05 1996 Ronan Waide <waider@waider.ie>
* [misc/shell.c]
Fixed some FIXMEs relating to ShellExec() and FindExecutable().
* [misc/main.c]
Implemented a few more of the SystemParametersInfo() cases.
Tue Nov 19 01:24:34 1996 Philippe De Muyter <phdm@info.ucl.ac.be>
* [include/keyboard.h]
New file, new macro WINE_VKEY_MAPPINGS (using code taken from event.c).
* [include/windows.h]
New [VK_A, VK_Z] and [VK_0, VK9] macros.
* [misc/keyboard.c]
Fixes in KeyTable and ToAscii.
* [objects/font.c]
FONT_init : Give default value for MSWIN "system" font.
FONT_MatchFont : Do not try every size of a font family if the
family does not exist.
* [windows/event.c]
lastEventChar hack removed.
KeyStateTable replaced by InputKeyStateTable (maintained in event.c)
and QueueKeyStateTable (maintained in message.c).
EVENT_key : Corrections to the extended bit setting.
* [windows/message.c] [windows/keyboard.c]
Implementation of a new QueueKeyStateTable : table of key states
valid when messages are retrieved by GetMessage or PeekMessage,
and valid for TranslateMessage.
TranslateMessage : Convert WM*KEY messages using QueueKeyStateTable
and ToAscii.
Mon Nov 18 16:59:01 1996 Robert Pouliot <krynos@clic.net>
* [graphics/Makefile.in] [graphics/wing.c]
[if1632/wing.spec]
Some functions for WinG support, mostly empty stubs.
* [misc/crtdll.c] [if1632/crtdll.spec]
Many functions added to CRTDLL, mostly calls to Unix C library.
1996-12-01 18:17:47 +01:00
|
|
|
*/
|
2012-03-28 15:49:24 +02:00
|
|
|
BOOL WINAPI CreateScalableFontResourceW( DWORD hidden, LPCWSTR resource_file,
|
|
|
|
LPCWSTR font_file, LPCWSTR font_path )
|
|
|
|
{
|
2020-10-27 14:25:47 +01:00
|
|
|
struct fontdir fontdir = { 0 };
|
|
|
|
struct gdi_font *font = NULL;
|
|
|
|
WCHAR path[MAX_PATH];
|
|
|
|
|
2012-03-28 15:49:24 +02:00
|
|
|
TRACE("(%d, %s, %s, %s)\n", hidden, debugstr_w(resource_file),
|
|
|
|
debugstr_w(font_file), debugstr_w(font_path) );
|
|
|
|
|
2020-10-20 22:07:06 +02:00
|
|
|
if (!font_funcs) return FALSE;
|
2020-10-27 14:25:47 +01:00
|
|
|
|
|
|
|
if (!font_file) goto done;
|
|
|
|
if (font_path && font_path[0])
|
|
|
|
{
|
2020-11-05 10:44:16 +01:00
|
|
|
int len = lstrlenW( font_path ) + lstrlenW( font_file ) + 2;
|
2020-10-27 14:25:47 +01:00
|
|
|
if (len > MAX_PATH) goto done;
|
|
|
|
lstrcpynW( path, font_path, MAX_PATH );
|
2020-11-06 12:08:16 +01:00
|
|
|
lstrcatW( path, L"\\" );
|
2020-11-05 10:44:16 +01:00
|
|
|
lstrcatW( path, font_file );
|
2020-10-27 14:25:47 +01:00
|
|
|
}
|
|
|
|
else if (!GetFullPathNameW( font_file, MAX_PATH, path, NULL )) goto done;
|
|
|
|
|
|
|
|
if (!(font = alloc_gdi_font( path, NULL, 0 ))) goto done;
|
|
|
|
font->lf.lfHeight = 100;
|
|
|
|
if (!font_funcs->load_font( font )) goto done;
|
|
|
|
if (!font_funcs->set_outline_text_metrics( font )) goto done;
|
|
|
|
|
|
|
|
if (!(font->otm.otmTextMetrics.tmPitchAndFamily & TMPF_TRUETYPE)) goto done;
|
|
|
|
|
|
|
|
fontdir.num_of_resources = 1;
|
|
|
|
fontdir.res_id = 0;
|
|
|
|
fontdir.dfVersion = 0x200;
|
|
|
|
fontdir.dfSize = sizeof(fontdir);
|
|
|
|
strcpy( fontdir.dfCopyright, "Wine fontdir" );
|
|
|
|
fontdir.dfType = 0x4003; /* 0x0080 set if private */
|
|
|
|
fontdir.dfPoints = font->otm.otmEMSquare;
|
|
|
|
fontdir.dfVertRes = 72;
|
|
|
|
fontdir.dfHorizRes = 72;
|
|
|
|
fontdir.dfAscent = font->otm.otmTextMetrics.tmAscent;
|
|
|
|
fontdir.dfInternalLeading = font->otm.otmTextMetrics.tmInternalLeading;
|
|
|
|
fontdir.dfExternalLeading = font->otm.otmTextMetrics.tmExternalLeading;
|
|
|
|
fontdir.dfItalic = font->otm.otmTextMetrics.tmItalic;
|
|
|
|
fontdir.dfUnderline = font->otm.otmTextMetrics.tmUnderlined;
|
|
|
|
fontdir.dfStrikeOut = font->otm.otmTextMetrics.tmStruckOut;
|
|
|
|
fontdir.dfWeight = font->otm.otmTextMetrics.tmWeight;
|
|
|
|
fontdir.dfCharSet = font->otm.otmTextMetrics.tmCharSet;
|
|
|
|
fontdir.dfPixWidth = 0;
|
|
|
|
fontdir.dfPixHeight = font->otm.otmTextMetrics.tmHeight;
|
|
|
|
fontdir.dfPitchAndFamily = font->otm.otmTextMetrics.tmPitchAndFamily;
|
|
|
|
fontdir.dfAvgWidth = font->otm.otmTextMetrics.tmAveCharWidth;
|
|
|
|
fontdir.dfMaxWidth = font->otm.otmTextMetrics.tmMaxCharWidth;
|
|
|
|
fontdir.dfFirstChar = font->otm.otmTextMetrics.tmFirstChar;
|
|
|
|
fontdir.dfLastChar = font->otm.otmTextMetrics.tmLastChar;
|
|
|
|
fontdir.dfDefaultChar = font->otm.otmTextMetrics.tmDefaultChar;
|
|
|
|
fontdir.dfBreakChar = font->otm.otmTextMetrics.tmBreakChar;
|
|
|
|
fontdir.dfWidthBytes = 0;
|
|
|
|
fontdir.dfDevice = 0;
|
|
|
|
fontdir.dfFace = FIELD_OFFSET( struct fontdir, szFaceName );
|
|
|
|
fontdir.dfReserved = 0;
|
|
|
|
WideCharToMultiByte( CP_ACP, 0, (WCHAR *)font->otm.otmpFamilyName, -1,
|
|
|
|
fontdir.szFaceName, LF_FACESIZE, NULL, NULL );
|
2020-12-09 21:41:27 +01:00
|
|
|
free_gdi_font( font );
|
2020-10-27 14:25:47 +01:00
|
|
|
|
|
|
|
if (hidden) fontdir.dfType |= 0x80;
|
|
|
|
return create_fot( resource_file, font_file, &fontdir );
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (font) free_gdi_font( font );
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
|
|
return FALSE;
|
1996-11-17 19:59:11 +01:00
|
|
|
}
|
|
|
|
|
1997-03-05 09:22:35 +01:00
|
|
|
/*************************************************************************
|
2021-09-10 14:28:04 +02:00
|
|
|
* NtGdiGetKerningPairs (win32u.@)
|
1997-03-05 09:22:35 +01:00
|
|
|
*/
|
2021-09-10 14:28:04 +02:00
|
|
|
DWORD WINAPI NtGdiGetKerningPairs( HDC hdc, DWORD count, KERNINGPAIR *kern_pair )
|
1997-03-05 09:22:35 +01:00
|
|
|
{
|
2006-09-27 16:43:23 +02:00
|
|
|
DC *dc;
|
2011-10-20 16:39:53 +02:00
|
|
|
DWORD ret;
|
|
|
|
PHYSDEV dev;
|
2006-01-12 11:54:20 +01:00
|
|
|
|
2021-08-27 14:51:54 +02:00
|
|
|
TRACE( "(%p,%d,%p)\n", hdc, count, kern_pair );
|
2006-01-12 11:54:20 +01:00
|
|
|
|
2021-08-27 14:51:54 +02:00
|
|
|
if (!count && kern_pair)
|
2006-09-27 16:43:23 +02:00
|
|
|
{
|
2021-08-27 14:51:54 +02:00
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
2006-09-27 16:43:23 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-08-27 14:51:54 +02:00
|
|
|
dc = get_dc_ptr( hdc );
|
2006-09-20 17:18:51 +02:00
|
|
|
if (!dc) return 0;
|
|
|
|
|
2011-10-20 16:39:53 +02:00
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
|
2021-08-27 14:51:54 +02:00
|
|
|
ret = dev->funcs->pGetKerningPairs( dev, count, kern_pair );
|
2008-02-05 21:16:27 +01:00
|
|
|
release_dc_ptr( dc );
|
2006-09-20 17:18:51 +02:00
|
|
|
return ret;
|
1997-03-05 09:22:35 +01:00
|
|
|
}
|
1997-06-16 19:43:53 +02:00
|
|
|
|
Release 980809
Sat Aug 8 19:11:46 1998 Marcus Meissner <marcus@jet.franken.de>
* [*/*]
Added some missing WINAPI and some missing prototypes for
functions.
* [controls/static.c]
Got rid of the MODULE32_LookupHMODULE error showing up for every
message box.
* [windows/winproc.c]
WM_NOTIFY 16->32 mapping (AOL Instant Messenger or however it is called).
* [misc/winsock.c]
hostent/servent/protoent should not use the same static buffers.
(has broken nt3.15 finger.exe which does hp=gethostbyname(), then
getservbyname("finger","tcp") and the references hp->h_addr_list[0]).
Sat Aug 8 13:21:24 1998 Alexandre Julliard <julliard@lrc.epfl.ch>
* [include/server.h] [tools/make_requests] [server/request.c]
[server/trace.c]
Automated part of the client/server request code generation.
Added tracing of client/server communication.
* [scheduler/*.c] [server/process.c]
Added support for server-side handles.
* [scheduler/thread.c]
Added DLL_THREAD_ATTACH/DETACH notifications.
* [configure.in]
Added check for -lsocket.
* [windows/winproc.c]
Return the thunk address in WINPROC_GetProc if the function types
don't match.
Sat Aug 8 02:44:04 1998 Douglas Ridgway <ridgway@winehq.com>
* [windows/winproc.c][windows/win.c][windows/message.c]
Documentation for CallWindowProc, SetWindowLong, DispatchMessage,
WaitMessage, GetMessage, and PeekMessage.
Sat Aug 8 01:00:00 1998 Juergen Schmied <juergen.schmied@metronet.de>
* [controls/commctrl.c][controls/widgets.c][include/builtin32.h]
[include/commctrl.h][relay32/builtin32.c][relay32/comctl32.spec]
[tools/build.c] [relay32/shell32.spec]
Added the functionality of the LibMain function. The common
controls are properly initialized now.
* [controls/treeview.c][memory/atom.c][scheduler/thread.c][windows/class.c]
[windows/msgbox.c][windows/win.c]
Put TRACE in, put SetLastError() in.
* [include/interfaces.h]
Added IClassFactory::LockServer.
* [include/ole2.h]
Added struct for LPOLEMENUGROUPWIDTHS32, HOLEMENU32.
* [include/shell.h][include/shlobj.h][misc/shell.c][ole/folders.c]
Reorganized and many structs and classes (IShellBrowser,IShellView)
added. shell32.dll should work in many cases now.
Started SHGetFileInfoA implementeation, rewrote SHGetPathFromIDList32A.
New Shell32LibMain started ShellIconCache Implementation.
* [misc/shellord.c]
Rewrote ILCombine, ILGetSize
New stubs SHFind_InitMenuPopup, FileMenu_Create, ShellExecuteEx,
SHSetInstanceExplorer, SHGetInstanceExplorer, SHFreeUnusedLibraries.
* [include/winerror.h]
Class and window related error codes added.
* [memory/heap.c]
Changed lstrlen32A to strlen to get rid of milions of TRACE lines.
* [misc/ddeml.c]
First lines for DdeCreateStringHandle32A / DdeFreeStringHandle32.
* [misc/network.c][relay32/mpr.spec]
Fixed some bugs, changed ordinals.
* [windows/class.c]
Workarounds for incorrect hInstance handling. Fixes parts of
MSWord95/Excel95 and Money95.
Thu Aug 6 21:05:35 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
* [windows/nonclient.c][misc/tweak.c][include/tweak.h]
[documentation/win95look]
Removed some tweak variables. They are no longer needed.
* [files/dos_fs.c]
Added check for null pointer in DOSFS_GetDevice().
* [controls/tooltips.c][include/commctrl.h]
Improved tooltips.
* [controls/status.c][include/commctrl.h]
Cleaned up code and added tooltip support.
* [controls/toolbar.c][include/commctrl.h]
Added tooltip support.
* [documentation/common_controls]
Updated.
Thu Aug 6 00:05:22 1998 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
* [include/ver.h] [misc/ver.c]
Write VIF_BUFFTOOSMALL, not VIF_BUFTOSMALL.
* [debugger/hash.c] [debugger/stabs.c]
Make debug output more friendly for posting.
* [files/file.c]
Partial implementation of OF_SHARE_EXCLUSIVE.
Needed for Quicklogic/QuickChip (InstallShield).
* [files/profile.c]
When a cached-only entry is found, return it.
* [graphics/x11drv/xfont.c]
Accept a space as delimiter for a fontname and inhibit overrun
(Make xplasim.ex from the Phillips Coolrunner CPLD suite proceed).
* [miscemu/main.c]
Delay setting IF1632_CallLargeStack after loading the executables.
Stops fpgaexp.exe from the Viewlogic FPGA suite from crashing when
showing the Blinker error Message Box.
* [misc/network.c]
Make WNetGetConnection16 recognise a CDROM as a local drive.
* [multimedia/mmsystem.c]
Preliminary check for MCI_ALL_DEVICE_ID in MCI_Close by a FIXME.
Tue Aug 4 21:15:23 1998 James Juran <jrj120@psu.edu>
* [ole/ole2nls.c]
Fixed bug in CompareString32A. strcmp() doesn't necessarily
return -1, 0, or 1, which the previous code depended on.
Changed name of is_punctuation to OLE2NLS_isPunctuation.
Made NORM_IGNOREWIDTH not print a FIXME message in
LCMapString32A.
Other debugging messages, documentation, and code cleanups.
* [objects/font.c] [relay32/gdi32.spec] [include/winerror.h]
Added stub for GetFontData32, and added GDI_ERROR constant
to winerror.h.
Tue Aug 4 07:44:43 1998 Ove Kaaven <ovek@arcticnet.no>
* [multimedia/mmio.c]
Implemented mmioSetBuffer, mmioAdvance, mmioAscend, and
mmioCreateChunk to the best of my knowledge. But watch out,
there's bound to be bugs in there...
* [include/mmsystem.h] [multimedia/mmsystem.c]
Hacked in support for 32-bit multimedia function callbacks.
* [AUTHORS] [misc/shell.c]
Selfishly credited my authorship. Hopefully I'm excused.
* [include/dosexe.h] [include/module.h] [loader/dos/*]
[loader/module.c] [loader/task.c] [Makefile.in]
[configure.in] [Makefile.in]
Added DOS EXE (MZ) loader and virtual machine. Task
structure integration thanks to Ulrich Weigand.
* [files/dos_fs.c]
Work around a null pointer dereference if ioctlGetDeviceInfo-ing
a FILE_DupUnixHandle'd file (i.e. GetStdHandle'd).
* [include/miscemu.h] [include/winnt.h] [loader/main.c]
[memory/global.c] [msdos/dpmi.c] [msdos/dosmem.c]
Added support for DOS memory images, and added
DOSMEM_ResizeBlock() and DOSMEM_Available().
* [msdos/int21.c]
Added support for the DOS virtual machine, tweaked handle
assignment to avoid stdio clashes, forced INT21_FindNext to exit
wildcardless searches after finding one entry, added AH=7, 8, 9,
C, 48, 49, 4A, and 7160 CL=1 (Get Short Filename), and made the
long filename calls only respond if running with with -winver
win95.
* [objects/cursoricon.c]
DestroyCursor32 and DestroyIcon32 should now free the objects
(hopefully) correctly.
Sun Aug 2 21:42:09 1998 Huw D M Davies <daviesh@abacus.physics.ox.ac.uk>
* [graphics/psdrv/*] [include/psdrv.h]
Added PPD file parsing - at the moment it reads a file called
default.ppd from the directory in which you start Wine. Page sizes
other than A4 should now work (landscape may not). All fonts that are
present on your printer (according to the PPD) should be available,
providing you have the AFM files. Fonts should now be the correct size.
Graphics is still basically lines only. See graphics/psdrv/README .
* [misc/printdrv.c]
Yet more Drv[Get/Set]PrinterData fixes.
Fri Jul 31 21:33:22 1998 Per Lindstrm <pelinstr@algonet.se>
* [relay32/crtdll.spec] [misc/crtdll.c]
Added stub for freopen, _findfirst, _findnext, _fstat and _read.
* [files/directory.c]
Modified warning message.
Wed Jul 29 11:25:28 1998 Luiz Otavio L. Zorzella <zorzella@nr.conexware.com>
* [objects/font.c]
Added stub for GetFontData.
* [multimedia/msvideo.c]
Created this file to hold the msvideo.dll calls (and maybe also
msvfw32.dll).
* [objects/cursoricon.c]
Added search in Global Heap for cursor when trying to destroy it
with DestroyCursor16. This test should be done in many (all?)
other functions that use FreeResource.
* [controls/treeview.c] [include/commctrl.h]
Minor correction in name and addition of many placeholders for TVM
messages in TREEVIEW_WindowProc.
* [msdos/dpmi.c]
Fixed a bug in DPMI_xrealloc where in a copy of a memory region
"A" of size "a" to a region "B" of size "b", "b" bytes were being
copied, instead of "a", as the new version does. This both
increases speed, as well as avoids segfaults.
1998-08-09 14:47:43 +02:00
|
|
|
/*************************************************************************
|
2021-08-27 14:51:56 +02:00
|
|
|
* NtGdiGetFontData (win32u.@)
|
2004-02-09 21:47:42 +01:00
|
|
|
*
|
|
|
|
* Retrieve data for TrueType font.
|
Release 980809
Sat Aug 8 19:11:46 1998 Marcus Meissner <marcus@jet.franken.de>
* [*/*]
Added some missing WINAPI and some missing prototypes for
functions.
* [controls/static.c]
Got rid of the MODULE32_LookupHMODULE error showing up for every
message box.
* [windows/winproc.c]
WM_NOTIFY 16->32 mapping (AOL Instant Messenger or however it is called).
* [misc/winsock.c]
hostent/servent/protoent should not use the same static buffers.
(has broken nt3.15 finger.exe which does hp=gethostbyname(), then
getservbyname("finger","tcp") and the references hp->h_addr_list[0]).
Sat Aug 8 13:21:24 1998 Alexandre Julliard <julliard@lrc.epfl.ch>
* [include/server.h] [tools/make_requests] [server/request.c]
[server/trace.c]
Automated part of the client/server request code generation.
Added tracing of client/server communication.
* [scheduler/*.c] [server/process.c]
Added support for server-side handles.
* [scheduler/thread.c]
Added DLL_THREAD_ATTACH/DETACH notifications.
* [configure.in]
Added check for -lsocket.
* [windows/winproc.c]
Return the thunk address in WINPROC_GetProc if the function types
don't match.
Sat Aug 8 02:44:04 1998 Douglas Ridgway <ridgway@winehq.com>
* [windows/winproc.c][windows/win.c][windows/message.c]
Documentation for CallWindowProc, SetWindowLong, DispatchMessage,
WaitMessage, GetMessage, and PeekMessage.
Sat Aug 8 01:00:00 1998 Juergen Schmied <juergen.schmied@metronet.de>
* [controls/commctrl.c][controls/widgets.c][include/builtin32.h]
[include/commctrl.h][relay32/builtin32.c][relay32/comctl32.spec]
[tools/build.c] [relay32/shell32.spec]
Added the functionality of the LibMain function. The common
controls are properly initialized now.
* [controls/treeview.c][memory/atom.c][scheduler/thread.c][windows/class.c]
[windows/msgbox.c][windows/win.c]
Put TRACE in, put SetLastError() in.
* [include/interfaces.h]
Added IClassFactory::LockServer.
* [include/ole2.h]
Added struct for LPOLEMENUGROUPWIDTHS32, HOLEMENU32.
* [include/shell.h][include/shlobj.h][misc/shell.c][ole/folders.c]
Reorganized and many structs and classes (IShellBrowser,IShellView)
added. shell32.dll should work in many cases now.
Started SHGetFileInfoA implementeation, rewrote SHGetPathFromIDList32A.
New Shell32LibMain started ShellIconCache Implementation.
* [misc/shellord.c]
Rewrote ILCombine, ILGetSize
New stubs SHFind_InitMenuPopup, FileMenu_Create, ShellExecuteEx,
SHSetInstanceExplorer, SHGetInstanceExplorer, SHFreeUnusedLibraries.
* [include/winerror.h]
Class and window related error codes added.
* [memory/heap.c]
Changed lstrlen32A to strlen to get rid of milions of TRACE lines.
* [misc/ddeml.c]
First lines for DdeCreateStringHandle32A / DdeFreeStringHandle32.
* [misc/network.c][relay32/mpr.spec]
Fixed some bugs, changed ordinals.
* [windows/class.c]
Workarounds for incorrect hInstance handling. Fixes parts of
MSWord95/Excel95 and Money95.
Thu Aug 6 21:05:35 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
* [windows/nonclient.c][misc/tweak.c][include/tweak.h]
[documentation/win95look]
Removed some tweak variables. They are no longer needed.
* [files/dos_fs.c]
Added check for null pointer in DOSFS_GetDevice().
* [controls/tooltips.c][include/commctrl.h]
Improved tooltips.
* [controls/status.c][include/commctrl.h]
Cleaned up code and added tooltip support.
* [controls/toolbar.c][include/commctrl.h]
Added tooltip support.
* [documentation/common_controls]
Updated.
Thu Aug 6 00:05:22 1998 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
* [include/ver.h] [misc/ver.c]
Write VIF_BUFFTOOSMALL, not VIF_BUFTOSMALL.
* [debugger/hash.c] [debugger/stabs.c]
Make debug output more friendly for posting.
* [files/file.c]
Partial implementation of OF_SHARE_EXCLUSIVE.
Needed for Quicklogic/QuickChip (InstallShield).
* [files/profile.c]
When a cached-only entry is found, return it.
* [graphics/x11drv/xfont.c]
Accept a space as delimiter for a fontname and inhibit overrun
(Make xplasim.ex from the Phillips Coolrunner CPLD suite proceed).
* [miscemu/main.c]
Delay setting IF1632_CallLargeStack after loading the executables.
Stops fpgaexp.exe from the Viewlogic FPGA suite from crashing when
showing the Blinker error Message Box.
* [misc/network.c]
Make WNetGetConnection16 recognise a CDROM as a local drive.
* [multimedia/mmsystem.c]
Preliminary check for MCI_ALL_DEVICE_ID in MCI_Close by a FIXME.
Tue Aug 4 21:15:23 1998 James Juran <jrj120@psu.edu>
* [ole/ole2nls.c]
Fixed bug in CompareString32A. strcmp() doesn't necessarily
return -1, 0, or 1, which the previous code depended on.
Changed name of is_punctuation to OLE2NLS_isPunctuation.
Made NORM_IGNOREWIDTH not print a FIXME message in
LCMapString32A.
Other debugging messages, documentation, and code cleanups.
* [objects/font.c] [relay32/gdi32.spec] [include/winerror.h]
Added stub for GetFontData32, and added GDI_ERROR constant
to winerror.h.
Tue Aug 4 07:44:43 1998 Ove Kaaven <ovek@arcticnet.no>
* [multimedia/mmio.c]
Implemented mmioSetBuffer, mmioAdvance, mmioAscend, and
mmioCreateChunk to the best of my knowledge. But watch out,
there's bound to be bugs in there...
* [include/mmsystem.h] [multimedia/mmsystem.c]
Hacked in support for 32-bit multimedia function callbacks.
* [AUTHORS] [misc/shell.c]
Selfishly credited my authorship. Hopefully I'm excused.
* [include/dosexe.h] [include/module.h] [loader/dos/*]
[loader/module.c] [loader/task.c] [Makefile.in]
[configure.in] [Makefile.in]
Added DOS EXE (MZ) loader and virtual machine. Task
structure integration thanks to Ulrich Weigand.
* [files/dos_fs.c]
Work around a null pointer dereference if ioctlGetDeviceInfo-ing
a FILE_DupUnixHandle'd file (i.e. GetStdHandle'd).
* [include/miscemu.h] [include/winnt.h] [loader/main.c]
[memory/global.c] [msdos/dpmi.c] [msdos/dosmem.c]
Added support for DOS memory images, and added
DOSMEM_ResizeBlock() and DOSMEM_Available().
* [msdos/int21.c]
Added support for the DOS virtual machine, tweaked handle
assignment to avoid stdio clashes, forced INT21_FindNext to exit
wildcardless searches after finding one entry, added AH=7, 8, 9,
C, 48, 49, 4A, and 7160 CL=1 (Get Short Filename), and made the
long filename calls only respond if running with with -winver
win95.
* [objects/cursoricon.c]
DestroyCursor32 and DestroyIcon32 should now free the objects
(hopefully) correctly.
Sun Aug 2 21:42:09 1998 Huw D M Davies <daviesh@abacus.physics.ox.ac.uk>
* [graphics/psdrv/*] [include/psdrv.h]
Added PPD file parsing - at the moment it reads a file called
default.ppd from the directory in which you start Wine. Page sizes
other than A4 should now work (landscape may not). All fonts that are
present on your printer (according to the PPD) should be available,
providing you have the AFM files. Fonts should now be the correct size.
Graphics is still basically lines only. See graphics/psdrv/README .
* [misc/printdrv.c]
Yet more Drv[Get/Set]PrinterData fixes.
Fri Jul 31 21:33:22 1998 Per Lindstrm <pelinstr@algonet.se>
* [relay32/crtdll.spec] [misc/crtdll.c]
Added stub for freopen, _findfirst, _findnext, _fstat and _read.
* [files/directory.c]
Modified warning message.
Wed Jul 29 11:25:28 1998 Luiz Otavio L. Zorzella <zorzella@nr.conexware.com>
* [objects/font.c]
Added stub for GetFontData.
* [multimedia/msvideo.c]
Created this file to hold the msvideo.dll calls (and maybe also
msvfw32.dll).
* [objects/cursoricon.c]
Added search in Global Heap for cursor when trying to destroy it
with DestroyCursor16. This test should be done in many (all?)
other functions that use FreeResource.
* [controls/treeview.c] [include/commctrl.h]
Minor correction in name and addition of many placeholders for TVM
messages in TREEVIEW_WindowProc.
* [msdos/dpmi.c]
Fixed a bug in DPMI_xrealloc where in a copy of a memory region
"A" of size "a" to a region "B" of size "b", "b" bytes were being
copied, instead of "a", as the new version does. This both
increases speed, as well as avoids segfaults.
1998-08-09 14:47:43 +02:00
|
|
|
*
|
|
|
|
* RETURNS
|
|
|
|
*
|
2002-06-01 01:06:46 +02:00
|
|
|
* success: Number of bytes returned
|
Release 980809
Sat Aug 8 19:11:46 1998 Marcus Meissner <marcus@jet.franken.de>
* [*/*]
Added some missing WINAPI and some missing prototypes for
functions.
* [controls/static.c]
Got rid of the MODULE32_LookupHMODULE error showing up for every
message box.
* [windows/winproc.c]
WM_NOTIFY 16->32 mapping (AOL Instant Messenger or however it is called).
* [misc/winsock.c]
hostent/servent/protoent should not use the same static buffers.
(has broken nt3.15 finger.exe which does hp=gethostbyname(), then
getservbyname("finger","tcp") and the references hp->h_addr_list[0]).
Sat Aug 8 13:21:24 1998 Alexandre Julliard <julliard@lrc.epfl.ch>
* [include/server.h] [tools/make_requests] [server/request.c]
[server/trace.c]
Automated part of the client/server request code generation.
Added tracing of client/server communication.
* [scheduler/*.c] [server/process.c]
Added support for server-side handles.
* [scheduler/thread.c]
Added DLL_THREAD_ATTACH/DETACH notifications.
* [configure.in]
Added check for -lsocket.
* [windows/winproc.c]
Return the thunk address in WINPROC_GetProc if the function types
don't match.
Sat Aug 8 02:44:04 1998 Douglas Ridgway <ridgway@winehq.com>
* [windows/winproc.c][windows/win.c][windows/message.c]
Documentation for CallWindowProc, SetWindowLong, DispatchMessage,
WaitMessage, GetMessage, and PeekMessage.
Sat Aug 8 01:00:00 1998 Juergen Schmied <juergen.schmied@metronet.de>
* [controls/commctrl.c][controls/widgets.c][include/builtin32.h]
[include/commctrl.h][relay32/builtin32.c][relay32/comctl32.spec]
[tools/build.c] [relay32/shell32.spec]
Added the functionality of the LibMain function. The common
controls are properly initialized now.
* [controls/treeview.c][memory/atom.c][scheduler/thread.c][windows/class.c]
[windows/msgbox.c][windows/win.c]
Put TRACE in, put SetLastError() in.
* [include/interfaces.h]
Added IClassFactory::LockServer.
* [include/ole2.h]
Added struct for LPOLEMENUGROUPWIDTHS32, HOLEMENU32.
* [include/shell.h][include/shlobj.h][misc/shell.c][ole/folders.c]
Reorganized and many structs and classes (IShellBrowser,IShellView)
added. shell32.dll should work in many cases now.
Started SHGetFileInfoA implementeation, rewrote SHGetPathFromIDList32A.
New Shell32LibMain started ShellIconCache Implementation.
* [misc/shellord.c]
Rewrote ILCombine, ILGetSize
New stubs SHFind_InitMenuPopup, FileMenu_Create, ShellExecuteEx,
SHSetInstanceExplorer, SHGetInstanceExplorer, SHFreeUnusedLibraries.
* [include/winerror.h]
Class and window related error codes added.
* [memory/heap.c]
Changed lstrlen32A to strlen to get rid of milions of TRACE lines.
* [misc/ddeml.c]
First lines for DdeCreateStringHandle32A / DdeFreeStringHandle32.
* [misc/network.c][relay32/mpr.spec]
Fixed some bugs, changed ordinals.
* [windows/class.c]
Workarounds for incorrect hInstance handling. Fixes parts of
MSWord95/Excel95 and Money95.
Thu Aug 6 21:05:35 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
* [windows/nonclient.c][misc/tweak.c][include/tweak.h]
[documentation/win95look]
Removed some tweak variables. They are no longer needed.
* [files/dos_fs.c]
Added check for null pointer in DOSFS_GetDevice().
* [controls/tooltips.c][include/commctrl.h]
Improved tooltips.
* [controls/status.c][include/commctrl.h]
Cleaned up code and added tooltip support.
* [controls/toolbar.c][include/commctrl.h]
Added tooltip support.
* [documentation/common_controls]
Updated.
Thu Aug 6 00:05:22 1998 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
* [include/ver.h] [misc/ver.c]
Write VIF_BUFFTOOSMALL, not VIF_BUFTOSMALL.
* [debugger/hash.c] [debugger/stabs.c]
Make debug output more friendly for posting.
* [files/file.c]
Partial implementation of OF_SHARE_EXCLUSIVE.
Needed for Quicklogic/QuickChip (InstallShield).
* [files/profile.c]
When a cached-only entry is found, return it.
* [graphics/x11drv/xfont.c]
Accept a space as delimiter for a fontname and inhibit overrun
(Make xplasim.ex from the Phillips Coolrunner CPLD suite proceed).
* [miscemu/main.c]
Delay setting IF1632_CallLargeStack after loading the executables.
Stops fpgaexp.exe from the Viewlogic FPGA suite from crashing when
showing the Blinker error Message Box.
* [misc/network.c]
Make WNetGetConnection16 recognise a CDROM as a local drive.
* [multimedia/mmsystem.c]
Preliminary check for MCI_ALL_DEVICE_ID in MCI_Close by a FIXME.
Tue Aug 4 21:15:23 1998 James Juran <jrj120@psu.edu>
* [ole/ole2nls.c]
Fixed bug in CompareString32A. strcmp() doesn't necessarily
return -1, 0, or 1, which the previous code depended on.
Changed name of is_punctuation to OLE2NLS_isPunctuation.
Made NORM_IGNOREWIDTH not print a FIXME message in
LCMapString32A.
Other debugging messages, documentation, and code cleanups.
* [objects/font.c] [relay32/gdi32.spec] [include/winerror.h]
Added stub for GetFontData32, and added GDI_ERROR constant
to winerror.h.
Tue Aug 4 07:44:43 1998 Ove Kaaven <ovek@arcticnet.no>
* [multimedia/mmio.c]
Implemented mmioSetBuffer, mmioAdvance, mmioAscend, and
mmioCreateChunk to the best of my knowledge. But watch out,
there's bound to be bugs in there...
* [include/mmsystem.h] [multimedia/mmsystem.c]
Hacked in support for 32-bit multimedia function callbacks.
* [AUTHORS] [misc/shell.c]
Selfishly credited my authorship. Hopefully I'm excused.
* [include/dosexe.h] [include/module.h] [loader/dos/*]
[loader/module.c] [loader/task.c] [Makefile.in]
[configure.in] [Makefile.in]
Added DOS EXE (MZ) loader and virtual machine. Task
structure integration thanks to Ulrich Weigand.
* [files/dos_fs.c]
Work around a null pointer dereference if ioctlGetDeviceInfo-ing
a FILE_DupUnixHandle'd file (i.e. GetStdHandle'd).
* [include/miscemu.h] [include/winnt.h] [loader/main.c]
[memory/global.c] [msdos/dpmi.c] [msdos/dosmem.c]
Added support for DOS memory images, and added
DOSMEM_ResizeBlock() and DOSMEM_Available().
* [msdos/int21.c]
Added support for the DOS virtual machine, tweaked handle
assignment to avoid stdio clashes, forced INT21_FindNext to exit
wildcardless searches after finding one entry, added AH=7, 8, 9,
C, 48, 49, 4A, and 7160 CL=1 (Get Short Filename), and made the
long filename calls only respond if running with with -winver
win95.
* [objects/cursoricon.c]
DestroyCursor32 and DestroyIcon32 should now free the objects
(hopefully) correctly.
Sun Aug 2 21:42:09 1998 Huw D M Davies <daviesh@abacus.physics.ox.ac.uk>
* [graphics/psdrv/*] [include/psdrv.h]
Added PPD file parsing - at the moment it reads a file called
default.ppd from the directory in which you start Wine. Page sizes
other than A4 should now work (landscape may not). All fonts that are
present on your printer (according to the PPD) should be available,
providing you have the AFM files. Fonts should now be the correct size.
Graphics is still basically lines only. See graphics/psdrv/README .
* [misc/printdrv.c]
Yet more Drv[Get/Set]PrinterData fixes.
Fri Jul 31 21:33:22 1998 Per Lindstrm <pelinstr@algonet.se>
* [relay32/crtdll.spec] [misc/crtdll.c]
Added stub for freopen, _findfirst, _findnext, _fstat and _read.
* [files/directory.c]
Modified warning message.
Wed Jul 29 11:25:28 1998 Luiz Otavio L. Zorzella <zorzella@nr.conexware.com>
* [objects/font.c]
Added stub for GetFontData.
* [multimedia/msvideo.c]
Created this file to hold the msvideo.dll calls (and maybe also
msvfw32.dll).
* [objects/cursoricon.c]
Added search in Global Heap for cursor when trying to destroy it
with DestroyCursor16. This test should be done in many (all?)
other functions that use FreeResource.
* [controls/treeview.c] [include/commctrl.h]
Minor correction in name and addition of many placeholders for TVM
messages in TREEVIEW_WindowProc.
* [msdos/dpmi.c]
Fixed a bug in DPMI_xrealloc where in a copy of a memory region
"A" of size "a" to a region "B" of size "b", "b" bytes were being
copied, instead of "a", as the new version does. This both
increases speed, as well as avoids segfaults.
1998-08-09 14:47:43 +02:00
|
|
|
* failure: GDI_ERROR
|
|
|
|
*
|
|
|
|
* NOTES
|
|
|
|
*
|
2002-06-01 01:06:46 +02:00
|
|
|
* Calls SetLastError()
|
Release 980809
Sat Aug 8 19:11:46 1998 Marcus Meissner <marcus@jet.franken.de>
* [*/*]
Added some missing WINAPI and some missing prototypes for
functions.
* [controls/static.c]
Got rid of the MODULE32_LookupHMODULE error showing up for every
message box.
* [windows/winproc.c]
WM_NOTIFY 16->32 mapping (AOL Instant Messenger or however it is called).
* [misc/winsock.c]
hostent/servent/protoent should not use the same static buffers.
(has broken nt3.15 finger.exe which does hp=gethostbyname(), then
getservbyname("finger","tcp") and the references hp->h_addr_list[0]).
Sat Aug 8 13:21:24 1998 Alexandre Julliard <julliard@lrc.epfl.ch>
* [include/server.h] [tools/make_requests] [server/request.c]
[server/trace.c]
Automated part of the client/server request code generation.
Added tracing of client/server communication.
* [scheduler/*.c] [server/process.c]
Added support for server-side handles.
* [scheduler/thread.c]
Added DLL_THREAD_ATTACH/DETACH notifications.
* [configure.in]
Added check for -lsocket.
* [windows/winproc.c]
Return the thunk address in WINPROC_GetProc if the function types
don't match.
Sat Aug 8 02:44:04 1998 Douglas Ridgway <ridgway@winehq.com>
* [windows/winproc.c][windows/win.c][windows/message.c]
Documentation for CallWindowProc, SetWindowLong, DispatchMessage,
WaitMessage, GetMessage, and PeekMessage.
Sat Aug 8 01:00:00 1998 Juergen Schmied <juergen.schmied@metronet.de>
* [controls/commctrl.c][controls/widgets.c][include/builtin32.h]
[include/commctrl.h][relay32/builtin32.c][relay32/comctl32.spec]
[tools/build.c] [relay32/shell32.spec]
Added the functionality of the LibMain function. The common
controls are properly initialized now.
* [controls/treeview.c][memory/atom.c][scheduler/thread.c][windows/class.c]
[windows/msgbox.c][windows/win.c]
Put TRACE in, put SetLastError() in.
* [include/interfaces.h]
Added IClassFactory::LockServer.
* [include/ole2.h]
Added struct for LPOLEMENUGROUPWIDTHS32, HOLEMENU32.
* [include/shell.h][include/shlobj.h][misc/shell.c][ole/folders.c]
Reorganized and many structs and classes (IShellBrowser,IShellView)
added. shell32.dll should work in many cases now.
Started SHGetFileInfoA implementeation, rewrote SHGetPathFromIDList32A.
New Shell32LibMain started ShellIconCache Implementation.
* [misc/shellord.c]
Rewrote ILCombine, ILGetSize
New stubs SHFind_InitMenuPopup, FileMenu_Create, ShellExecuteEx,
SHSetInstanceExplorer, SHGetInstanceExplorer, SHFreeUnusedLibraries.
* [include/winerror.h]
Class and window related error codes added.
* [memory/heap.c]
Changed lstrlen32A to strlen to get rid of milions of TRACE lines.
* [misc/ddeml.c]
First lines for DdeCreateStringHandle32A / DdeFreeStringHandle32.
* [misc/network.c][relay32/mpr.spec]
Fixed some bugs, changed ordinals.
* [windows/class.c]
Workarounds for incorrect hInstance handling. Fixes parts of
MSWord95/Excel95 and Money95.
Thu Aug 6 21:05:35 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
* [windows/nonclient.c][misc/tweak.c][include/tweak.h]
[documentation/win95look]
Removed some tweak variables. They are no longer needed.
* [files/dos_fs.c]
Added check for null pointer in DOSFS_GetDevice().
* [controls/tooltips.c][include/commctrl.h]
Improved tooltips.
* [controls/status.c][include/commctrl.h]
Cleaned up code and added tooltip support.
* [controls/toolbar.c][include/commctrl.h]
Added tooltip support.
* [documentation/common_controls]
Updated.
Thu Aug 6 00:05:22 1998 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
* [include/ver.h] [misc/ver.c]
Write VIF_BUFFTOOSMALL, not VIF_BUFTOSMALL.
* [debugger/hash.c] [debugger/stabs.c]
Make debug output more friendly for posting.
* [files/file.c]
Partial implementation of OF_SHARE_EXCLUSIVE.
Needed for Quicklogic/QuickChip (InstallShield).
* [files/profile.c]
When a cached-only entry is found, return it.
* [graphics/x11drv/xfont.c]
Accept a space as delimiter for a fontname and inhibit overrun
(Make xplasim.ex from the Phillips Coolrunner CPLD suite proceed).
* [miscemu/main.c]
Delay setting IF1632_CallLargeStack after loading the executables.
Stops fpgaexp.exe from the Viewlogic FPGA suite from crashing when
showing the Blinker error Message Box.
* [misc/network.c]
Make WNetGetConnection16 recognise a CDROM as a local drive.
* [multimedia/mmsystem.c]
Preliminary check for MCI_ALL_DEVICE_ID in MCI_Close by a FIXME.
Tue Aug 4 21:15:23 1998 James Juran <jrj120@psu.edu>
* [ole/ole2nls.c]
Fixed bug in CompareString32A. strcmp() doesn't necessarily
return -1, 0, or 1, which the previous code depended on.
Changed name of is_punctuation to OLE2NLS_isPunctuation.
Made NORM_IGNOREWIDTH not print a FIXME message in
LCMapString32A.
Other debugging messages, documentation, and code cleanups.
* [objects/font.c] [relay32/gdi32.spec] [include/winerror.h]
Added stub for GetFontData32, and added GDI_ERROR constant
to winerror.h.
Tue Aug 4 07:44:43 1998 Ove Kaaven <ovek@arcticnet.no>
* [multimedia/mmio.c]
Implemented mmioSetBuffer, mmioAdvance, mmioAscend, and
mmioCreateChunk to the best of my knowledge. But watch out,
there's bound to be bugs in there...
* [include/mmsystem.h] [multimedia/mmsystem.c]
Hacked in support for 32-bit multimedia function callbacks.
* [AUTHORS] [misc/shell.c]
Selfishly credited my authorship. Hopefully I'm excused.
* [include/dosexe.h] [include/module.h] [loader/dos/*]
[loader/module.c] [loader/task.c] [Makefile.in]
[configure.in] [Makefile.in]
Added DOS EXE (MZ) loader and virtual machine. Task
structure integration thanks to Ulrich Weigand.
* [files/dos_fs.c]
Work around a null pointer dereference if ioctlGetDeviceInfo-ing
a FILE_DupUnixHandle'd file (i.e. GetStdHandle'd).
* [include/miscemu.h] [include/winnt.h] [loader/main.c]
[memory/global.c] [msdos/dpmi.c] [msdos/dosmem.c]
Added support for DOS memory images, and added
DOSMEM_ResizeBlock() and DOSMEM_Available().
* [msdos/int21.c]
Added support for the DOS virtual machine, tweaked handle
assignment to avoid stdio clashes, forced INT21_FindNext to exit
wildcardless searches after finding one entry, added AH=7, 8, 9,
C, 48, 49, 4A, and 7160 CL=1 (Get Short Filename), and made the
long filename calls only respond if running with with -winver
win95.
* [objects/cursoricon.c]
DestroyCursor32 and DestroyIcon32 should now free the objects
(hopefully) correctly.
Sun Aug 2 21:42:09 1998 Huw D M Davies <daviesh@abacus.physics.ox.ac.uk>
* [graphics/psdrv/*] [include/psdrv.h]
Added PPD file parsing - at the moment it reads a file called
default.ppd from the directory in which you start Wine. Page sizes
other than A4 should now work (landscape may not). All fonts that are
present on your printer (according to the PPD) should be available,
providing you have the AFM files. Fonts should now be the correct size.
Graphics is still basically lines only. See graphics/psdrv/README .
* [misc/printdrv.c]
Yet more Drv[Get/Set]PrinterData fixes.
Fri Jul 31 21:33:22 1998 Per Lindstrm <pelinstr@algonet.se>
* [relay32/crtdll.spec] [misc/crtdll.c]
Added stub for freopen, _findfirst, _findnext, _fstat and _read.
* [files/directory.c]
Modified warning message.
Wed Jul 29 11:25:28 1998 Luiz Otavio L. Zorzella <zorzella@nr.conexware.com>
* [objects/font.c]
Added stub for GetFontData.
* [multimedia/msvideo.c]
Created this file to hold the msvideo.dll calls (and maybe also
msvfw32.dll).
* [objects/cursoricon.c]
Added search in Global Heap for cursor when trying to destroy it
with DestroyCursor16. This test should be done in many (all?)
other functions that use FreeResource.
* [controls/treeview.c] [include/commctrl.h]
Minor correction in name and addition of many placeholders for TVM
messages in TREEVIEW_WindowProc.
* [msdos/dpmi.c]
Fixed a bug in DPMI_xrealloc where in a copy of a memory region
"A" of size "a" to a region "B" of size "b", "b" bytes were being
copied, instead of "a", as the new version does. This both
increases speed, as well as avoids segfaults.
1998-08-09 14:47:43 +02:00
|
|
|
*
|
|
|
|
*/
|
2021-08-27 14:51:56 +02:00
|
|
|
DWORD WINAPI NtGdiGetFontData( HDC hdc, DWORD table, DWORD offset, void *buffer, DWORD length )
|
Release 980809
Sat Aug 8 19:11:46 1998 Marcus Meissner <marcus@jet.franken.de>
* [*/*]
Added some missing WINAPI and some missing prototypes for
functions.
* [controls/static.c]
Got rid of the MODULE32_LookupHMODULE error showing up for every
message box.
* [windows/winproc.c]
WM_NOTIFY 16->32 mapping (AOL Instant Messenger or however it is called).
* [misc/winsock.c]
hostent/servent/protoent should not use the same static buffers.
(has broken nt3.15 finger.exe which does hp=gethostbyname(), then
getservbyname("finger","tcp") and the references hp->h_addr_list[0]).
Sat Aug 8 13:21:24 1998 Alexandre Julliard <julliard@lrc.epfl.ch>
* [include/server.h] [tools/make_requests] [server/request.c]
[server/trace.c]
Automated part of the client/server request code generation.
Added tracing of client/server communication.
* [scheduler/*.c] [server/process.c]
Added support for server-side handles.
* [scheduler/thread.c]
Added DLL_THREAD_ATTACH/DETACH notifications.
* [configure.in]
Added check for -lsocket.
* [windows/winproc.c]
Return the thunk address in WINPROC_GetProc if the function types
don't match.
Sat Aug 8 02:44:04 1998 Douglas Ridgway <ridgway@winehq.com>
* [windows/winproc.c][windows/win.c][windows/message.c]
Documentation for CallWindowProc, SetWindowLong, DispatchMessage,
WaitMessage, GetMessage, and PeekMessage.
Sat Aug 8 01:00:00 1998 Juergen Schmied <juergen.schmied@metronet.de>
* [controls/commctrl.c][controls/widgets.c][include/builtin32.h]
[include/commctrl.h][relay32/builtin32.c][relay32/comctl32.spec]
[tools/build.c] [relay32/shell32.spec]
Added the functionality of the LibMain function. The common
controls are properly initialized now.
* [controls/treeview.c][memory/atom.c][scheduler/thread.c][windows/class.c]
[windows/msgbox.c][windows/win.c]
Put TRACE in, put SetLastError() in.
* [include/interfaces.h]
Added IClassFactory::LockServer.
* [include/ole2.h]
Added struct for LPOLEMENUGROUPWIDTHS32, HOLEMENU32.
* [include/shell.h][include/shlobj.h][misc/shell.c][ole/folders.c]
Reorganized and many structs and classes (IShellBrowser,IShellView)
added. shell32.dll should work in many cases now.
Started SHGetFileInfoA implementeation, rewrote SHGetPathFromIDList32A.
New Shell32LibMain started ShellIconCache Implementation.
* [misc/shellord.c]
Rewrote ILCombine, ILGetSize
New stubs SHFind_InitMenuPopup, FileMenu_Create, ShellExecuteEx,
SHSetInstanceExplorer, SHGetInstanceExplorer, SHFreeUnusedLibraries.
* [include/winerror.h]
Class and window related error codes added.
* [memory/heap.c]
Changed lstrlen32A to strlen to get rid of milions of TRACE lines.
* [misc/ddeml.c]
First lines for DdeCreateStringHandle32A / DdeFreeStringHandle32.
* [misc/network.c][relay32/mpr.spec]
Fixed some bugs, changed ordinals.
* [windows/class.c]
Workarounds for incorrect hInstance handling. Fixes parts of
MSWord95/Excel95 and Money95.
Thu Aug 6 21:05:35 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
* [windows/nonclient.c][misc/tweak.c][include/tweak.h]
[documentation/win95look]
Removed some tweak variables. They are no longer needed.
* [files/dos_fs.c]
Added check for null pointer in DOSFS_GetDevice().
* [controls/tooltips.c][include/commctrl.h]
Improved tooltips.
* [controls/status.c][include/commctrl.h]
Cleaned up code and added tooltip support.
* [controls/toolbar.c][include/commctrl.h]
Added tooltip support.
* [documentation/common_controls]
Updated.
Thu Aug 6 00:05:22 1998 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
* [include/ver.h] [misc/ver.c]
Write VIF_BUFFTOOSMALL, not VIF_BUFTOSMALL.
* [debugger/hash.c] [debugger/stabs.c]
Make debug output more friendly for posting.
* [files/file.c]
Partial implementation of OF_SHARE_EXCLUSIVE.
Needed for Quicklogic/QuickChip (InstallShield).
* [files/profile.c]
When a cached-only entry is found, return it.
* [graphics/x11drv/xfont.c]
Accept a space as delimiter for a fontname and inhibit overrun
(Make xplasim.ex from the Phillips Coolrunner CPLD suite proceed).
* [miscemu/main.c]
Delay setting IF1632_CallLargeStack after loading the executables.
Stops fpgaexp.exe from the Viewlogic FPGA suite from crashing when
showing the Blinker error Message Box.
* [misc/network.c]
Make WNetGetConnection16 recognise a CDROM as a local drive.
* [multimedia/mmsystem.c]
Preliminary check for MCI_ALL_DEVICE_ID in MCI_Close by a FIXME.
Tue Aug 4 21:15:23 1998 James Juran <jrj120@psu.edu>
* [ole/ole2nls.c]
Fixed bug in CompareString32A. strcmp() doesn't necessarily
return -1, 0, or 1, which the previous code depended on.
Changed name of is_punctuation to OLE2NLS_isPunctuation.
Made NORM_IGNOREWIDTH not print a FIXME message in
LCMapString32A.
Other debugging messages, documentation, and code cleanups.
* [objects/font.c] [relay32/gdi32.spec] [include/winerror.h]
Added stub for GetFontData32, and added GDI_ERROR constant
to winerror.h.
Tue Aug 4 07:44:43 1998 Ove Kaaven <ovek@arcticnet.no>
* [multimedia/mmio.c]
Implemented mmioSetBuffer, mmioAdvance, mmioAscend, and
mmioCreateChunk to the best of my knowledge. But watch out,
there's bound to be bugs in there...
* [include/mmsystem.h] [multimedia/mmsystem.c]
Hacked in support for 32-bit multimedia function callbacks.
* [AUTHORS] [misc/shell.c]
Selfishly credited my authorship. Hopefully I'm excused.
* [include/dosexe.h] [include/module.h] [loader/dos/*]
[loader/module.c] [loader/task.c] [Makefile.in]
[configure.in] [Makefile.in]
Added DOS EXE (MZ) loader and virtual machine. Task
structure integration thanks to Ulrich Weigand.
* [files/dos_fs.c]
Work around a null pointer dereference if ioctlGetDeviceInfo-ing
a FILE_DupUnixHandle'd file (i.e. GetStdHandle'd).
* [include/miscemu.h] [include/winnt.h] [loader/main.c]
[memory/global.c] [msdos/dpmi.c] [msdos/dosmem.c]
Added support for DOS memory images, and added
DOSMEM_ResizeBlock() and DOSMEM_Available().
* [msdos/int21.c]
Added support for the DOS virtual machine, tweaked handle
assignment to avoid stdio clashes, forced INT21_FindNext to exit
wildcardless searches after finding one entry, added AH=7, 8, 9,
C, 48, 49, 4A, and 7160 CL=1 (Get Short Filename), and made the
long filename calls only respond if running with with -winver
win95.
* [objects/cursoricon.c]
DestroyCursor32 and DestroyIcon32 should now free the objects
(hopefully) correctly.
Sun Aug 2 21:42:09 1998 Huw D M Davies <daviesh@abacus.physics.ox.ac.uk>
* [graphics/psdrv/*] [include/psdrv.h]
Added PPD file parsing - at the moment it reads a file called
default.ppd from the directory in which you start Wine. Page sizes
other than A4 should now work (landscape may not). All fonts that are
present on your printer (according to the PPD) should be available,
providing you have the AFM files. Fonts should now be the correct size.
Graphics is still basically lines only. See graphics/psdrv/README .
* [misc/printdrv.c]
Yet more Drv[Get/Set]PrinterData fixes.
Fri Jul 31 21:33:22 1998 Per Lindstrm <pelinstr@algonet.se>
* [relay32/crtdll.spec] [misc/crtdll.c]
Added stub for freopen, _findfirst, _findnext, _fstat and _read.
* [files/directory.c]
Modified warning message.
Wed Jul 29 11:25:28 1998 Luiz Otavio L. Zorzella <zorzella@nr.conexware.com>
* [objects/font.c]
Added stub for GetFontData.
* [multimedia/msvideo.c]
Created this file to hold the msvideo.dll calls (and maybe also
msvfw32.dll).
* [objects/cursoricon.c]
Added search in Global Heap for cursor when trying to destroy it
with DestroyCursor16. This test should be done in many (all?)
other functions that use FreeResource.
* [controls/treeview.c] [include/commctrl.h]
Minor correction in name and addition of many placeholders for TVM
messages in TREEVIEW_WindowProc.
* [msdos/dpmi.c]
Fixed a bug in DPMI_xrealloc where in a copy of a memory region
"A" of size "a" to a region "B" of size "b", "b" bytes were being
copied, instead of "a", as the new version does. This both
increases speed, as well as avoids segfaults.
1998-08-09 14:47:43 +02:00
|
|
|
{
|
2008-02-05 21:16:27 +01:00
|
|
|
DC *dc = get_dc_ptr(hdc);
|
2011-10-20 17:58:09 +02:00
|
|
|
PHYSDEV dev;
|
|
|
|
DWORD ret;
|
2001-10-23 22:06:32 +02:00
|
|
|
|
|
|
|
if(!dc) return GDI_ERROR;
|
|
|
|
|
2011-10-20 17:58:09 +02:00
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetFontData );
|
|
|
|
ret = dev->funcs->pGetFontData( dev, table, offset, buffer, length );
|
2008-02-05 21:16:27 +01:00
|
|
|
release_dc_ptr( dc );
|
2001-10-23 22:06:32 +02:00
|
|
|
return ret;
|
Release 980809
Sat Aug 8 19:11:46 1998 Marcus Meissner <marcus@jet.franken.de>
* [*/*]
Added some missing WINAPI and some missing prototypes for
functions.
* [controls/static.c]
Got rid of the MODULE32_LookupHMODULE error showing up for every
message box.
* [windows/winproc.c]
WM_NOTIFY 16->32 mapping (AOL Instant Messenger or however it is called).
* [misc/winsock.c]
hostent/servent/protoent should not use the same static buffers.
(has broken nt3.15 finger.exe which does hp=gethostbyname(), then
getservbyname("finger","tcp") and the references hp->h_addr_list[0]).
Sat Aug 8 13:21:24 1998 Alexandre Julliard <julliard@lrc.epfl.ch>
* [include/server.h] [tools/make_requests] [server/request.c]
[server/trace.c]
Automated part of the client/server request code generation.
Added tracing of client/server communication.
* [scheduler/*.c] [server/process.c]
Added support for server-side handles.
* [scheduler/thread.c]
Added DLL_THREAD_ATTACH/DETACH notifications.
* [configure.in]
Added check for -lsocket.
* [windows/winproc.c]
Return the thunk address in WINPROC_GetProc if the function types
don't match.
Sat Aug 8 02:44:04 1998 Douglas Ridgway <ridgway@winehq.com>
* [windows/winproc.c][windows/win.c][windows/message.c]
Documentation for CallWindowProc, SetWindowLong, DispatchMessage,
WaitMessage, GetMessage, and PeekMessage.
Sat Aug 8 01:00:00 1998 Juergen Schmied <juergen.schmied@metronet.de>
* [controls/commctrl.c][controls/widgets.c][include/builtin32.h]
[include/commctrl.h][relay32/builtin32.c][relay32/comctl32.spec]
[tools/build.c] [relay32/shell32.spec]
Added the functionality of the LibMain function. The common
controls are properly initialized now.
* [controls/treeview.c][memory/atom.c][scheduler/thread.c][windows/class.c]
[windows/msgbox.c][windows/win.c]
Put TRACE in, put SetLastError() in.
* [include/interfaces.h]
Added IClassFactory::LockServer.
* [include/ole2.h]
Added struct for LPOLEMENUGROUPWIDTHS32, HOLEMENU32.
* [include/shell.h][include/shlobj.h][misc/shell.c][ole/folders.c]
Reorganized and many structs and classes (IShellBrowser,IShellView)
added. shell32.dll should work in many cases now.
Started SHGetFileInfoA implementeation, rewrote SHGetPathFromIDList32A.
New Shell32LibMain started ShellIconCache Implementation.
* [misc/shellord.c]
Rewrote ILCombine, ILGetSize
New stubs SHFind_InitMenuPopup, FileMenu_Create, ShellExecuteEx,
SHSetInstanceExplorer, SHGetInstanceExplorer, SHFreeUnusedLibraries.
* [include/winerror.h]
Class and window related error codes added.
* [memory/heap.c]
Changed lstrlen32A to strlen to get rid of milions of TRACE lines.
* [misc/ddeml.c]
First lines for DdeCreateStringHandle32A / DdeFreeStringHandle32.
* [misc/network.c][relay32/mpr.spec]
Fixed some bugs, changed ordinals.
* [windows/class.c]
Workarounds for incorrect hInstance handling. Fixes parts of
MSWord95/Excel95 and Money95.
Thu Aug 6 21:05:35 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
* [windows/nonclient.c][misc/tweak.c][include/tweak.h]
[documentation/win95look]
Removed some tweak variables. They are no longer needed.
* [files/dos_fs.c]
Added check for null pointer in DOSFS_GetDevice().
* [controls/tooltips.c][include/commctrl.h]
Improved tooltips.
* [controls/status.c][include/commctrl.h]
Cleaned up code and added tooltip support.
* [controls/toolbar.c][include/commctrl.h]
Added tooltip support.
* [documentation/common_controls]
Updated.
Thu Aug 6 00:05:22 1998 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
* [include/ver.h] [misc/ver.c]
Write VIF_BUFFTOOSMALL, not VIF_BUFTOSMALL.
* [debugger/hash.c] [debugger/stabs.c]
Make debug output more friendly for posting.
* [files/file.c]
Partial implementation of OF_SHARE_EXCLUSIVE.
Needed for Quicklogic/QuickChip (InstallShield).
* [files/profile.c]
When a cached-only entry is found, return it.
* [graphics/x11drv/xfont.c]
Accept a space as delimiter for a fontname and inhibit overrun
(Make xplasim.ex from the Phillips Coolrunner CPLD suite proceed).
* [miscemu/main.c]
Delay setting IF1632_CallLargeStack after loading the executables.
Stops fpgaexp.exe from the Viewlogic FPGA suite from crashing when
showing the Blinker error Message Box.
* [misc/network.c]
Make WNetGetConnection16 recognise a CDROM as a local drive.
* [multimedia/mmsystem.c]
Preliminary check for MCI_ALL_DEVICE_ID in MCI_Close by a FIXME.
Tue Aug 4 21:15:23 1998 James Juran <jrj120@psu.edu>
* [ole/ole2nls.c]
Fixed bug in CompareString32A. strcmp() doesn't necessarily
return -1, 0, or 1, which the previous code depended on.
Changed name of is_punctuation to OLE2NLS_isPunctuation.
Made NORM_IGNOREWIDTH not print a FIXME message in
LCMapString32A.
Other debugging messages, documentation, and code cleanups.
* [objects/font.c] [relay32/gdi32.spec] [include/winerror.h]
Added stub for GetFontData32, and added GDI_ERROR constant
to winerror.h.
Tue Aug 4 07:44:43 1998 Ove Kaaven <ovek@arcticnet.no>
* [multimedia/mmio.c]
Implemented mmioSetBuffer, mmioAdvance, mmioAscend, and
mmioCreateChunk to the best of my knowledge. But watch out,
there's bound to be bugs in there...
* [include/mmsystem.h] [multimedia/mmsystem.c]
Hacked in support for 32-bit multimedia function callbacks.
* [AUTHORS] [misc/shell.c]
Selfishly credited my authorship. Hopefully I'm excused.
* [include/dosexe.h] [include/module.h] [loader/dos/*]
[loader/module.c] [loader/task.c] [Makefile.in]
[configure.in] [Makefile.in]
Added DOS EXE (MZ) loader and virtual machine. Task
structure integration thanks to Ulrich Weigand.
* [files/dos_fs.c]
Work around a null pointer dereference if ioctlGetDeviceInfo-ing
a FILE_DupUnixHandle'd file (i.e. GetStdHandle'd).
* [include/miscemu.h] [include/winnt.h] [loader/main.c]
[memory/global.c] [msdos/dpmi.c] [msdos/dosmem.c]
Added support for DOS memory images, and added
DOSMEM_ResizeBlock() and DOSMEM_Available().
* [msdos/int21.c]
Added support for the DOS virtual machine, tweaked handle
assignment to avoid stdio clashes, forced INT21_FindNext to exit
wildcardless searches after finding one entry, added AH=7, 8, 9,
C, 48, 49, 4A, and 7160 CL=1 (Get Short Filename), and made the
long filename calls only respond if running with with -winver
win95.
* [objects/cursoricon.c]
DestroyCursor32 and DestroyIcon32 should now free the objects
(hopefully) correctly.
Sun Aug 2 21:42:09 1998 Huw D M Davies <daviesh@abacus.physics.ox.ac.uk>
* [graphics/psdrv/*] [include/psdrv.h]
Added PPD file parsing - at the moment it reads a file called
default.ppd from the directory in which you start Wine. Page sizes
other than A4 should now work (landscape may not). All fonts that are
present on your printer (according to the PPD) should be available,
providing you have the AFM files. Fonts should now be the correct size.
Graphics is still basically lines only. See graphics/psdrv/README .
* [misc/printdrv.c]
Yet more Drv[Get/Set]PrinterData fixes.
Fri Jul 31 21:33:22 1998 Per Lindstrm <pelinstr@algonet.se>
* [relay32/crtdll.spec] [misc/crtdll.c]
Added stub for freopen, _findfirst, _findnext, _fstat and _read.
* [files/directory.c]
Modified warning message.
Wed Jul 29 11:25:28 1998 Luiz Otavio L. Zorzella <zorzella@nr.conexware.com>
* [objects/font.c]
Added stub for GetFontData.
* [multimedia/msvideo.c]
Created this file to hold the msvideo.dll calls (and maybe also
msvfw32.dll).
* [objects/cursoricon.c]
Added search in Global Heap for cursor when trying to destroy it
with DestroyCursor16. This test should be done in many (all?)
other functions that use FreeResource.
* [controls/treeview.c] [include/commctrl.h]
Minor correction in name and addition of many placeholders for TVM
messages in TREEVIEW_WindowProc.
* [msdos/dpmi.c]
Fixed a bug in DPMI_xrealloc where in a copy of a memory region
"A" of size "a" to a region "B" of size "b", "b" bytes were being
copied, instead of "a", as the new version does. This both
increases speed, as well as avoids segfaults.
1998-08-09 14:47:43 +02:00
|
|
|
}
|
Release 980712
Sun Jul 12 16:23:36 1998 Alexandre Julliard <julliard@lrc.epfl.ch>
* [server/*] [scheduler/client.c] (new files)
[scheduler/sysdeps.c] [scheduler/thread.c] [scheduler/process.c]
Beginnings of client/server communication for inter-process
synchronisation.
Sat Jul 11 19:45:45 1998 Ulrich Weigand <weigand@informatik.uni-erlangen.de>
* [include/bitmap.h] [objects/bitmap.c] [objects/dib.c]
[objects/oembitmap.c]
Speed up DIB section handling by using pre-allocated colormap and
XImage. Moved DIB section data out of general BITMAPOBJ structure.
Bugfix: GetDIBits32 would overwrite one byte beyond bitmap data.
* [if1632/shell.spec] [if1632/kernel.spec] [win32/kernel32.c]
More verbose error message if ThunkConnect fails.
Implemented KERNEL_475.
* [files/profile.c] [ole/ole2nls.c]
Minor bugfixes.
* [if1632/builtin.c] [if1632/kernel.spec] [include/task.h]
[loader/ne/module.c] [loader/task.c]
Implemented KERNEL.THHOOK.
* [if1632/wprocs.spec] [include/process.h] [msdos/dpmi.c] [msdos/vxd.c]
Implemented Win32s VxD services (W32S.386).
Sat Jul 11 17:52:23 1998 Huw D M Davies <daviesh@abacus.physics.ox.ac.uk>
* [graphics/x11drv/xfont.c] [graphics/x11drv/text.c]
[include/x11font.h]
Improve handling of rotated X11 fonts. Metrics/extents should now be
correct. ExtTextOut should behave better (still doesn't handle lpDx).
* [graphics/painting.c]
DrawFocusRect32: Don't do anything if width or height are zero.
Sat Jul 11 15:21:35 1998 Andreas Mohr <100.30936@germany.net>
* [files/profile.c] [include/windows.h]
The length arguments of *Profile*() need to be treated
as UINTxx instead of INTxx.
* [graphics/env.c] [graphics/win16drv/init.c] [include/print.h]
[misc/printdrv.c]
Many printer driver fixes/changes (many thanks go to Huw !).
Most printers should work again ;)
* [memory/atom.c]
Fixed ATOM_AddAtom to store atoms exactly like Windows.
* [*/*]
Fixed misc compiler warnings.
Fri Jul 10 15:58:36 1998 Marcus Meissner <marcus@jet.franken.de>
* [files/drive.c]
Fixed GetDriveType16 to return DRIVE_REMOTE again.
* [loader/pe_image.c][loader/module.c]
Look for modules that have the same modulename or the same
filename (they sometimes differ).
Fixed up fixup_imports, removed one of the loops.
* [windows/winpos.c]
Added some NULL ptr checks. Needs more.
* [graphics/ddraw.c]
Some stubs added.
* [if1632/snoop.c]
Updated, made WINELIB compatible.
Fri Jul 10 04:39:56 1998 Douglas Ridgway <ridgway@winehq.com>
* [objects/enhmetafile.c] [relay32/gdi32.spec]
Small tweaks for documentation system.
Thu Jul 9 22:00:18 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
* [controls/commctrl.c][include/commctrl.h][relay32/comctl32.spec]
Fixed GetEffectiveClientRect, CreateToolbarEx and CreateMappedBitmap.
Added stub for ShowHideMenuCtl. Added some documentation.
* [documentation/common_controls]
Added and updated some information.
* [controls/toolbar.c][include/toolbar.h]
Added string support.
* [misc/shell.c][misc/shellord.c][relay32/shell.spec]
Changed names of undocumented functions to their real names and
fixed the export table.
* [controls/imagelist.c][relay32/comctl32.spec]
Added stub for ImageList_SetFilter.
Fixed some minor bugs and typos.
* [objects/font.c][include/windows.h][relay32/gdi32.spec]
Added stubs for GetCharacterPlacement32[A/W].
* [objects/region.c][relay32/gdi32.spec]
Added stub for UNDOCUMENTED GetRandomRgn.
* [controls/commctrl.c][controls/*.c][include/*.h]
Added dummy listview, pager, rebar, tooltips, trackbar and
treeview control. This keeps some programs from complaining.
Thu Jul 9 11:23:58 1998 Rein Klazes <rklazes@casema.net>
* [graphics/painting.c] [graphics/*/init.c]
[graphics/x11drv/graphics.c] [relay32/gdi32.spec]
[if1632/gdi.spec] [include/gdi.h] [include/x11drv.h]
Implemented drawing bezier curves: PolyBezier16/32 and
PolyBezierTo16/32.
* [graphics/x11drv/graphics.c]
Improved accuracy of several graphic routines, especially the
drawing of pie's.
* [include/windows.h] [misc/spy.c]
Added 25 window messages related to programs based on MFC and/or OLE.
Wed Jul 8 22:00:00 1998 James Juran <jrj120@psu.edu>
* [documentation/wine.man]
Updated manpage.
* [wine.ini]
Added section for Win95Look=true (commented out by default).
Wed Jul 8 06:23:19 1998 Matthew Becker <mbecker@glasscity.net>
* [misc/registry.c]
Fixed a crash in RegEnumValue32A when the dwType parameter is
NULL.
* [programs/regtest/regtest.c]
Improved the printing of errors.
* [misc/ntdll.c]
Added stub for RtlFormatCurrentUserKeyPath.
* [win32/console.c]
Added stub for ScrollConsoleScreenBuffer.
Mon Jul 6 16:41:47 1998 Per Lindstrm <pelinstr@algonet.se>
* [include/windows.h] [relay32/kernel.spec] [win32/newfns.c]
Added stubs for SleepEx and TerminateProcess.
* [rc/README]
Corrected a grammatical error.
Mon Jul 3 12:00:00 1998 Juergen Schmied <juergen.schmied@metronet.de>
* [misc/shellord.c]
Put some TRACE in.
* [memory/string.c]
Deleted unused variable in lstrcmpi32A.
* [include/windows.h][memory/string.c]
Added functions WideCharToLocal32 LocalToWideChar32 for
OLE-strings
* [include/shlobj.h][include/winerror.h][misc/shell.c]
[ole/folders.c]
Added definition of internal class pidlmgr.
Changed definitions of EnumIDList, IShellFolder.
Added some OLE error constants.
Implemented EnumIDList, IShellFolder, IClassFactory,
PidlMgr, SHELL32_DllGetClassObject, SHGetDesktopFolder,
SHGetSpecialFolderLocation (half), SHGetPathFromIDList
(!!This stuff is not finished yet!!)
* [include/windows.h][misc/network][reley32/mpr.spec]
Added stubs for WNetConnectionDialog32[A|W|API].
Added struct LPCONNECTDLGSTRUCT32[A|W] and some constants.
Added some SetLastError(WN_NO_NETWORK) to the stubs.
Fixed bufferhandling in WNetCancelConnection
Added stub for MultinetGetErrorText[A|W]
* [ole/ole2nls.c]
Rewrote GetTimeFormat32A.
Fri Jul 3 10:27:30 1998 Michael Poole <poole+@andrew.cmu.edu>
* [graphics/ddraw.c] [tsx11/X11_calls]
Implement IDirectDrawPalette_GetEntries.
Use CopyColormapAndFree to avoid erasing previously-set
palette entries.
* [graphics/ddraw.c] [include/ddraw.h]
[tools/make_X11wrappers] [tsx11/X11_calls]
Provide a preliminary, not-yet-working framework for doing
DirectDraw via Xlib or XShm as well as DGA.
Tue Jun 30 00:16:09 1998 Marcel Baur <mbaur@g26.ethz.ch>
* [ole/nls/*.nls]
Added remaining 22 locales (including arabic locales).
1998-07-12 21:29:36 +02:00
|
|
|
|
2002-04-03 22:41:14 +02:00
|
|
|
/*************************************************************************
|
2021-08-30 13:52:36 +02:00
|
|
|
* NtGdiGetGlyphIndicesW (win32u.@)
|
2002-04-03 22:41:14 +02:00
|
|
|
*/
|
2021-08-30 13:52:36 +02:00
|
|
|
DWORD WINAPI NtGdiGetGlyphIndicesW( HDC hdc, const WCHAR *str, INT count,
|
|
|
|
WORD *indices, DWORD flags )
|
2002-04-03 22:41:14 +02:00
|
|
|
{
|
2008-02-05 21:16:27 +01:00
|
|
|
DC *dc = get_dc_ptr(hdc);
|
2011-10-20 16:30:32 +02:00
|
|
|
PHYSDEV dev;
|
|
|
|
DWORD ret;
|
2002-04-03 22:41:14 +02:00
|
|
|
|
2021-08-30 13:52:36 +02:00
|
|
|
TRACE( "(%p, %s, %d, %p, 0x%x)\n", hdc, debugstr_wn(str, count), count, indices, flags );
|
2002-04-03 22:41:14 +02:00
|
|
|
|
|
|
|
if(!dc) return GDI_ERROR;
|
|
|
|
|
2011-10-20 16:30:32 +02:00
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
|
2021-08-30 13:52:36 +02:00
|
|
|
ret = dev->funcs->pGetGlyphIndices( dev, str, count, indices, flags );
|
2008-02-05 21:16:27 +01:00
|
|
|
release_dc_ptr( dc );
|
2002-04-03 22:41:14 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2000-03-19 22:20:54 +01:00
|
|
|
/***********************************************************************
|
|
|
|
* *
|
|
|
|
* Font Resource API *
|
|
|
|
* *
|
|
|
|
***********************************************************************/
|
|
|
|
|
2007-09-07 19:11:09 +02:00
|
|
|
static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
|
|
|
|
{
|
|
|
|
HRSRC rsrc = FindResourceW(hModule, name, type);
|
|
|
|
HGLOBAL hMem = LoadResource(hModule, rsrc);
|
|
|
|
LPVOID *pMem = LockResource(hMem);
|
|
|
|
int *num_total = (int *)lParam;
|
|
|
|
DWORD num_in_res;
|
|
|
|
|
|
|
|
TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
|
2021-09-10 14:28:30 +02:00
|
|
|
if (!NtGdiAddFontMemResourceEx( pMem, SizeofResource(hModule, rsrc), NULL, 0, &num_in_res ))
|
2007-09-07 19:11:09 +02:00
|
|
|
{
|
|
|
|
ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*num_total += num_in_res;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2012-03-30 13:38:04 +02:00
|
|
|
static void *map_file( const WCHAR *filename, LARGE_INTEGER *size )
|
|
|
|
{
|
|
|
|
HANDLE file, mapping;
|
|
|
|
void *ptr;
|
|
|
|
|
|
|
|
file = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
|
|
|
|
if (file == INVALID_HANDLE_VALUE) return NULL;
|
|
|
|
|
2012-04-02 07:40:50 +02:00
|
|
|
if (!GetFileSizeEx( file, size ) || size->u.HighPart)
|
|
|
|
{
|
|
|
|
CloseHandle( file );
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-03-30 13:38:04 +02:00
|
|
|
mapping = CreateFileMappingW( file, NULL, PAGE_READONLY, 0, 0, NULL );
|
|
|
|
CloseHandle( file );
|
2012-04-02 07:40:50 +02:00
|
|
|
if (!mapping) return NULL;
|
2012-03-30 13:38:04 +02:00
|
|
|
|
|
|
|
ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
|
|
|
|
CloseHandle( mapping );
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2013-01-15 12:52:04 +01:00
|
|
|
static void *find_resource( BYTE *ptr, WORD type, DWORD rsrc_off, DWORD size, DWORD *len )
|
|
|
|
{
|
|
|
|
WORD align, type_id, count;
|
|
|
|
DWORD res_off;
|
|
|
|
|
|
|
|
if (size < rsrc_off + 10) return NULL;
|
|
|
|
align = *(WORD *)(ptr + rsrc_off);
|
|
|
|
rsrc_off += 2;
|
|
|
|
type_id = *(WORD *)(ptr + rsrc_off);
|
|
|
|
while (type_id && type_id != type)
|
|
|
|
{
|
|
|
|
count = *(WORD *)(ptr + rsrc_off + 2);
|
|
|
|
rsrc_off += 8 + count * 12;
|
|
|
|
if (size < rsrc_off + 8) return NULL;
|
|
|
|
type_id = *(WORD *)(ptr + rsrc_off);
|
|
|
|
}
|
|
|
|
if (!type_id) return NULL;
|
|
|
|
count = *(WORD *)(ptr + rsrc_off + 2);
|
|
|
|
if (size < rsrc_off + 8 + count * 12) return NULL;
|
|
|
|
res_off = *(WORD *)(ptr + rsrc_off + 8) << align;
|
|
|
|
*len = *(WORD *)(ptr + rsrc_off + 10) << align;
|
|
|
|
if (size < res_off + *len) return NULL;
|
|
|
|
return ptr + res_off;
|
|
|
|
}
|
|
|
|
|
|
|
|
static WCHAR *get_scalable_filename( const WCHAR *res, BOOL *hidden )
|
2012-03-30 13:38:04 +02:00
|
|
|
{
|
|
|
|
LARGE_INTEGER size;
|
|
|
|
BYTE *ptr = map_file( res, &size );
|
|
|
|
const IMAGE_DOS_HEADER *dos;
|
|
|
|
const IMAGE_OS2_HEADER *ne;
|
2013-01-15 12:52:04 +01:00
|
|
|
WORD *fontdir;
|
|
|
|
char *data;
|
2012-03-30 13:38:04 +02:00
|
|
|
WCHAR *name = NULL;
|
2013-01-15 12:52:04 +01:00
|
|
|
DWORD len;
|
2012-03-30 13:38:04 +02:00
|
|
|
|
|
|
|
if (!ptr) return NULL;
|
|
|
|
|
|
|
|
if (size.u.LowPart < sizeof( *dos )) goto fail;
|
|
|
|
dos = (const IMAGE_DOS_HEADER *)ptr;
|
|
|
|
if (dos->e_magic != IMAGE_DOS_SIGNATURE) goto fail;
|
|
|
|
if (size.u.LowPart < dos->e_lfanew + sizeof( *ne )) goto fail;
|
|
|
|
ne = (const IMAGE_OS2_HEADER *)(ptr + dos->e_lfanew);
|
|
|
|
|
2013-01-15 12:52:04 +01:00
|
|
|
fontdir = find_resource( ptr, 0x8007, dos->e_lfanew + ne->ne_rsrctab, size.u.LowPart, &len );
|
|
|
|
if (!fontdir) goto fail;
|
|
|
|
*hidden = (fontdir[35] & 0x80) != 0; /* fontdir->dfType */
|
2012-03-30 13:38:04 +02:00
|
|
|
|
2013-01-15 12:52:04 +01:00
|
|
|
data = find_resource( ptr, 0x80cc, dos->e_lfanew + ne->ne_rsrctab, size.u.LowPart, &len );
|
|
|
|
if (!data) goto fail;
|
|
|
|
if (!memchr( data, 0, len )) goto fail;
|
2012-03-30 13:38:04 +02:00
|
|
|
|
2013-01-15 12:52:04 +01:00
|
|
|
len = MultiByteToWideChar( CP_ACP, 0, data, -1, NULL, 0 );
|
2012-03-30 13:38:04 +02:00
|
|
|
name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
|
2013-01-15 12:52:04 +01:00
|
|
|
if (name) MultiByteToWideChar( CP_ACP, 0, data, -1, name, len );
|
2012-03-30 13:38:04 +02:00
|
|
|
|
|
|
|
fail:
|
|
|
|
UnmapViewOfFile( ptr );
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
2020-10-26 12:04:36 +01:00
|
|
|
static int add_system_font_resource( const WCHAR *file, DWORD flags )
|
|
|
|
{
|
|
|
|
WCHAR path[MAX_PATH];
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* try in %WINDIR%/fonts, needed for Fotobuch Designer */
|
|
|
|
get_fonts_win_dir_path( file, path );
|
|
|
|
EnterCriticalSection( &font_cs );
|
|
|
|
ret = font_funcs->add_font( path, flags );
|
|
|
|
LeaveCriticalSection( &font_cs );
|
|
|
|
/* try in datadir/fonts (or builddir/fonts), needed for Magic the Gathering Online */
|
|
|
|
if (!ret)
|
|
|
|
{
|
|
|
|
get_fonts_data_dir_path( file, path );
|
|
|
|
EnterCriticalSection( &font_cs );
|
|
|
|
ret = font_funcs->add_font( path, flags );
|
|
|
|
LeaveCriticalSection( &font_cs );
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL remove_system_font_resource( LPCWSTR file, DWORD flags )
|
|
|
|
{
|
|
|
|
WCHAR path[MAX_PATH];
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
get_fonts_win_dir_path( file, path );
|
2020-11-04 09:12:24 +01:00
|
|
|
if (!(ret = remove_font( path, flags )))
|
2020-10-26 12:04:36 +01:00
|
|
|
{
|
|
|
|
get_fonts_data_dir_path( file, path );
|
2020-11-04 09:12:24 +01:00
|
|
|
ret = remove_font( path, flags );
|
2020-10-26 12:04:36 +01:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int add_font_resource( LPCWSTR file, DWORD flags )
|
|
|
|
{
|
|
|
|
WCHAR path[MAX_PATH];
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (GetFullPathNameW( file, MAX_PATH, path, NULL ))
|
|
|
|
{
|
|
|
|
DWORD addfont_flags = ADDFONT_ALLOW_BITMAP | ADDFONT_ADD_RESOURCE;
|
|
|
|
|
|
|
|
if (!(flags & FR_PRIVATE)) addfont_flags |= ADDFONT_ADD_TO_CACHE;
|
|
|
|
EnterCriticalSection( &font_cs );
|
|
|
|
ret = font_funcs->add_font( path, addfont_flags );
|
|
|
|
LeaveCriticalSection( &font_cs );
|
|
|
|
}
|
|
|
|
|
2020-11-05 10:44:16 +01:00
|
|
|
if (!ret && !wcschr( file, '\\' ))
|
2020-10-26 12:04:36 +01:00
|
|
|
ret = add_system_font_resource( file, ADDFONT_ALLOW_BITMAP | ADDFONT_ADD_RESOURCE );
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL remove_font_resource( LPCWSTR file, DWORD flags )
|
|
|
|
{
|
|
|
|
WCHAR path[MAX_PATH];
|
|
|
|
BOOL ret = FALSE;
|
|
|
|
|
|
|
|
if (GetFullPathNameW( file, MAX_PATH, path, NULL ))
|
|
|
|
{
|
|
|
|
DWORD addfont_flags = ADDFONT_ALLOW_BITMAP | ADDFONT_ADD_RESOURCE;
|
|
|
|
|
|
|
|
if (!(flags & FR_PRIVATE)) addfont_flags |= ADDFONT_ADD_TO_CACHE;
|
2020-11-04 09:12:24 +01:00
|
|
|
ret = remove_font( path, addfont_flags );
|
2020-10-26 12:04:36 +01:00
|
|
|
}
|
|
|
|
|
2020-11-05 10:44:16 +01:00
|
|
|
if (!ret && !wcschr( file, '\\' ))
|
2020-10-26 12:04:36 +01:00
|
|
|
ret = remove_system_font_resource( file, ADDFONT_ALLOW_BITMAP | ADDFONT_ADD_RESOURCE );
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-11-03 11:28:20 +01:00
|
|
|
static void load_system_bitmap_fonts(void)
|
2020-10-27 10:27:06 +01:00
|
|
|
{
|
2020-11-06 12:08:16 +01:00
|
|
|
static const WCHAR * const fonts[] = { L"FONTS.FON", L"OEMFONT.FON", L"FIXEDFON.FON" };
|
2020-10-27 10:27:06 +01:00
|
|
|
HKEY hkey;
|
|
|
|
WCHAR data[MAX_PATH];
|
|
|
|
DWORD i, dlen, type;
|
|
|
|
|
2020-11-06 12:08:16 +01:00
|
|
|
if (RegOpenKeyW( HKEY_CURRENT_CONFIG, L"Software\\Fonts", &hkey )) return;
|
2020-10-27 10:27:06 +01:00
|
|
|
for (i = 0; i < ARRAY_SIZE(fonts); i++)
|
|
|
|
{
|
|
|
|
dlen = sizeof(data);
|
|
|
|
if (!RegQueryValueExW( hkey, fonts[i], 0, &type, (BYTE *)data, &dlen ) && type == REG_SZ)
|
2020-11-27 15:38:05 +01:00
|
|
|
add_system_font_resource( data, ADDFONT_ALLOW_BITMAP );
|
2020-10-27 10:27:06 +01:00
|
|
|
}
|
|
|
|
RegCloseKey( hkey );
|
|
|
|
}
|
|
|
|
|
2020-10-27 10:27:32 +01:00
|
|
|
static void load_directory_fonts( WCHAR *path, UINT flags )
|
|
|
|
{
|
|
|
|
HANDLE handle;
|
|
|
|
WIN32_FIND_DATAW data;
|
|
|
|
WCHAR *p;
|
|
|
|
|
2020-11-05 10:44:16 +01:00
|
|
|
p = path + lstrlenW(path) - 1;
|
2020-10-27 10:27:32 +01:00
|
|
|
TRACE( "loading fonts from %s\n", debugstr_w(path) );
|
|
|
|
handle = FindFirstFileW( path, &data );
|
|
|
|
if (handle == INVALID_HANDLE_VALUE) return;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
|
2020-11-05 10:44:16 +01:00
|
|
|
lstrcpyW( p, data.cFileName );
|
2020-10-27 10:27:32 +01:00
|
|
|
font_funcs->add_font( path, flags );
|
|
|
|
} while (FindNextFileW( handle, &data ));
|
|
|
|
FindClose( handle );
|
|
|
|
}
|
|
|
|
|
2020-11-03 11:28:20 +01:00
|
|
|
static void load_file_system_fonts(void)
|
2020-10-27 10:27:32 +01:00
|
|
|
{
|
|
|
|
WCHAR *ptr, *next, path[MAX_PATH], value[1024];
|
|
|
|
DWORD len = ARRAY_SIZE(value);
|
|
|
|
|
|
|
|
/* Windows directory */
|
2020-11-06 12:08:16 +01:00
|
|
|
get_fonts_win_dir_path( L"*", path );
|
2020-11-27 15:38:05 +01:00
|
|
|
load_directory_fonts( path, 0 );
|
2020-10-27 10:27:32 +01:00
|
|
|
|
|
|
|
/* Wine data directory */
|
2020-11-06 12:08:16 +01:00
|
|
|
get_fonts_data_dir_path( L"*", path );
|
2020-11-27 15:38:05 +01:00
|
|
|
load_directory_fonts( path, ADDFONT_EXTERNAL_FONT );
|
2020-10-27 10:27:32 +01:00
|
|
|
|
|
|
|
/* custom paths */
|
|
|
|
/* @@ Wine registry key: HKCU\Software\Wine\Fonts */
|
2020-11-06 12:08:16 +01:00
|
|
|
if (!RegQueryValueExW( wine_fonts_key, L"Path", NULL, NULL, (BYTE *)value, &len ))
|
2020-10-27 10:27:32 +01:00
|
|
|
{
|
|
|
|
for (ptr = value; ptr; ptr = next)
|
|
|
|
{
|
2020-11-05 10:44:16 +01:00
|
|
|
if ((next = wcschr( ptr, ';' ))) *next++ = 0;
|
2020-10-27 10:27:32 +01:00
|
|
|
if (next && next - ptr < 2) continue;
|
|
|
|
lstrcpynW( path, ptr, MAX_PATH - 2 );
|
2020-11-06 12:08:16 +01:00
|
|
|
lstrcatW( path, L"\\*" );
|
2020-11-27 15:38:05 +01:00
|
|
|
load_directory_fonts( path, ADDFONT_EXTERNAL_FONT );
|
2020-10-27 10:27:32 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-03 11:28:20 +01:00
|
|
|
struct external_key
|
|
|
|
{
|
2020-11-27 15:38:03 +01:00
|
|
|
struct list entry;
|
|
|
|
WCHAR value[LF_FULLFACESIZE + 12];
|
2020-11-03 11:28:20 +01:00
|
|
|
};
|
|
|
|
|
2020-11-27 15:38:03 +01:00
|
|
|
static void update_external_font_keys(void)
|
2020-11-03 11:28:20 +01:00
|
|
|
{
|
2020-11-27 15:38:03 +01:00
|
|
|
struct list external_keys = LIST_INIT(external_keys);
|
|
|
|
HKEY winnt_key = 0, win9x_key = 0;
|
|
|
|
struct gdi_font_family *family;
|
|
|
|
struct external_key *key, *next;
|
|
|
|
struct gdi_font_face *face;
|
|
|
|
DWORD len, i = 0, type, dlen, vlen;
|
|
|
|
WCHAR value[LF_FULLFACESIZE + 12], path[MAX_PATH], *tmp;
|
|
|
|
WCHAR *file;
|
|
|
|
HKEY hkey;
|
2020-11-03 11:28:20 +01:00
|
|
|
|
2020-11-27 15:38:03 +01:00
|
|
|
RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",
|
|
|
|
0, NULL, 0, KEY_ALL_ACCESS, NULL, &winnt_key, NULL );
|
|
|
|
RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Fonts",
|
|
|
|
0, NULL, 0, KEY_ALL_ACCESS, NULL, &win9x_key, NULL );
|
2020-11-03 11:28:20 +01:00
|
|
|
|
2020-11-27 15:38:03 +01:00
|
|
|
/* enumerate the fonts and add external ones to the two keys */
|
2020-11-03 11:28:20 +01:00
|
|
|
|
2020-11-27 15:38:03 +01:00
|
|
|
if (RegCreateKeyW( wine_fonts_key, L"External Fonts", &hkey )) return;
|
2020-11-03 11:28:20 +01:00
|
|
|
|
|
|
|
vlen = ARRAY_SIZE(value);
|
|
|
|
dlen = sizeof(path);
|
|
|
|
while (!RegEnumValueW( hkey, i++, value, &vlen, NULL, &type, (BYTE *)path, &dlen ))
|
|
|
|
{
|
|
|
|
if (type != REG_SZ) goto next;
|
2020-11-27 15:38:03 +01:00
|
|
|
if ((tmp = wcsrchr( value, ' ' )) && !facename_compare( tmp, L" (TrueType)", -1 )) *tmp = 0;
|
2021-05-24 12:30:46 +02:00
|
|
|
if ((face = find_face_from_full_name( value )) && !wcsicmp( face->file, path ))
|
2020-11-27 15:38:03 +01:00
|
|
|
{
|
2021-05-24 12:30:46 +02:00
|
|
|
face->flags |= ADDFONT_EXTERNAL_FOUND;
|
2020-11-27 15:38:03 +01:00
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
if (tmp && !*tmp) *tmp = ' ';
|
|
|
|
if (!(key = HeapAlloc( GetProcessHeap(), 0, sizeof(*key) ))) break;
|
2020-11-05 10:44:16 +01:00
|
|
|
lstrcpyW( key->value, value );
|
2020-11-27 15:38:03 +01:00
|
|
|
list_add_tail( &external_keys, &key->entry );
|
2020-11-03 11:28:20 +01:00
|
|
|
next:
|
|
|
|
vlen = ARRAY_SIZE(value);
|
|
|
|
dlen = sizeof(path);
|
|
|
|
}
|
|
|
|
|
2020-11-13 10:05:55 +01:00
|
|
|
WINE_RB_FOR_EACH_ENTRY( family, &family_name_tree, struct gdi_font_family, name_entry )
|
2020-11-03 11:28:20 +01:00
|
|
|
{
|
|
|
|
LIST_FOR_EACH_ENTRY( face, &family->faces, struct gdi_font_face, entry )
|
|
|
|
{
|
|
|
|
if (!(face->flags & ADDFONT_EXTERNAL_FONT)) continue;
|
2020-11-27 15:38:03 +01:00
|
|
|
if ((face->flags & ADDFONT_EXTERNAL_FOUND)) continue;
|
2020-11-03 11:28:20 +01:00
|
|
|
|
2020-11-05 10:44:16 +01:00
|
|
|
lstrcpyW( value, face->full_name );
|
2020-11-06 12:08:16 +01:00
|
|
|
if (face->scalable) lstrcatW( value, L" (TrueType)" );
|
2020-11-03 11:28:20 +01:00
|
|
|
|
|
|
|
if (GetFullPathNameW( face->file, MAX_PATH, path, NULL ))
|
|
|
|
file = path;
|
2020-11-05 10:44:16 +01:00
|
|
|
else if ((file = wcsrchr( face->file, '\\' )))
|
2020-11-03 11:28:20 +01:00
|
|
|
file++;
|
|
|
|
else
|
|
|
|
file = face->file;
|
|
|
|
|
2020-11-05 10:44:16 +01:00
|
|
|
len = (lstrlenW(file) + 1) * sizeof(WCHAR);
|
2020-11-03 11:28:20 +01:00
|
|
|
RegSetValueExW( winnt_key, value, 0, REG_SZ, (BYTE *)file, len );
|
|
|
|
RegSetValueExW( win9x_key, value, 0, REG_SZ, (BYTE *)file, len );
|
|
|
|
RegSetValueExW( hkey, value, 0, REG_SZ, (BYTE *)file, len );
|
|
|
|
}
|
|
|
|
}
|
2020-11-27 15:38:03 +01:00
|
|
|
LIST_FOR_EACH_ENTRY_SAFE( key, next, &external_keys, struct external_key, entry )
|
2020-11-03 11:28:20 +01:00
|
|
|
{
|
|
|
|
RegDeleteValueW( win9x_key, key->value );
|
|
|
|
RegDeleteValueW( winnt_key, key->value );
|
|
|
|
RegDeleteValueW( hkey, key->value );
|
2020-11-27 15:38:03 +01:00
|
|
|
list_remove( &key->entry );
|
2020-11-03 11:28:20 +01:00
|
|
|
HeapFree( GetProcessHeap(), 0, key );
|
|
|
|
}
|
|
|
|
RegCloseKey( win9x_key );
|
|
|
|
RegCloseKey( winnt_key );
|
2020-11-27 15:38:03 +01:00
|
|
|
RegCloseKey( hkey );
|
2020-11-03 11:28:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void load_registry_fonts(void)
|
2020-10-27 10:27:20 +01:00
|
|
|
{
|
2020-11-27 15:38:02 +01:00
|
|
|
WCHAR value[LF_FULLFACESIZE + 12], data[MAX_PATH], *tmp;
|
2020-10-27 10:27:20 +01:00
|
|
|
DWORD i = 0, type, dlen, vlen;
|
|
|
|
HKEY hkey;
|
|
|
|
|
|
|
|
/* Look under HKLM\Software\Microsoft\Windows[ NT]\CurrentVersion\Fonts
|
|
|
|
for any fonts not installed in %WINDOWSDIR%\Fonts. They will have their
|
|
|
|
full path as the entry. Also look for any .fon fonts, since ReadFontDir
|
|
|
|
will skip these. */
|
2020-11-06 12:08:16 +01:00
|
|
|
if (RegOpenKeyW( HKEY_LOCAL_MACHINE,
|
|
|
|
is_win9x() ? L"Software\\Microsoft\\Windows\\CurrentVersion\\Fonts" :
|
|
|
|
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts", &hkey ))
|
2020-10-27 10:27:20 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
vlen = ARRAY_SIZE(value);
|
|
|
|
dlen = sizeof(data);
|
2020-11-27 15:38:04 +01:00
|
|
|
while (!RegEnumValueW( hkey, i++, value, &vlen, NULL, &type, NULL, NULL ))
|
2020-10-27 10:27:20 +01:00
|
|
|
{
|
2020-11-03 11:28:20 +01:00
|
|
|
if (type != REG_SZ) goto next;
|
2020-10-27 10:27:20 +01:00
|
|
|
dlen /= sizeof(WCHAR);
|
2020-11-27 15:38:02 +01:00
|
|
|
if ((tmp = wcsrchr( value, ' ' )) && !facename_compare( tmp, L" (TrueType)", -1 )) *tmp = 0;
|
|
|
|
if (find_face_from_full_name( value )) goto next;
|
|
|
|
if (tmp && !*tmp) *tmp = ' ';
|
|
|
|
|
2020-11-27 15:38:04 +01:00
|
|
|
if (RegQueryValueExW( hkey, value, NULL, NULL, (LPBYTE)data, &dlen ))
|
|
|
|
{
|
|
|
|
WARN( "Unable to get face path %s\n", debugstr_w(value) );
|
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
|
|
|
|
dlen /= sizeof(WCHAR);
|
2020-10-27 10:27:20 +01:00
|
|
|
if (data[0] && data[1] == ':')
|
2020-11-27 15:38:05 +01:00
|
|
|
add_font_resource( data, ADDFONT_ALLOW_BITMAP );
|
2020-11-06 12:08:16 +01:00
|
|
|
else if (dlen >= 6 && !wcsicmp( data + dlen - 5, L".fon" ))
|
2020-11-27 15:38:05 +01:00
|
|
|
add_system_font_resource( data, ADDFONT_ALLOW_BITMAP );
|
2020-11-03 11:28:20 +01:00
|
|
|
next:
|
2020-10-27 10:27:20 +01:00
|
|
|
vlen = ARRAY_SIZE(value);
|
|
|
|
dlen = sizeof(data);
|
|
|
|
}
|
|
|
|
RegCloseKey( hkey );
|
|
|
|
}
|
|
|
|
|
2020-11-05 10:32:04 +01:00
|
|
|
static const struct font_callback_funcs callback_funcs = { add_gdi_face };
|
|
|
|
|
2020-11-03 11:28:20 +01:00
|
|
|
/***********************************************************************
|
|
|
|
* font_init
|
|
|
|
*/
|
|
|
|
void font_init(void)
|
|
|
|
{
|
|
|
|
HANDLE mutex;
|
|
|
|
DWORD disposition;
|
|
|
|
|
2020-11-06 12:08:16 +01:00
|
|
|
if (RegCreateKeyExW( HKEY_CURRENT_USER, L"Software\\Wine\\Fonts", 0, NULL, 0,
|
2020-11-03 11:28:20 +01:00
|
|
|
KEY_ALL_ACCESS, NULL, &wine_fonts_key, NULL ))
|
|
|
|
return;
|
|
|
|
|
|
|
|
init_font_options();
|
|
|
|
update_codepage();
|
2020-11-05 10:32:04 +01:00
|
|
|
if (__wine_init_unix_lib( gdi32_module, DLL_PROCESS_ATTACH, &callback_funcs, &font_funcs )) return;
|
2020-11-03 11:28:20 +01:00
|
|
|
|
2020-11-27 15:38:05 +01:00
|
|
|
load_system_bitmap_fonts();
|
|
|
|
load_file_system_fonts();
|
|
|
|
font_funcs->load_fonts();
|
|
|
|
|
2020-11-06 12:08:16 +01:00
|
|
|
if (!(mutex = CreateMutexW( NULL, FALSE, L"__WINE_FONT_MUTEX__" ))) return;
|
2020-11-03 11:28:20 +01:00
|
|
|
WaitForSingleObject( mutex, INFINITE );
|
|
|
|
|
2020-11-06 12:08:16 +01:00
|
|
|
RegCreateKeyExW( wine_fonts_key, L"Cache", 0, NULL, REG_OPTION_VOLATILE,
|
2020-11-03 11:28:20 +01:00
|
|
|
KEY_ALL_ACCESS, NULL, &wine_fonts_cache_key, &disposition );
|
|
|
|
|
|
|
|
if (disposition == REG_CREATED_NEW_KEY)
|
|
|
|
{
|
2020-11-27 15:38:01 +01:00
|
|
|
load_registry_fonts();
|
2020-11-27 15:38:03 +01:00
|
|
|
update_external_font_keys();
|
2020-11-03 11:28:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseMutex( mutex );
|
|
|
|
|
2020-11-27 15:38:05 +01:00
|
|
|
if (disposition != REG_CREATED_NEW_KEY)
|
|
|
|
{
|
|
|
|
load_registry_fonts();
|
|
|
|
load_font_list_from_cache();
|
|
|
|
}
|
|
|
|
|
2020-11-03 11:28:20 +01:00
|
|
|
reorder_font_list();
|
|
|
|
load_gdi_font_subst();
|
|
|
|
load_gdi_font_replacements();
|
|
|
|
load_system_links();
|
|
|
|
dump_gdi_font_list();
|
|
|
|
dump_gdi_font_subst();
|
|
|
|
}
|
|
|
|
|
2002-06-22 03:19:29 +02:00
|
|
|
/***********************************************************************
|
2021-09-01 14:08:52 +02:00
|
|
|
* NtGdiAddFontResourceW (win32u.@)
|
2002-06-22 03:19:29 +02:00
|
|
|
*/
|
2021-09-01 14:08:52 +02:00
|
|
|
INT WINAPI NtGdiAddFontResourceW( const WCHAR *str, ULONG size, ULONG files, DWORD flags,
|
|
|
|
DWORD tid, void *dv )
|
2002-06-22 03:19:29 +02:00
|
|
|
{
|
2020-10-20 22:07:06 +02:00
|
|
|
int ret;
|
2012-03-30 13:38:04 +02:00
|
|
|
WCHAR *filename;
|
2013-01-15 12:52:04 +01:00
|
|
|
BOOL hidden;
|
2012-03-30 13:38:04 +02:00
|
|
|
|
2020-10-20 22:07:06 +02:00
|
|
|
if (!font_funcs) return 1;
|
2020-10-26 12:04:36 +01:00
|
|
|
if (!(ret = add_font_resource( str, flags )))
|
2007-09-07 19:11:09 +02:00
|
|
|
{
|
2007-09-27 18:57:51 +02:00
|
|
|
/* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
|
2007-09-07 19:11:09 +02:00
|
|
|
HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
|
|
|
|
if (hModule != NULL)
|
|
|
|
{
|
|
|
|
int num_resources = 0;
|
|
|
|
LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
|
|
|
|
|
2012-06-27 22:47:54 +02:00
|
|
|
TRACE("WineEngAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
|
2007-09-07 19:11:09 +02:00
|
|
|
wine_dbgstr_w(str));
|
|
|
|
if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
|
|
|
|
ret = num_resources;
|
|
|
|
FreeLibrary(hModule);
|
|
|
|
}
|
2013-01-15 12:52:04 +01:00
|
|
|
else if ((filename = get_scalable_filename( str, &hidden )) != NULL)
|
2012-03-30 13:38:04 +02:00
|
|
|
{
|
2020-10-26 12:04:36 +01:00
|
|
|
if (hidden) flags |= FR_PRIVATE | FR_NOT_ENUM;
|
|
|
|
ret = add_font_resource( filename, flags );
|
2012-03-30 13:38:04 +02:00
|
|
|
HeapFree( GetProcessHeap(), 0, filename );
|
|
|
|
}
|
2007-09-07 19:11:09 +02:00
|
|
|
}
|
|
|
|
return ret;
|
2000-03-19 22:20:54 +01:00
|
|
|
}
|
|
|
|
|
2005-12-06 11:32:41 +01:00
|
|
|
/***********************************************************************
|
2021-09-01 14:08:41 +02:00
|
|
|
* NtGdiAddFontMemResourceEx (win32u.@)
|
2005-12-06 11:32:41 +01:00
|
|
|
*/
|
2021-09-01 14:08:41 +02:00
|
|
|
HANDLE WINAPI NtGdiAddFontMemResourceEx( void *ptr, DWORD size, void *dv, ULONG dv_size,
|
|
|
|
DWORD *count )
|
2005-12-06 11:32:41 +01:00
|
|
|
{
|
2010-08-02 08:35:04 +02:00
|
|
|
HANDLE ret;
|
|
|
|
DWORD num_fonts;
|
2020-10-26 12:05:19 +01:00
|
|
|
void *copy;
|
2010-08-02 08:35:04 +02:00
|
|
|
|
2021-09-01 14:08:41 +02:00
|
|
|
if (!ptr || !size || !count)
|
2010-08-03 14:07:59 +02:00
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return NULL;
|
|
|
|
}
|
2020-10-20 22:07:06 +02:00
|
|
|
if (!font_funcs) return NULL;
|
2020-10-26 12:05:19 +01:00
|
|
|
if (!(copy = HeapAlloc( GetProcessHeap(), 0, size ))) return NULL;
|
|
|
|
memcpy( copy, ptr, size );
|
|
|
|
|
2020-10-22 11:54:35 +02:00
|
|
|
EnterCriticalSection( &font_cs );
|
2020-10-26 12:05:19 +01:00
|
|
|
num_fonts = font_funcs->add_mem_font( copy, size, ADDFONT_ALLOW_BITMAP | ADDFONT_ADD_RESOURCE );
|
2020-10-22 11:54:35 +02:00
|
|
|
LeaveCriticalSection( &font_cs );
|
2020-10-26 12:05:19 +01:00
|
|
|
|
|
|
|
if (!num_fonts)
|
2010-08-02 08:35:04 +02:00
|
|
|
{
|
2020-10-26 12:05:19 +01:00
|
|
|
HeapFree( GetProcessHeap(), 0, copy );
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: is the handle only for use in RemoveFontMemResourceEx or should it be a true handle?
|
|
|
|
* For now return something unique but quite random
|
|
|
|
*/
|
|
|
|
ret = (HANDLE)((INT_PTR)copy ^ 0x87654321);
|
|
|
|
|
|
|
|
__TRY
|
|
|
|
{
|
2021-09-01 14:08:41 +02:00
|
|
|
*count = num_fonts;
|
2020-10-26 12:05:19 +01:00
|
|
|
}
|
|
|
|
__EXCEPT_PAGE_FAULT
|
|
|
|
{
|
2021-09-01 14:08:41 +02:00
|
|
|
WARN( "page fault while writing to *count (%p)\n", count );
|
|
|
|
NtGdiRemoveFontMemResourceEx( ret );
|
2020-10-26 12:05:19 +01:00
|
|
|
ret = 0;
|
2010-08-02 08:35:04 +02:00
|
|
|
}
|
2020-10-26 12:05:19 +01:00
|
|
|
__ENDTRY
|
|
|
|
TRACE( "Returning handle %p\n", ret );
|
2010-08-02 08:35:04 +02:00
|
|
|
return ret;
|
2005-12-06 11:32:41 +01:00
|
|
|
}
|
|
|
|
|
2008-01-01 16:23:39 +01:00
|
|
|
/***********************************************************************
|
2021-09-01 14:08:41 +02:00
|
|
|
* NtGdiRemoveFontMemResourceEx (win32u.@)
|
2008-01-01 16:23:39 +01:00
|
|
|
*/
|
2021-09-01 14:08:41 +02:00
|
|
|
BOOL WINAPI NtGdiRemoveFontMemResourceEx( HANDLE handle )
|
2008-01-01 16:23:39 +01:00
|
|
|
{
|
2021-09-01 14:08:41 +02:00
|
|
|
FIXME( "(%p) stub\n", handle );
|
2008-01-01 16:23:39 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2002-06-22 03:19:29 +02:00
|
|
|
/***********************************************************************
|
2021-09-01 14:08:52 +02:00
|
|
|
* NtGdiRemoveFontResourceW (win32u.@)
|
2002-06-22 03:19:29 +02:00
|
|
|
*/
|
2021-09-01 14:08:52 +02:00
|
|
|
BOOL WINAPI NtGdiRemoveFontResourceW( const WCHAR *str, ULONG size, ULONG files, DWORD flags,
|
|
|
|
DWORD tid, void *dv )
|
2002-06-22 03:19:29 +02:00
|
|
|
{
|
2020-10-20 22:07:06 +02:00
|
|
|
int ret;
|
2013-01-15 12:54:02 +01:00
|
|
|
WCHAR *filename;
|
2013-01-15 12:52:04 +01:00
|
|
|
BOOL hidden;
|
2013-01-15 12:54:02 +01:00
|
|
|
|
2020-10-20 22:07:06 +02:00
|
|
|
if (!font_funcs) return TRUE;
|
|
|
|
|
2020-10-26 12:04:36 +01:00
|
|
|
if (!(ret = remove_font_resource( str, flags )))
|
2013-01-15 12:54:02 +01:00
|
|
|
{
|
|
|
|
/* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
|
|
|
|
HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
|
|
|
|
if (hModule != NULL)
|
|
|
|
{
|
|
|
|
WARN("Can't unload resources from PE file %s\n", wine_dbgstr_w(str));
|
|
|
|
FreeLibrary(hModule);
|
|
|
|
}
|
2013-01-15 12:52:04 +01:00
|
|
|
else if ((filename = get_scalable_filename( str, &hidden )) != NULL)
|
2013-01-15 12:54:02 +01:00
|
|
|
{
|
2020-10-26 12:04:36 +01:00
|
|
|
if (hidden) flags |= FR_PRIVATE | FR_NOT_ENUM;
|
|
|
|
ret = remove_font_resource( filename, flags );
|
2013-01-15 12:54:02 +01:00
|
|
|
HeapFree( GetProcessHeap(), 0, filename );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
2000-03-19 22:20:54 +01:00
|
|
|
}
|
2003-06-23 22:51:06 +02:00
|
|
|
|
2006-05-07 01:33:32 +02:00
|
|
|
/***********************************************************************
|
2021-08-30 13:54:30 +02:00
|
|
|
* NtGdiGetFontUnicodeRanges (win32u.@)
|
2007-03-01 20:30:12 +01:00
|
|
|
*
|
|
|
|
* Retrieve a list of supported Unicode characters in a font.
|
|
|
|
*
|
|
|
|
* PARAMS
|
|
|
|
* hdc [I] Handle to a device context.
|
|
|
|
* lpgs [O] GLYPHSET structure specifying supported character ranges.
|
|
|
|
*
|
|
|
|
* RETURNS
|
|
|
|
* Success: Number of bytes written to the buffer pointed to by lpgs.
|
|
|
|
* Failure: 0
|
|
|
|
*
|
2006-05-07 01:33:32 +02:00
|
|
|
*/
|
2021-08-30 13:54:30 +02:00
|
|
|
DWORD WINAPI NtGdiGetFontUnicodeRanges( HDC hdc, GLYPHSET *lpgs )
|
2006-05-07 01:33:32 +02:00
|
|
|
{
|
2011-10-20 16:26:26 +02:00
|
|
|
DWORD ret;
|
|
|
|
PHYSDEV dev;
|
2008-02-05 21:16:27 +01:00
|
|
|
DC *dc = get_dc_ptr(hdc);
|
2007-09-26 20:17:13 +02:00
|
|
|
|
|
|
|
TRACE("(%p, %p)\n", hdc, lpgs);
|
|
|
|
|
|
|
|
if (!dc) return 0;
|
|
|
|
|
2011-10-20 16:26:26 +02:00
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
|
|
|
|
ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
|
2008-02-05 21:16:27 +01:00
|
|
|
release_dc_ptr(dc);
|
2007-09-26 20:17:13 +02:00
|
|
|
return ret;
|
2006-05-07 01:33:32 +02:00
|
|
|
}
|
2007-09-26 20:21:34 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************
|
2021-08-30 13:54:30 +02:00
|
|
|
* NtGdiFontIsLinked (win32u.@)
|
2007-09-26 20:21:34 +02:00
|
|
|
*/
|
2021-08-30 13:54:30 +02:00
|
|
|
BOOL WINAPI NtGdiFontIsLinked( HDC hdc )
|
2007-09-26 20:21:34 +02:00
|
|
|
{
|
2008-02-05 21:16:27 +01:00
|
|
|
DC *dc = get_dc_ptr(hdc);
|
2011-10-21 11:37:48 +02:00
|
|
|
PHYSDEV dev;
|
|
|
|
BOOL ret;
|
2007-09-26 20:21:34 +02:00
|
|
|
|
|
|
|
if (!dc) return FALSE;
|
2011-10-21 11:37:48 +02:00
|
|
|
dev = GET_DC_PHYSDEV( dc, pFontIsLinked );
|
|
|
|
ret = dev->funcs->pFontIsLinked( dev );
|
2008-02-05 21:16:27 +01:00
|
|
|
release_dc_ptr(dc);
|
2007-09-26 20:21:34 +02:00
|
|
|
TRACE("returning %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
2008-02-27 18:00:06 +01:00
|
|
|
|
2008-07-26 19:20:33 +02:00
|
|
|
/*************************************************************
|
2021-08-30 13:54:30 +02:00
|
|
|
* NtGdiGetRealizationInfo (win32u.@)
|
2008-07-26 19:20:33 +02:00
|
|
|
*/
|
2021-08-30 13:54:30 +02:00
|
|
|
BOOL WINAPI NtGdiGetRealizationInfo( HDC hdc, struct font_realization_info *info )
|
2008-02-27 18:00:06 +01:00
|
|
|
{
|
2021-08-02 19:46:35 +02:00
|
|
|
BOOL is_v0 = info->size == FIELD_OFFSET(struct font_realization_info, file_count);
|
2011-10-21 11:40:35 +02:00
|
|
|
PHYSDEV dev;
|
|
|
|
BOOL ret;
|
2015-08-29 18:54:17 +02:00
|
|
|
DC *dc;
|
|
|
|
|
|
|
|
if (info->size != sizeof(*info) && !is_v0)
|
|
|
|
return FALSE;
|
2008-02-27 18:00:06 +01:00
|
|
|
|
2015-08-29 18:54:17 +02:00
|
|
|
dc = get_dc_ptr(hdc);
|
2008-07-31 17:47:22 +02:00
|
|
|
if (!dc) return FALSE;
|
2015-08-29 18:54:17 +02:00
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetFontRealizationInfo );
|
|
|
|
ret = dev->funcs->pGetFontRealizationInfo( dev, info );
|
2008-07-31 17:47:22 +02:00
|
|
|
release_dc_ptr(dc);
|
|
|
|
return ret;
|
2008-02-27 18:00:06 +01:00
|
|
|
}
|
2015-08-29 18:54:17 +02:00
|
|
|
|
2020-10-20 22:07:06 +02:00
|
|
|
/*************************************************************************
|
2021-08-30 13:54:30 +02:00
|
|
|
* NtGdiGetRasterizerCaps (win32u.@)
|
2020-10-20 22:07:06 +02:00
|
|
|
*/
|
2021-08-30 13:54:30 +02:00
|
|
|
BOOL WINAPI NtGdiGetRasterizerCaps( RASTERIZER_STATUS *status, UINT size )
|
2020-10-20 22:07:06 +02:00
|
|
|
{
|
2021-08-30 13:54:30 +02:00
|
|
|
status->nSize = sizeof(RASTERIZER_STATUS);
|
|
|
|
status->wFlags = font_funcs ? (TT_AVAILABLE | TT_ENABLED) : 0;
|
|
|
|
status->nLanguageID = 0;
|
2020-10-20 22:07:06 +02:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*************************************************************************
|
2021-08-30 13:54:44 +02:00
|
|
|
* NtGdiGetFontFileData (win32u.@)
|
2020-10-20 22:07:06 +02:00
|
|
|
*/
|
2021-08-30 13:54:44 +02:00
|
|
|
BOOL WINAPI NtGdiGetFontFileData( DWORD instance_id, DWORD file_index, UINT64 *offset,
|
|
|
|
void *buff, DWORD buff_size )
|
2020-10-20 22:07:06 +02:00
|
|
|
{
|
2020-10-22 11:54:35 +02:00
|
|
|
struct gdi_font *font;
|
2020-10-22 11:57:48 +02:00
|
|
|
DWORD tag = 0, size;
|
2020-10-22 11:54:35 +02:00
|
|
|
BOOL ret = FALSE;
|
2020-10-21 10:59:51 +02:00
|
|
|
|
2020-10-22 11:54:35 +02:00
|
|
|
if (!font_funcs) return FALSE;
|
|
|
|
EnterCriticalSection( &font_cs );
|
|
|
|
if ((font = get_font_from_handle( instance_id )))
|
2020-10-22 11:57:48 +02:00
|
|
|
{
|
|
|
|
if (font->ttc_item_offset) tag = MS_TTCF_TAG;
|
|
|
|
size = font_funcs->get_font_data( font, tag, 0, NULL, 0 );
|
2021-08-30 13:54:44 +02:00
|
|
|
if (size != GDI_ERROR && size >= buff_size && *offset <= size - buff_size)
|
|
|
|
ret = font_funcs->get_font_data( font, tag, *offset, buff, buff_size ) != GDI_ERROR;
|
2020-10-22 11:57:48 +02:00
|
|
|
else
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
|
|
}
|
2020-10-22 11:54:35 +02:00
|
|
|
LeaveCriticalSection( &font_cs );
|
|
|
|
return ret;
|
2020-10-20 22:07:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*************************************************************************
|
2021-08-30 13:54:30 +02:00
|
|
|
* NtGdiGetFontFileInfo (win32u.@)
|
2020-10-20 22:07:06 +02:00
|
|
|
*/
|
2021-08-30 13:54:30 +02:00
|
|
|
BOOL WINAPI NtGdiGetFontFileInfo( DWORD instance_id, DWORD file_index, struct font_fileinfo *info,
|
|
|
|
SIZE_T size, SIZE_T *needed )
|
2020-10-20 22:07:06 +02:00
|
|
|
{
|
2020-10-22 11:54:35 +02:00
|
|
|
SIZE_T required_size = 0;
|
|
|
|
struct gdi_font *font;
|
|
|
|
BOOL ret = FALSE;
|
2020-10-21 10:59:51 +02:00
|
|
|
|
2020-10-22 11:54:35 +02:00
|
|
|
EnterCriticalSection( &font_cs );
|
2020-10-21 10:59:51 +02:00
|
|
|
|
2020-10-22 11:54:35 +02:00
|
|
|
if ((font = get_font_from_handle( instance_id )))
|
2020-10-21 11:02:48 +02:00
|
|
|
{
|
2020-11-05 10:44:16 +01:00
|
|
|
required_size = sizeof(*info) + lstrlenW( font->file ) * sizeof(WCHAR);
|
2020-10-22 11:54:35 +02:00
|
|
|
if (required_size <= size)
|
|
|
|
{
|
2020-10-26 11:37:03 +01:00
|
|
|
info->writetime = font->writetime;
|
|
|
|
info->size.QuadPart = font->data_size;
|
2020-11-05 10:44:16 +01:00
|
|
|
lstrcpyW( info->path, font->file );
|
2020-10-22 11:54:35 +02:00
|
|
|
ret = TRUE;
|
|
|
|
}
|
|
|
|
else SetLastError( ERROR_INSUFFICIENT_BUFFER );
|
2020-10-21 11:02:48 +02:00
|
|
|
}
|
2020-10-22 11:54:35 +02:00
|
|
|
|
|
|
|
LeaveCriticalSection( &font_cs );
|
|
|
|
if (needed) *needed = required_size;
|
|
|
|
return ret;
|
2020-10-20 22:07:06 +02:00
|
|
|
}
|
|
|
|
|
2019-04-09 11:32:59 +02:00
|
|
|
/*************************************************************
|
2021-08-30 13:54:30 +02:00
|
|
|
* NtGdiGetCharWidthInfo (win32u.@)
|
2019-04-09 11:32:59 +02:00
|
|
|
*/
|
2021-08-30 13:54:30 +02:00
|
|
|
BOOL WINAPI NtGdiGetCharWidthInfo( HDC hdc, struct char_width_info *info )
|
2019-04-09 11:32:59 +02:00
|
|
|
{
|
|
|
|
PHYSDEV dev;
|
|
|
|
BOOL ret;
|
|
|
|
DC *dc;
|
|
|
|
|
|
|
|
dc = get_dc_ptr(hdc);
|
|
|
|
if (!dc) return FALSE;
|
|
|
|
dev = GET_DC_PHYSDEV( dc, pGetCharWidthInfo );
|
|
|
|
ret = dev->funcs->pGetCharWidthInfo( dev, info );
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
info->lsb = width_to_LP( dc, info->lsb );
|
|
|
|
info->rsb = width_to_LP( dc, info->rsb );
|
|
|
|
}
|
|
|
|
release_dc_ptr(dc);
|
|
|
|
return ret;
|
|
|
|
}
|