687 lines
27 KiB
NASM
687 lines
27 KiB
NASM
page ,132
|
||
;*****************************Module*Header*******************************\
|
||
; Module Name: cache.asm
|
||
;
|
||
;
|
||
; Created: 9-Dec-1992
|
||
; Author: Paul Butzi
|
||
;
|
||
; Copyright (c) 1990-1999 Microsoft Corporation
|
||
;
|
||
;*************************************************************************/
|
||
; Note: This module would be more efficient with Frame Pointer Omission
|
||
; (FPO), whereby the stack is addressed off ESP rather than EBP, so we
|
||
; could stop pushing and popping EBP. However, the ASM macros currently
|
||
; don't support FPO.
|
||
;*************************************************************************/
|
||
|
||
.386
|
||
.model small,c
|
||
|
||
assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
|
||
assume fs:nothing,gs:nothing
|
||
|
||
.xlist
|
||
include callconv.inc
|
||
include gdii386.inc
|
||
.list
|
||
|
||
|
||
.code
|
||
EXTRNP xprunFindRunRFONTOBJ,2
|
||
EXTRNP xpgdDefault,1
|
||
EXTRNP xInsertMetricsRFONTOBJ,3
|
||
EXTRNP xInsertMetricsPlusRFONTOBJ,3
|
||
EXTRNP xInsertGlyphbitsRFONTOBJ,3
|
||
|
||
ifdef FE_SB
|
||
EXTRNP xwpgdGetLinkMetricsRFONTOBJ,2
|
||
EXTRNP xwpgdGetLinkMetricsPlusRFONTOBJ,3
|
||
endif
|
||
|
||
|
||
FAST_WCHAR_BASE equ 20h ; Most ANSI fonts have a base of 32
|
||
|
||
;******************************Public*Routine******************************\
|
||
;
|
||
; BOOL RFONTOBJ::bGetGlyphMetrics (
|
||
; COUNT c,
|
||
; GLYPHPOS *pgp,
|
||
; WCHAR *pwc
|
||
; );
|
||
;
|
||
; Translate wchars into an array of GLYPHPOS structures, filling in
|
||
; the pointer to GLYPHDATA field. Only the metrics are assured to be
|
||
; valid; no attempt is made to ensure that the glyph data itself is
|
||
; present in the cache before the return to the caller.
|
||
;
|
||
; This routine is to be used primarily by GetTextExtent and GetCharWidths,
|
||
; which have no need for anything except metrics.
|
||
;
|
||
; A zero return means that we failed to insert the metrics due to some
|
||
; hard error, most likely a failure to commit memory in the glyph
|
||
; insertion routine.
|
||
;
|
||
; History:
|
||
; 21-Dec-92 -by- Michael Abrash
|
||
; Fixed bug in detecting run inclusion
|
||
; 9-Dec-92 -by- Paul Butzi
|
||
; Wrote it.
|
||
;**************************************************************************/
|
||
|
||
|
||
|
||
cPublicProc xGetGlyphMetrics,4,< \
|
||
uses ebx esi edi, \
|
||
pThis: ptr dword, \
|
||
c_: dword, \
|
||
pgp: ptr dword, \
|
||
pwc: dword >
|
||
mov eax, pThis ; (eax) = ptr to RFONTOBJ
|
||
mov eax, [eax].prfnt ; (eax) = ptr to RFONT
|
||
mov esi, pwc ; pointer to wchar data
|
||
;*486 pipelining
|
||
mov eax, [eax].wcgp ; (eax) = ptr to wcgp
|
||
mov edi, pgp ; pointer to glyphpos array to fill
|
||
;*486 pipelining
|
||
lea ebx, [eax].agprun ; (ebx) = ptr to first wcgp run
|
||
;*486 pipelining
|
||
mov ecx, [ebx].wcLow ; index of start of run
|
||
mov edx, [ebx].cGlyphs ; # of glyphs in run
|
||
mov ebx, [ebx].apgd ; pointer to run's pointers to cached
|
||
; glyphdata
|
||
|
||
push ebp
|
||
mov ebp,c_ ; we'll use EBP for the glyph count
|
||
; ***stack frame no longer available***
|
||
;
|
||
; Invariants:
|
||
; (esi) = ptr to wchar
|
||
; (edi) = ptr to pgp
|
||
; (ebx) = ptr to base of current run
|
||
; (ecx) = wcLow of current run
|
||
; (edx) = cGlyphs of current run
|
||
; (ebp) = count of glyphs remaining
|
||
loop_top:
|
||
|
||
sub eax, eax
|
||
mov ax, [esi] ; (eax) = wchar, zero extended
|
||
|
||
sub eax, ecx ; get index relative to current run base
|
||
cmp eax, edx ; is wchar in this run?
|
||
jae short find_run ; wrong run, better go get right one
|
||
|
||
run_found:
|
||
|
||
mov eax, [ebx+4*eax] ; (ecx) = ptr to glyphdata
|
||
|
||
|
||
;
|
||
; Invariants:
|
||
; (esi, edi, ebx, ecx, edx) as above at loop top
|
||
; (eax) = ptr to glyphdata
|
||
;
|
||
default_found:
|
||
and eax, eax ; is cached glyphdata there?
|
||
jz short get_glyph ; no glyphdata, better go get one
|
||
|
||
;
|
||
; Here, we are assured that the glyphdata is present in the cache
|
||
;
|
||
glyph_found:
|
||
mov [edi].gp_pgdf, eax ; set ptr to glyphdata in glyphpos
|
||
mov eax, [eax].gd_hg
|
||
mov [edi].gp_hg, eax ; set hg in glyphpos
|
||
|
||
|
||
add edi, SIZE_GLYPHPOS ; next glyphpos to fill in
|
||
add esi, 2 ; next wchar to look up
|
||
|
||
dec ebp ; any more glyphs?
|
||
jnz loop_top
|
||
|
||
pop ebp ; ***stack frame available***
|
||
|
||
mov eax, 1 ; success
|
||
stdRET xGetGlyphMetrics
|
||
|
||
|
||
|
||
|
||
;=======================================================================
|
||
; We got here because the current run does not contain the wchar we're
|
||
; interested in. Note that the following invariants must hold when
|
||
; we re-enter the loop (starred items must hold on entry, as well):
|
||
; (esi) = ptr to wchar*
|
||
; (edi) = ptr to pgp*
|
||
; (ebx) = ptr to apgd of new run
|
||
; (ecx) = wcLow of new run
|
||
; (edx) = cGlyphs of new run
|
||
; (eax) = ptr to glyphdata
|
||
; (ebp) = count of glyphs remaining*
|
||
;=======================================================================
|
||
align 4
|
||
find_run:
|
||
push ebp ; preserve count of remaining glpyhs
|
||
mov ebp,[esp+4] ; ***stack frame available***
|
||
; *****************************************
|
||
; * Note that the approach here is to get *
|
||
; * EBP off the stack, where it was *
|
||
; * pushed, by addressing off ESP. EBP *
|
||
; * remains pushed, so we don't need to *
|
||
; * re-push it when we're done. *
|
||
; * XCHGing EBP with the top of the stack *
|
||
; * would be cleaner, but XCHG locks the *
|
||
; * bus. *
|
||
; * This trick is repeated several times *
|
||
; * below. *
|
||
; *****************************************
|
||
|
||
sub eax, eax
|
||
mov ax, [esi] ; (eax) = current wchar
|
||
mov ebx, pThis
|
||
stdcall xprunFindRunRFONTOBJ, <ebx, eax> ; find the wchar's run
|
||
|
||
pop ebp ; <ebp> = glyph count
|
||
; ***stack frame no longer available***
|
||
mov ecx, [eax].wcLow ; index of start of new run
|
||
mov edx, [eax].cGlyphs ; # of glyphs in new run
|
||
mov ebx, [eax].apgd ; pointer to new run's pointers to
|
||
; cached glyphdata
|
||
sub eax, eax
|
||
mov ax, [esi] ; (eax) = current wchar
|
||
sub eax, ecx ; get index relative to new run base
|
||
cmp eax, edx ; is wchar in this run?
|
||
jb run_found ; yes, run with it
|
||
; not in any run; use default character
|
||
push ebp ; preserve count of remaining glyphs
|
||
mov ebp,[esp+4] ; ***stack frame available***
|
||
ifdef FE_SB ; call off to linked font handler
|
||
push ebx
|
||
push ecx
|
||
push edx
|
||
mov eax, pThis ; (eax) = pointer to RFONTOBJ
|
||
sub ebx,ebx ; (ebx) = 0
|
||
mov bx, [esi] ; (ebx) = current wchar
|
||
stdcall xwpgdGetLinkMetricsRFONTOBJ,<eax,ebx>
|
||
pop edx
|
||
pop ecx
|
||
pop ebx
|
||
else
|
||
mov eax, pThis
|
||
push ecx
|
||
push edx
|
||
stdcall xpgdDefault, <eax> ; eax = ptr to default character
|
||
pop edx
|
||
pop ecx
|
||
endif
|
||
pop ebp ; <ebp> = glyph count
|
||
jmp default_found ; go with the default character
|
||
|
||
;=======================================================================
|
||
; We got here because the glyph pointer in the wcgp run was null, meaning
|
||
; we don't yet have the metrics for this glyph. Note that the following
|
||
; invariants must be true on exit (starred items must hold on entry, as
|
||
; well):
|
||
; (esi) = ptr to wchar*
|
||
; (edi) = ptr to pgp*
|
||
; (ebx) = ptr to apgd of new run*
|
||
; (ecx) = wcLow of new run*
|
||
; (edx) = cGlyphs of new run*
|
||
; (eax) = ptr to glyphdata
|
||
; (ebp) = count of glyphs remaining*
|
||
;=======================================================================
|
||
align 4
|
||
get_glyph:
|
||
push ebp ; preserve count of remaining glpyhs
|
||
mov ebp,[esp+4] ; ***stack frame available***
|
||
|
||
push ebx
|
||
push edx
|
||
push ecx
|
||
|
||
sub eax, eax
|
||
mov ax, [esi] ; (eax) = wchar
|
||
mov edx, eax ; set aside wchar
|
||
sub eax, ecx ; (eax) = index into run
|
||
lea ebx, [ebx+eax*4] ; (ebx) = ptr to entry
|
||
mov ecx,pThis
|
||
stdcall xInsertMetricsRFONTOBJ, <ecx, ebx, edx>
|
||
pop ecx
|
||
pop edx
|
||
and eax, eax ; were we able to get the glyph metrics?
|
||
jz short failed ; no
|
||
|
||
mov eax, [ebx] ; get ptr to glyphdata from cache entry
|
||
|
||
pop ebx
|
||
|
||
pop ebp ; <ebp> = glyph count
|
||
; ***stack frame no longer available***
|
||
jmp glyph_found
|
||
|
||
failed:
|
||
pop ebx
|
||
|
||
pop eax ; clear glyph count from stack
|
||
pop eax ; clear pushed stack frame pointer from stack
|
||
|
||
sub eax, eax ; failure
|
||
stdRET xGetGlyphMetrics
|
||
|
||
stdENDP xGetGlyphMetrics
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
;******************************Public*Routine******************************\
|
||
;
|
||
; BOOL RFONTOBJ::bGetGlyphMetricsPlus (
|
||
; COUNT c,
|
||
; GLYPHPOS *pgp,
|
||
; WCHAR *pwc,
|
||
; BOOL *pbAccel
|
||
; );
|
||
;
|
||
; Translate wchars into an array of GLYPHPOS structures, filling in
|
||
; the pointer to GLYPHDATA field. Although only the metrics are assured to be
|
||
; valid, an attempt is made to ensure that the glyph data itself is
|
||
; present in the cache before the return to the caller. Failure in this
|
||
; attempt is indicated by clearing the flag *pbAccel. This allows the
|
||
; text code to tell the device driver that the STROBJ_bEnum callback is
|
||
; not needed.
|
||
;
|
||
; This routine is to be used primarily by TextOut and its kin.
|
||
;
|
||
; A zero return means that we failed to insert the metrics due to some
|
||
; hard error, most likely a failure to commit memory in the glyph
|
||
; insertion routine.
|
||
;
|
||
; This is a replacement for the C++ version in cache.cxx
|
||
;
|
||
; History:
|
||
; 21-Dec-92 -by- Michael Abrash
|
||
; Fixed bug in detecting run inclusion
|
||
; 9-Dec-92 -by- Paul Butzi
|
||
; Wrote it.
|
||
;**************************************************************************/
|
||
|
||
|
||
cPublicProc xGetGlyphMetricsPlus,5,< \
|
||
uses ebx esi edi, \
|
||
pThis: ptr dword, \
|
||
c_: dword, \
|
||
pgp: ptr dword, \
|
||
pwc: dword, \
|
||
pbAccel: ptr dword >
|
||
local pbacceltmp : dword ;1 if all glyph bits have been gotten
|
||
; so far, 0 if not
|
||
|
||
mov eax, pThis ; (eax) = ptr to RFONTOBJ
|
||
mov pbacceltmp,1 ; set bAccel to true (all glyph bits
|
||
; realized so far)
|
||
;*486 pipelining
|
||
mov eax, [eax].prfnt ; (eax) = ptr to RFONT
|
||
mov esi, pwc ; pointer to wchar data
|
||
;*486 pipelining
|
||
mov eax, [eax].wcgp ; (eax) = ptr to wcgp
|
||
mov edi, pgp ; pointer to glyphpos array to fill
|
||
;*486 pipelining
|
||
lea ebx, [eax].agprun ; (ebx) = ptr to first wcgp run
|
||
;*486 pipelining
|
||
push ebp ;*486 pipelining
|
||
mov ecx, [ebx].wcLow ; index of start of run
|
||
mov edx, [ebx].cGlyphs ; # of glyphs in run
|
||
mov ebx, [ebx].apgd ; pointer to run's pointers to cached
|
||
; glyphdata
|
||
|
||
mov ebp,c_ ; we'll use EBP for the glyph count
|
||
; ***stack frame no longer available***
|
||
|
||
;--------------------------------------------------------------------------
|
||
; Fast two-glyphs-at-a-time Pentium pipe-lined loop
|
||
;
|
||
; The philosophy of this loop is that for the vast majority of the time,
|
||
; all the glyphs will be in the proper range, have cached glyphdata, and
|
||
; have cached glyphbits -- and it takes advantage of that to better make
|
||
; use of both Pentium pipes by doing two glyphs at once. If one of those
|
||
; conditions fail, it converts to the single-glyph-at-a-time loop when
|
||
; that happens.
|
||
;
|
||
; Invariants:
|
||
; (esi) = ptr to 1st wchar
|
||
; (edi) = ptr to pgp
|
||
; (ecx) = ptr to 2nd wchar
|
||
; (ecx) = wcLow of current run
|
||
; (edx) = cGlyphs of current run
|
||
; (ebp) = count of glyphs remaining
|
||
; [esp] = wcLow of current run
|
||
|
||
cmp ecx, FAST_WCHAR_BASE ; fast loop handles wcLow values only
|
||
jne gmp_slow_loop_top ; of 32
|
||
|
||
dec ebp ; pre-decrement count
|
||
jz gmp_slow_loop_top ; only one character. it's okay to
|
||
; pop this through to gmp_slow_loop_top
|
||
; with a zero count -- it's effectively
|
||
; the same as a one count
|
||
|
||
push ecx ; wcLow is now at [esp]
|
||
|
||
gmp_fast_loop_top:
|
||
mov eax, [esi] ; 1U (eax) = first two glyphs
|
||
add edi, 2*SIZE_GLYPHPOS ; 1V each iteration does two glyphpos's.
|
||
; we do this now to eat up a free V
|
||
; pipe instruction
|
||
mov ecx, eax ; 1U
|
||
add esi, 4 ; 1V each iteration does two wchars.
|
||
; we do this now to eat up a free V
|
||
; pipe instruction
|
||
shr ecx, 16 ; 1U (ecx) = 2nd wchar, zero extended
|
||
and eax, 0ffffh ; 1V (eax) = 1st wchar, zero extended
|
||
|
||
sub eax, FAST_WCHAR_BASE ; 1U get index relative to current base
|
||
sub ecx, FAST_WCHAR_BASE ; 1V get index relative to current base
|
||
|
||
cmp eax, edx ; 1U is 1st wchar in this run?
|
||
jae gmp_restart_in_slow_loop; 1V wrong run, exit fast loop
|
||
cmp ecx, edx ; 1U is 2nd wchar in this run?
|
||
jae gmp_restart_in_slow_loop; 1V wrong run, exit fast loop
|
||
|
||
mov eax, [ebx+4*eax] ; 2U (eax) = ptr to 1st glyphdata
|
||
mov ecx, [ebx+4*ecx] ; 2V (ecx) = ptr to 2nd glyphdata
|
||
; (could be 3V if in same cache
|
||
; bank)
|
||
|
||
test eax, eax ; 1U is 1st cached glyphdata there?
|
||
jz gmp_restart_in_slow_loop; 1V no glyphdata, exit fast loop
|
||
test ecx, ecx ; 1U is 2nd cached glyphdata there?
|
||
jz gmp_restart_in_slow_loop; 1V no glyphdata, exit fast loop
|
||
|
||
cmp dword ptr [eax].gd_gdf, 0 ; 2U are 1st glyph bits in cache?
|
||
je gmp_restart_in_slow_loop ; 1V no, go get them
|
||
cmp dword ptr [ecx].gd_gdf, 0 ; 2U are 2nd glyph bits in cache?
|
||
je gmp_restart_in_slow_loop ; 1V no, go get them
|
||
|
||
mov [edi-2*SIZE_GLYPHPOS].gp_pgdf, eax
|
||
; 1U set ptr to glyphdata in glyphpos
|
||
mov eax, [eax].gd_hg ; 1V read 1st glyph handle
|
||
|
||
mov [edi-1*SIZE_GLYPHPOS].gp_pgdf, ecx
|
||
; 1U set ptr to glyphdata in glyphpos
|
||
mov ecx, [ecx].gd_hg ; 1V read 2nd glyph handle
|
||
|
||
mov [edi-2*SIZE_GLYPHPOS].gp_hg,eax ; 1U set handle in glyphpos
|
||
mov [edi-1*SIZE_GLYPHPOS].gp_hg,ecx ; 1V set handle in glyphpos
|
||
|
||
sub ebp, 2 ; 1U each iteration does two glyphs
|
||
jg gmp_fast_loop_top ; 1V more loops to do
|
||
pop ecx ; account for pushed wcLow
|
||
jz gmp_slow_loop_top ; odd number of glyphs, handle last one
|
||
|
||
pop ebp ; ***stack frame available***
|
||
mov ebx,pbaccel ; where we'll store whether all glyph
|
||
; bits found
|
||
mov eax, 1 ; success
|
||
mov [ebx], 1 ; success
|
||
|
||
stdRET xGetGlyphMetricsPlus
|
||
|
||
;--------------------------------------------------------------------------
|
||
; Not-so-fast one-glyph-at-a-time loop
|
||
;
|
||
; Invariants:
|
||
; (esi) = ptr to wchar
|
||
; (edi) = ptr to pgp
|
||
; (ebx) = ptr to base of current run
|
||
; (ecx) = wcLow of current run
|
||
; (edx) = cGlyphs of current run
|
||
; (ebp) = count of glyphs remaining
|
||
|
||
gmp_restart_in_slow_loop:
|
||
pop ecx ; (ecx) = wcLow of current run
|
||
inc ebp ; account for fast-loop preadjustments
|
||
sub edi, 2*SIZE_GLYPHPOS
|
||
sub esi, 4
|
||
|
||
gmp_slow_loop_top:
|
||
sub eax, eax
|
||
mov ax, [esi] ; (eax) = wchar, zero extended
|
||
|
||
sub eax, ecx ; get index relative to current run base
|
||
cmp eax, edx ; is wchar in this run?
|
||
jae short gmp_find_run ; wrong run, better go get right one
|
||
|
||
gmp_run_found:
|
||
mov eax, [ebx+4*eax] ; (ecx) = ptr to glyphdata
|
||
|
||
|
||
;
|
||
; Invariants:
|
||
; (esi, edi, ebx, ecx, edx) as above at loop top
|
||
; (eax) = ptr to glyphdata
|
||
;
|
||
gmp_default_found:
|
||
and eax, eax ; is cached glyphdata there?
|
||
jz gmp_get_glyph ; no glyphdata, better go get one
|
||
|
||
;
|
||
; Here, we are assured that the glyphdata is present in the cache
|
||
;
|
||
gmp_glyph_found:
|
||
cmp dword ptr [eax].gd_gdf, 0 ; are the glyph bits in the cache?
|
||
jz gmp_get_bits ; no, go get them
|
||
|
||
;
|
||
; Here, we have tried to get the glyphbits in the cache
|
||
;
|
||
gmp_got_bits:
|
||
mov [edi].gp_pgdf, eax ; set ptr to glyphdata in glyphpos
|
||
mov eax, [eax].gd_hg
|
||
mov [edi].gp_hg, eax ; set hg in glyphpos
|
||
|
||
|
||
add edi, SIZE_GLYPHPOS ; next glyphpos to fill in
|
||
add esi, 2 ; next wchar to look up
|
||
|
||
dec ebp ; any more glyphs?
|
||
jg gmp_slow_loop_top ; must be 'greater than' check
|
||
|
||
pop ebp ; ***stack frame available***
|
||
|
||
mov ebx,pbaccel ; where we'll store whether all glyph bits found
|
||
mov eax,pbacceltmp ; 0 if not all found, 1 if all found
|
||
mov [ebx],eax ; return whether we found all glyph bits or not
|
||
|
||
mov eax, 1 ; success
|
||
stdRET xGetGlyphMetricsPlus
|
||
|
||
|
||
|
||
;=======================================================================
|
||
; We got here because the current run does not contain the wchar we're
|
||
; interested in. Note that the following invariants must hold when
|
||
; we re-enter the loop (starred items must hold on entry, as well):
|
||
; (esi) = ptr to wchar*
|
||
; (edi) = ptr to pgp*
|
||
; (ebx) = ptr to apgd of new run
|
||
; (ecx) = wcLow of new run
|
||
; (edx) = cGlyphs of new run
|
||
; (eax) = ptr to glyphdata
|
||
; (ebp) = count of glyphs remaining*
|
||
;=======================================================================
|
||
align 4
|
||
gmp_find_run:
|
||
push ebp ; preserve count of remaining glpyhs
|
||
mov ebp,[esp+4] ; ***stack frame available***
|
||
|
||
sub eax, eax
|
||
mov ax, [esi] ; (eax) = current wchar
|
||
mov ebx, pThis
|
||
|
||
stdcall xprunFindRunRFONTOBJ, <ebx, eax>
|
||
|
||
pop ebp ; <ebp> = glyph count
|
||
; ***stack frame no longer available***
|
||
mov ecx, [eax].wcLow ; index of start of new run
|
||
mov edx, [eax].cGlyphs ; # of glyphs in new run
|
||
mov ebx, [eax].apgd ; pointer to new run's pointers to
|
||
; cached glyphdata
|
||
sub eax, eax
|
||
mov ax, [esi] ; (eax) = current wchar
|
||
sub eax, ecx ; get index relative to new run base
|
||
cmp eax, edx ; is wchar in this run?
|
||
jb gmp_run_found ; yes, run with it
|
||
; not in any run; use default character
|
||
push ebp ; preserve count of remaining glyphs
|
||
mov ebp,[esp+4] ; ***stack frame available***
|
||
|
||
ifdef FE_SB
|
||
push ebx
|
||
push ecx
|
||
push edx
|
||
mov eax, pThis ; (eax) = pointer to RFONTOBJ
|
||
lea ebx, pbacceltmp ; (ebx) = pointer to pbacceltmp
|
||
; (esi) = pointer to current wchar
|
||
stdcall xwpgdGetLinkMetricsPlusRFONTOBJ,<eax,esi,ebx>
|
||
pop edx
|
||
pop ecx
|
||
pop ebx ; (eax) is now proper wpgd
|
||
else
|
||
mov eax,pThis
|
||
push ecx
|
||
push edx
|
||
stdcall xpgdDefault, <eax> ; eax = ptr to default character
|
||
pop edx
|
||
pop ecx
|
||
endif
|
||
pop ebp ; <ebp> = glyph count
|
||
; ***stack frame no longer available***
|
||
|
||
jmp gmp_default_found ; go with the default character
|
||
|
||
|
||
;=======================================================================
|
||
; We got here because the glyph pointer in the wcgp run was null, meaning
|
||
; we don't yet have the metrics for this glyph. Note that the following
|
||
; invariants must be true on exit (starred items must hold on entry, as
|
||
; well):
|
||
; (esi) = ptr to wchar*
|
||
; (edi) = ptr to pgp*
|
||
; (ebx) = ptr to apgd of new run*
|
||
; (ecx) = wcLow of new run*
|
||
; (edx) = cGlyphs of new run*
|
||
; (eax) = ptr to glyphdata
|
||
; (ebp) = count of glyphs remaining*
|
||
;=======================================================================
|
||
align 4
|
||
gmp_get_glyph:
|
||
push ebp ; preserve count of remaining glpyhs
|
||
mov ebp,[esp+4] ; ***stack frame available***
|
||
|
||
push ebx
|
||
push edx
|
||
push ecx
|
||
|
||
sub eax, eax
|
||
mov ax, [esi] ; (eax) = wchar
|
||
mov edx, eax ; set aside wchar
|
||
sub eax, ecx ; (eax) = index into run
|
||
lea ebx, [ebx+4*eax] ; (ebx) = ptr to entry
|
||
mov ecx,pThis
|
||
stdcall xInsertMetricsPlusRFONTOBJ, <ecx, ebx, edx>
|
||
pop ecx
|
||
pop edx
|
||
and eax, eax ; were we able to get the glyph metrics?
|
||
jz short gmp_failed ; no
|
||
|
||
mov eax, [ebx] ; get ptr to glyphdata from it
|
||
|
||
pop ebx
|
||
|
||
pop ebp ; <ebp> = glyph count
|
||
; ***stack frame no longer available***
|
||
jmp gmp_glyph_found
|
||
|
||
gmp_failed:
|
||
pop ebx
|
||
|
||
pop eax ; clear glyph count from stack
|
||
pop eax ; clear pushed stack frame pointer from stack
|
||
|
||
sub eax, eax ;failure
|
||
stdRET xGetGlyphMetricsPlus
|
||
|
||
;=======================================================================
|
||
; We get here if we need to try to load the bits for the glyph we're
|
||
; interested in (because the bits havene't been realized yet). We only
|
||
; even bother to try if all bits have successfully been realized so far,
|
||
; because it's only useful to realize glyphs if we can get all of them.
|
||
; Note that the following invariants must be true on both entry and exit.
|
||
; (esi) = ptr to wchar
|
||
; (edi) = ptr to pgp
|
||
; (ebx) = ptr to apgd of new run
|
||
; (ecx) = wcLow of new run
|
||
; (edx) = cGlyphs of new run
|
||
; (eax) = ptr to glyphdata
|
||
; (ebp) = count of glyphs remaining
|
||
;=======================================================================
|
||
align 4
|
||
gmp_get_bits:
|
||
push ebp ; preserve count of remaining glpyhs
|
||
mov ebp,[esp+4] ; ***stack frame available***
|
||
|
||
cmp pbacceltmp,0 ;if we already failed to get glyph bits
|
||
je short got_the_bits_done ; once, no point in trying again
|
||
|
||
push ecx
|
||
mov ecx, pThis
|
||
push edx ;*486 pipelining
|
||
mov edx, [ecx].prfnt
|
||
push eax ;*486 pipelining
|
||
cmp dword ptr [edx].ulContent, FO_HGLYPHS
|
||
je short got_the_bits
|
||
|
||
sub edx,edx
|
||
cmp pwc,esi
|
||
sbb edx,-1 ; EDX == TRUE if first wc, FALSE else
|
||
stdcall xInsertGlyphbitsRFONTOBJ, <ecx, eax, edx> ;try to get the bits
|
||
|
||
and eax, eax ; did we succeed in getting the bits?
|
||
jnz short got_the_bits ; yes, we got the bits
|
||
mov pbacceltmp, eax ; didn't get the glyph (note: EAX is zero)
|
||
got_the_bits:
|
||
pop eax
|
||
pop edx
|
||
pop ecx
|
||
got_the_bits_done:
|
||
pop ebp ; <ebp> = glyph count
|
||
; ***stack frame no longer available***
|
||
jmp gmp_got_bits
|
||
|
||
|
||
stdENDP xGetGlyphMetricsPlus
|
||
|
||
|
||
|
||
end
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|