You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1385 lines
44 KiB
1385 lines
44 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: fntxform.cxx
|
|
*
|
|
* Created: 02-Feb-1993 16:33:14
|
|
* Author: Kirk Olynyk [kirko]
|
|
*
|
|
* Copyright (c) 1991-1999 Microsoft Corporation
|
|
\**************************************************************************/
|
|
|
|
|
|
#ifdef COMMENT_BLOCK
|
|
|
|
Author of these notes: BodinD
|
|
|
|
Differences between vector fonts and tt fonts in win31 + notes about what
|
|
nt does in these cases
|
|
|
|
1) Italicization
|
|
|
|
for vector fonts it is done is device space (wrong)
|
|
after notional to device transform has been applied
|
|
|
|
for tt fonts it is done right, font is first italicized in notional
|
|
space and then notional to device transform is applied.
|
|
|
|
on NT I italicized both vector and tt fonts in notional space.
|
|
|
|
2) emboldening
|
|
|
|
On NT I was able to fix vector fonts so as to shift
|
|
the glyph in the direction of baseline (which may be different
|
|
from x axis if esc != 0) thus preserving
|
|
rotational invariance of emboldened vector fonts. (check it out, it is cool)
|
|
|
|
for NT 5.0 we will have this also working for TT.
|
|
|
|
3) scaling properties under anisotropic page to device transform
|
|
|
|
tt fonts scale ISOtropically which clearly is wrong for
|
|
ANISOtropic page to device transform. The isotropic scaling factor
|
|
for tt fonts is the ABSOLUTE VALUE value of the yy component
|
|
of the page to device transform. From here it follows that
|
|
tt fonts igore the request to flip x and/or y axis
|
|
and the text is always written left to right up side up.
|
|
|
|
unlike tt fonts, vector fonts do scale ANISOtropically given
|
|
the anisotropic page to device xform. The request to flip
|
|
y axis is ignored (like for tt fonts). If the tranform
|
|
requests the flip of text in x axis, the text comes out GARBLED.
|
|
(DavidW, please, give it a try)
|
|
|
|
on NT I emulated this behavior in COMPATIBLE mode, execpt for the
|
|
GARBLED "mode" for vector fonts. In ADVANCED mode I made both vt and tt
|
|
fonts respect xform and behave in the same fashion wrt xforms.
|
|
|
|
4) interpretation of escapement and orientation
|
|
|
|
in tt case escapement is intepreted as DEVICE space concept
|
|
What this means is that after notional to world and world to
|
|
device scaling factors are applied the font is rotated in device space.
|
|
(conceptually wrong but agrees with win31 spec).
|
|
|
|
in vector font case escapement is intepreted as WORLD space concept
|
|
font is first rotated in world space and then world (page) to device
|
|
transform is applied.
|
|
(conceptually correct but it disagrees with with win31 spec)
|
|
|
|
on NT I went through excruiciating pain to emulate this behavior
|
|
under COMPATIBLE mode. In ADVANCED mode, vector and tt fonts
|
|
behave the same and esc and orientation are interpreted as WORLD
|
|
space concepts.
|
|
|
|
|
|
5) behavior in case of (esc != orientation)
|
|
|
|
tt fonts set orientation = esc
|
|
|
|
vector fonts snap orientation to the nearest multiple of
|
|
90 degrees relative to orientation.
|
|
(e.g. esc=300, or = -500 => esc = 300, or = - 600)
|
|
(DavidW, please, give it a try, also please use anisotropic
|
|
xform with window extents (-1,1))
|
|
|
|
|
|
on NT we emulate this behavior for in COMPATIBLE mode,
|
|
except for snapp orientation "fetature". The motivation is that
|
|
apps will explicitely set orientation and escapement to differ
|
|
by +/- 900, if they want it, rather than make use
|
|
of "snapping feature". In advanced mode if esc!=orientation
|
|
we use egg-shell algorithm to render text.
|
|
|
|
|
|
|
|
|
|
#endif COMMENT_BLOCK
|
|
|
|
|
|
|
|
#include "precomp.hxx"
|
|
#include "flhack.hxx"
|
|
// We include winuserp.h for the app compatibility #define GACF2_MSSHELLDLG
|
|
#include "winuserp.h"
|
|
|
|
//
|
|
// external procedures from draweng.cxx
|
|
//
|
|
|
|
extern BOOL gbShellFontCompatible;
|
|
|
|
EFLOAT efCos(EFLOAT x);
|
|
EFLOAT efSin(EFLOAT x);
|
|
|
|
/******************************Public*Routine******************************\
|
|
* lGetDefaultWorldHeight *
|
|
* *
|
|
* "If lfHeight is zero, a reasonable default size is substituted." *
|
|
* [SDK Vol 2]. Fortunately, the device driver is kind enough to *
|
|
* suggest a nice height (in pixels). We shall return this suggestion *
|
|
* in World corrdinates. *
|
|
* *
|
|
* History: *
|
|
* Thu 23-Jul-1992 13:01:49 by Kirk Olynyk [kirko] *
|
|
* Wrote it. *
|
|
\**************************************************************************/
|
|
|
|
LONG
|
|
lGetDefaultWorldHeight(
|
|
DCOBJ *pdco
|
|
)
|
|
{
|
|
LONG lfHeight;
|
|
{
|
|
PDEVOBJ pdo(pdco->hdev());
|
|
if (!pdo.bValid())
|
|
{
|
|
RIP("gdisrv!MAPPER:MAPPER -- invalid DCOBJ\n");
|
|
return(FM_EMERGENCY_DEFAULT_HEIGHT);
|
|
}
|
|
|
|
LFONTOBJ lfo(pdo.hlfntDefault());
|
|
if (!lfo.bValid())
|
|
{
|
|
RIP("gdisrv!MAPPER::MAPPER -- invalid LFONTOBJ\n");
|
|
return(FM_EMERGENCY_DEFAULT_HEIGHT);
|
|
}
|
|
|
|
lfHeight = lfo.plfw()->lfHeight;
|
|
}
|
|
|
|
//
|
|
// Now I must transform this default height in pixels to a height
|
|
// in World coordinates. Then this default height must be written
|
|
// into the LFONTOBJ supplied by the DC.
|
|
//
|
|
if (!pdco->pdc->bWorldToDeviceIdentity())
|
|
{
|
|
//
|
|
// Calculate the scaling factor along the y direction
|
|
// The correct thing to do might be to take the
|
|
// scaling factor along the ascender direction [kirko]
|
|
//
|
|
EFLOAT efT;
|
|
efT.eqMul(pdco->pdc->efM21(),pdco->pdc->efM21());
|
|
|
|
EFLOAT efU;
|
|
efU.eqMul(pdco->pdc->efM22(),pdco->pdc->efM22());
|
|
|
|
efU.eqAdd(efU,efT);
|
|
efU.eqSqrt(efU);
|
|
|
|
// at this point efU scales from world to device
|
|
|
|
efT.vSetToOne();
|
|
efU.eqDiv(efT,efU);
|
|
|
|
// at this point efU scales from device to world
|
|
|
|
lfHeight = lCvt(efU,FIX_FROM_LONG(lfHeight));
|
|
}
|
|
|
|
// insure against a trivial default height
|
|
|
|
if (lfHeight == 0)
|
|
{
|
|
return(FM_EMERGENCY_DEFAULT_HEIGHT);
|
|
}
|
|
|
|
//
|
|
// This value should be the character height and not the CELL height for
|
|
// Win 3.1 compatability. Fine Windows apps like CA Super Project will
|
|
// have clipped text if this isn't the case. [gerritv]
|
|
//
|
|
|
|
lfHeight *= -1;
|
|
|
|
|
|
return(lfHeight);
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vGetNtoW
|
|
*
|
|
* Calculates the notional to world transformation for fonts. This
|
|
* includes that funny factor of -1 for the different mapping modes
|
|
*
|
|
* Called by:
|
|
* bGetNtoW [FONTMAP.CXX]
|
|
*
|
|
* History:
|
|
* Wed 15-Apr-1992 15:35:10 by Kirk Olynyk [kirko]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
LONG lNormAngle(LONG lAngle);
|
|
|
|
VOID vGetNtoW
|
|
(
|
|
MATRIX *pmx, // destination for transform
|
|
LOGFONTW *pelfw, // wish list
|
|
IFIOBJ& ifio, // font to be used
|
|
DCOBJ *pdco
|
|
)
|
|
{
|
|
LONG lAngle,lfHeight;
|
|
EFLOAT efHeightScale,efWidthScale;
|
|
|
|
lfHeight = pelfw->lfHeight;
|
|
|
|
if (lfHeight == 0)
|
|
{
|
|
lfHeight = lGetDefaultWorldHeight(pdco);
|
|
}
|
|
ASSERTGDI(lfHeight,"gdisrv!vGetNtoW -- zero lfHeight\n");
|
|
|
|
// compute the height scale:
|
|
|
|
{
|
|
EFLOAT efHeightNum,efHeightDen;
|
|
|
|
if (lfHeight > 0)
|
|
{
|
|
efHeightNum = lfHeight;
|
|
efHeightDen = ifio.lfHeight();
|
|
}
|
|
else if (lfHeight < 0)
|
|
{
|
|
efHeightNum = -lfHeight;
|
|
efHeightDen = (LONG) ifio.fwdUnitsPerEm();
|
|
}
|
|
efHeightScale.eqDiv(efHeightNum,efHeightDen);
|
|
}
|
|
|
|
// compute the width scale:
|
|
|
|
POINTL ptlRes;
|
|
|
|
if (pelfw->lfWidth != 0)
|
|
{
|
|
EFLOAT efWidthNum,efWidthDen;
|
|
|
|
ptlRes.x = ptlRes.y = 1;
|
|
|
|
if (ifio.lfWidth() >= 0)
|
|
{
|
|
efWidthNum = (LONG) ABS(pelfw->lfWidth);
|
|
efWidthDen = ifio.lfWidth();
|
|
efWidthScale.eqDiv(efWidthNum,efWidthDen);
|
|
}
|
|
else
|
|
{
|
|
RIP(" gdisrv!vGetNtoW -- bad fwdAveCharWidth\n");
|
|
efWidthScale = efHeightScale;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ptlRes = *ifio.pptlAspect();
|
|
efWidthScale = efHeightScale;
|
|
}
|
|
|
|
// make sure that fonts look the same on printers of different resolutions:
|
|
|
|
PDEVOBJ pdo(pdco->hdev());
|
|
if (pdo.bValid())
|
|
{
|
|
if (pdo.ulLogPixelsX() != pdo.ulLogPixelsY())
|
|
{
|
|
ptlRes.y *= (LONG)pdo.ulLogPixelsX();
|
|
ptlRes.x *= (LONG)pdo.ulLogPixelsY();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RIP("gdisrv!bGetNtoW, pdevobj problem\n");
|
|
}
|
|
|
|
pmx->efM11.vSetToZero();
|
|
pmx->efM12.vSetToZero();
|
|
pmx->efM21.vSetToZero();
|
|
pmx->efM22.vSetToZero();
|
|
|
|
// Get the orientation from the LOGFONT. Win 3.1 treats the orientation
|
|
// as a rotation towards the negative y-axis. We do the same, which
|
|
// requires adjustment for some map modes.
|
|
|
|
lAngle = pelfw->lfOrientation;
|
|
if (pdco->pdc->bYisUp())
|
|
lAngle = 3600-lAngle;
|
|
lAngle = lNormAngle(lAngle);
|
|
|
|
switch (lAngle)
|
|
{
|
|
case 0 * ORIENTATION_90_DEG:
|
|
|
|
pmx->efM11 = efWidthScale;
|
|
pmx->efM22 = efHeightScale;
|
|
|
|
if (!pdco->pdc->bYisUp())
|
|
{
|
|
pmx->efM22.vNegate();
|
|
}
|
|
break;
|
|
|
|
case 1 * ORIENTATION_90_DEG:
|
|
|
|
pmx->efM12 = efWidthScale;
|
|
pmx->efM21 = efHeightScale;
|
|
|
|
if (!pdco->pdc->bYisUp())
|
|
{
|
|
pmx->efM12.vNegate();
|
|
}
|
|
pmx->efM21.vNegate();
|
|
break;
|
|
|
|
case 2 * ORIENTATION_90_DEG:
|
|
|
|
pmx->efM11 = efWidthScale;
|
|
pmx->efM22 = efHeightScale;
|
|
|
|
pmx->efM11.vNegate();
|
|
if (pdco->pdc->bYisUp())
|
|
{
|
|
pmx->efM22.vNegate();
|
|
}
|
|
break;
|
|
|
|
case 3 * ORIENTATION_90_DEG:
|
|
|
|
pmx->efM12 = efWidthScale;
|
|
pmx->efM21 = efHeightScale;
|
|
|
|
if (pdco->pdc->bYisUp())
|
|
{
|
|
pmx->efM12.vNegate();
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
{
|
|
EFLOATEXT efAngle = lAngle;
|
|
efAngle /= (LONG) 10;
|
|
|
|
EFLOAT efCosine = efCos(efAngle);
|
|
EFLOAT efSine = efSin(efAngle);
|
|
|
|
pmx->efM11.eqMul(efWidthScale, efCosine);
|
|
pmx->efM22.eqMul(efHeightScale,efCosine);
|
|
|
|
pmx->efM12.eqMul(efWidthScale, efSine);
|
|
pmx->efM21.eqMul(efHeightScale,efSine);
|
|
}
|
|
pmx->efM21.vNegate();
|
|
if (!pdco->pdc->bYisUp())
|
|
{
|
|
pmx->efM12.vNegate();
|
|
pmx->efM22.vNegate();
|
|
}
|
|
break;
|
|
}
|
|
|
|
// adjust for non-square resolution:
|
|
|
|
if (pdo.ulLogPixelsX() != pdo.ulLogPixelsY())
|
|
{
|
|
EFLOATEXT efTmp = (LONG)pdo.ulLogPixelsX();
|
|
efTmp /= (LONG)pdo.ulLogPixelsY();
|
|
|
|
if (pelfw->lfWidth == 0)
|
|
{
|
|
pmx->efM11 *= efTmp;
|
|
pmx->efM21 *= efTmp;
|
|
}
|
|
else
|
|
{
|
|
pmx->efM12 /= efTmp;
|
|
pmx->efM21 *= efTmp;
|
|
}
|
|
}
|
|
|
|
EXFORMOBJ xoNW(pmx, DONT_COMPUTE_FLAGS);
|
|
xoNW.vRemoveTranslation();
|
|
xoNW.vComputeAccelFlags();
|
|
}
|
|
|
|
//
|
|
// galFloat -- an array of LONG's that represent the IEEE floating
|
|
// point equivalents of the integers corresponding
|
|
// to the indices
|
|
//
|
|
|
|
LONG
|
|
galFloat[] = {
|
|
0x00000000, // = 0.0
|
|
0x3f800000, // = 1.0
|
|
0x40000000, // = 2.0
|
|
0x40400000, // = 3.0
|
|
0x40800000, // = 4.0
|
|
0x40a00000, // = 5.0
|
|
0x40c00000, // = 6.0
|
|
0x40e00000, // = 7.0
|
|
0x41000000 // = 8.0
|
|
};
|
|
|
|
|
|
LONG
|
|
galFloatNeg[] = {
|
|
0x00000000, // = 0.0
|
|
0xBf800000, // = -1.0
|
|
0xC0000000, // = -2.0
|
|
0xC0400000, // = -3.0
|
|
0xC0800000, // = -4.0
|
|
0xC0a00000, // = -5.0
|
|
0xC0c00000, // = -6.0
|
|
0xC0e00000, // = -7.0
|
|
0xC1000000 // = -8.0
|
|
};
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* bGetNtoD
|
|
*
|
|
* Get the notional to device transform for the font drivers
|
|
*
|
|
* Called by:
|
|
* PFEOBJ::bSetFontXform [PFEOBJ.CXX]
|
|
*
|
|
* History:
|
|
* Tue 12-Jan-1993 11:58:41 by Kirk Olynyk [kirko]
|
|
* Added a quick code path for non-transformable (bitmap) fonts.
|
|
* Wed 15-Apr-1992 15:09:22 by Kirk Olynyk [kirko]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
bGetNtoD(
|
|
FD_XFORM *pfdx, // pointer to the buffer to recieve the
|
|
// notional to device transformation for the
|
|
// font driver. There are a couple of
|
|
// important things to remember. First,
|
|
// according to the conventions of the ISO
|
|
// committee, the coordinate space for notional
|
|
// (font designer) spaces are cartesian.
|
|
// However, due to a series of errors on my part
|
|
// [kirko] the convention that is used by the
|
|
// DDI is that the notional to device transformation
|
|
// passed over the DDI assumes that both the notional
|
|
// and the device space are anti-Cartesian, that is,
|
|
// positive y increases in the downward direction.
|
|
// The fontdriver assumes that
|
|
// one unit in device space corresponds to the
|
|
// distance between pixels. This is different from
|
|
// GDI's internal view, where one device unit
|
|
// corresponds to a sub-pixel unit.
|
|
|
|
|
|
LOGFONTW *pelfw, // points to the extended logical font defining
|
|
// the font that is requested by the application.
|
|
// Units are ususally in World coordinates.
|
|
|
|
IFIOBJ& ifio, // font to be used
|
|
|
|
DCOBJ *pdco, // the device context defines the transforms between
|
|
// the various coordinate spaces.
|
|
|
|
POINTL* const pptlSim
|
|
)
|
|
{
|
|
MATRIX mxNW, mxND;
|
|
|
|
if(( pptlSim->x ) && !ifio.bContinuousScaling())
|
|
|
|
{
|
|
//
|
|
// This code path is for bitmap / non-scalable fonts. The notional
|
|
// to device transformation is determined by simply looking up
|
|
// the scaling factors for both the x-direction and y-direcion
|
|
//
|
|
|
|
#if DBG
|
|
if (!(0 < pptlSim->x && pptlSim->x <= sizeof(galFloat)/sizeof(LONG)))
|
|
{
|
|
DbgPrint("\t*pptlSim = (%d,%d)\n",pptlSim->x,pptlSim->y);
|
|
RIP("gre -- bad *pptlSim\n");
|
|
|
|
//
|
|
// bogus fix up for debugging purposes only
|
|
//
|
|
pptlSim->x = 1;
|
|
pptlSim->y = 1;
|
|
}
|
|
#endif
|
|
|
|
ULONG uAngle = 0;
|
|
|
|
if( ifio.b90DegreeRotations() )
|
|
{
|
|
|
|
// If the WorldToDeive transform is not identity,
|
|
// We have to consider WToD Xform for font orientation
|
|
// This is only for Advanced Mode
|
|
|
|
if(!(pdco->pdc->bWorldToDeviceIdentity()) )
|
|
{
|
|
INT s11,s12,s21,s22;
|
|
EXFORMOBJ xo(*pdco,WORLD_TO_DEVICE);
|
|
|
|
// Get Matrix element
|
|
// lSignum() returns -1, if the element is minus value, otherwise 1
|
|
|
|
s11 = (INT) xo.efM11().lSignum();
|
|
s12 = (INT) xo.efM12().lSignum();
|
|
s21 = (INT) xo.efM21().lSignum();
|
|
s22 = (INT) xo.efM22().lSignum();
|
|
|
|
// Check mapping mode
|
|
|
|
if (pdco->pdc->bYisUp())
|
|
{
|
|
s21 = -s21;
|
|
s22 = -s22;
|
|
uAngle = 3600 - lNormAngle( pelfw->lfOrientation );
|
|
}
|
|
else
|
|
{
|
|
uAngle = lNormAngle( pelfw->lfOrientation );
|
|
}
|
|
|
|
// Compute font orientation on distination device
|
|
//
|
|
// This logic depend on that -1 is represented as All bits are ON.
|
|
|
|
uAngle = (ULONG)( lNormAngle
|
|
(
|
|
uAngle
|
|
+ (s12 & 900)
|
|
+ (s11 & 1800)
|
|
+ (s21 & 2700)
|
|
) / ORIENTATION_90_DEG
|
|
);
|
|
}
|
|
else
|
|
{
|
|
uAngle = (ULONG)(lNormAngle(pelfw->lfOrientation) /
|
|
ORIENTATION_90_DEG );
|
|
}
|
|
}
|
|
|
|
switch( uAngle )
|
|
{
|
|
case 0: // 0 Degrees
|
|
SET_FLOAT_WITH_LONG(pfdx->eXX,galFloat[pptlSim->x]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eXY,galFloat[0 ]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eYX,galFloat[0 ]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eYY,galFloatNeg[pptlSim->y]);
|
|
break;
|
|
case 1: // 90 Degrees
|
|
SET_FLOAT_WITH_LONG(pfdx->eYX,galFloatNeg[pptlSim->x]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eXX,galFloat[0 ]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eYY,galFloat[0 ]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eXY,galFloatNeg[pptlSim->y]);
|
|
break;
|
|
case 2: // 180 Degrees
|
|
SET_FLOAT_WITH_LONG(pfdx->eXX,galFloatNeg[pptlSim->x]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eXY,galFloat[0 ]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eYX,galFloat[0 ]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eYY,galFloat[pptlSim->y]);
|
|
break;
|
|
case 3: // 270 Degress
|
|
SET_FLOAT_WITH_LONG(pfdx->eXY,galFloat[pptlSim->y]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eXX,galFloat[0 ]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eYY,galFloat[0 ]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eYX,galFloat[pptlSim->x]);
|
|
break;
|
|
default:
|
|
WARNING("bGetNtoD():Invalid Angle\n");
|
|
break;
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
vGetNtoW(&mxNW, pelfw, ifio, pdco);
|
|
|
|
EXFORMOBJ xoND(&mxND, DONT_COMPUTE_FLAGS);
|
|
|
|
if ( pdco->pdc->bWorldToDeviceIdentity() == FALSE)
|
|
{
|
|
if (!xoND.bMultiply(&mxNW,&pdco->pdc->mxWorldToDevice()))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Compensate for the fact that for the font driver, one
|
|
// device unit corresponds to the distance between pixels,
|
|
// whereas for the engine, one device unit corresponds to
|
|
// 1/16'th the way between pixels
|
|
//
|
|
mxND.efM11.vDivBy16();
|
|
mxND.efM12.vDivBy16();
|
|
mxND.efM21.vDivBy16();
|
|
mxND.efM22.vDivBy16();
|
|
}
|
|
else
|
|
{
|
|
mxND = mxNW;
|
|
}
|
|
|
|
SET_FLOAT_WITH_LONG(pfdx->eXX,mxND.efM11.lEfToF());
|
|
SET_FLOAT_WITH_LONG(pfdx->eXY,mxND.efM12.lEfToF());
|
|
SET_FLOAT_WITH_LONG(pfdx->eYX,mxND.efM21.lEfToF());
|
|
SET_FLOAT_WITH_LONG(pfdx->eYY,mxND.efM22.lEfToF());
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* bGetNtoW_Win31
|
|
*
|
|
* Computes notional to world transform for the compatible
|
|
* mode Basically, computes notional to device transform in
|
|
* win31 style using page to device transform (ignoring
|
|
* possibly exhistent world to page transform. then page to
|
|
* device is factored out leaving us with win31 style crippled
|
|
* notional to world transform. As to the page to device
|
|
* transform, either the one in the dc is used, or if this
|
|
* routine has a metafile client, then page to device
|
|
* transform of the recording device is used. Metafile code
|
|
* stored this transform in the dc.
|
|
*
|
|
* Called by:
|
|
* bGetNtoD_Win31 [FONTMAP.CXX]
|
|
*
|
|
* History:
|
|
* 24-Nov-1992 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
|
|
|
|
BOOL
|
|
bGetNtoW_Win31(
|
|
MATRIX *pmxNW, // store the result here
|
|
LOGFONTW *pelfw, // points to the extended logical font defining
|
|
// the font that is requested by the application.
|
|
// Units are ususally in World coordinates.
|
|
|
|
IFIOBJ& ifio, // font to be used
|
|
|
|
DCOBJ *pdco, // the device context defines the transforms between
|
|
// the various coordinate spaces.
|
|
|
|
FLONG fl, // The flags supported are:
|
|
//
|
|
// ND_IGNORE_ESC_AND_ORIENT
|
|
//
|
|
// The presence of this flag indicates that
|
|
// the escapement and orientation values
|
|
// of the LOGFONT should be ignored. This
|
|
// is used for GetGlyphOutline which ignores
|
|
// these values on Win 3.1. Corel Draw 5.0
|
|
// relies on this behavior to print rotated
|
|
// text.
|
|
//
|
|
BOOL bIsLinkedFont // is passed in as TRUE if the font is linked, FALSE otherwise
|
|
)
|
|
{
|
|
|
|
ASSERTGDI(
|
|
(fl & ~(ND_IGNORE_ESC_AND_ORIENT | ND_IGNORE_MAP_MODE)) == 0,
|
|
"gdisrv!NtoW_Win31 -- bad value for fl\n"
|
|
);
|
|
|
|
LONG lfHeight;
|
|
|
|
|
|
EFLOAT efHeightScale,
|
|
efHeightNum,
|
|
efHeightDen,
|
|
efWidthScale,
|
|
efWidthDen,
|
|
efDefaultScale;
|
|
|
|
if (ifio.lfWidth() == 0)
|
|
{
|
|
WARNING("gdisrv!bGetNtoW_Win31, AvgChW\n");
|
|
}
|
|
|
|
BOOL bUseMeta = pdco->pdc->bUseMetaPtoD();
|
|
|
|
BOOL bDoXform = (!(fl & ND_IGNORE_MAP_MODE) &&
|
|
(bUseMeta || !pdco->pdc->bPageToDeviceScaleIdentity()));
|
|
|
|
BOOL bPD11Is1 = TRUE; // efPD11 == 1
|
|
BOOL bPD22IsNeg = FALSE; // efPD22 is negative
|
|
|
|
EFLOATEXT efPD11;
|
|
|
|
if ((lfHeight = pelfw->lfHeight) == 0)
|
|
{
|
|
lfHeight = lGetDefaultWorldHeight(pdco);
|
|
}
|
|
|
|
ASSERTGDI(lfHeight,"gdisrv!vGetNtoW -- zero lfHeight\n");
|
|
|
|
|
|
// dchinn 9/16/98:
|
|
// A fix to the Visual FoxPro 5.0 hcw.exe bug. The bug is that the
|
|
// dialog boxes in hcw.exe are designed with 8pt MS Shell Dlg
|
|
// (at 96dpi, that's 11ppem), but the text in the dialog appears
|
|
// as 12ppem in NT 5. A possible contributing reason for this bug
|
|
// is that the default shell dialog font in NT 4 is MS Sans Serif, which
|
|
// is a bitmap font with only sizes 8, 10, 12, 14, 18, 24. The default
|
|
// shell dialog font for NT 5 is Microsoft Sans Serif, which is an OpenType
|
|
// (TrueType) font. Perhaps FoxPro somehow hardcodes 12ppem somewhere.
|
|
// The fix here is that if the logfont is for the MS Shell Dlg at 12ppem
|
|
// then we actually use an lfHeight of 11ppem.
|
|
//
|
|
// We only adjust for negative lfHeight because when lfHeight is negative,
|
|
// the logfont is requesting an em height (as opposed to ascender plus
|
|
// descender if lfHeight is positive).
|
|
//
|
|
// Well, change of heart, Lotus notes is asking for lfHeight == +15,
|
|
// expecting to get the same size font as ms sans serif at lfHeight = -11;
|
|
// so we have to adjust for positive lfHeights as well [bodind]
|
|
//
|
|
// Finally, this table of conversions below handles the case when
|
|
// small fonts is set on the system (not large fonts)
|
|
// (actually, it handles the lowest size for large fonts
|
|
// and two smallest sizes for small fonts [bodind])
|
|
|
|
|
|
if (gbShellFontCompatible &&
|
|
!_wcsicmp(pelfw->lfFaceName, L"MS Shell Dlg") &&
|
|
!bIsLinkedFont) // don't do font size collapsing if dealing with a linked font
|
|
{
|
|
if (lfHeight > 0)
|
|
{
|
|
// sizes 12 and 13 are mapped to 14 because in bitmap font there is
|
|
// no size smaller than 14. But we do not want to map everything from
|
|
// 1 to 15 to 14 for tt, we only want to bump up as few sizes as needed to
|
|
// get the backwards compat with nt 40 in the shell.
|
|
|
|
if ((lfHeight >= 12) && (lfHeight <= 15))
|
|
{
|
|
lfHeight = 14; // same as -11 for ms sans serif
|
|
}
|
|
else if ((lfHeight > 15) && (lfHeight <= 19))
|
|
{
|
|
lfHeight = 16; // same as -13 for ms sans serif
|
|
}
|
|
}
|
|
else // lfHeight < 0
|
|
{
|
|
// sizes -9 and -10 are mapped to -11 because in bitmap font there is
|
|
// no size smaller than -11. But we do not want to map everything from
|
|
// -11 to -15 to 14 for tt, we only want to bump up as few sizes as needed to
|
|
// get the backwards compat with nt 40 in the shell.
|
|
|
|
if ((lfHeight >= -12) && (lfHeight <= -9))
|
|
{
|
|
lfHeight = -11; // fixes older version of outlook and janna contact dialogs
|
|
}
|
|
else if ((lfHeight > -16) && (lfHeight <= -13))
|
|
{
|
|
lfHeight = -13; // just in case
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
if (gbShellFontCompatible && !_wcsicmp(pelfw->lfFaceName, L"MS Shell Dlg") && ((lfHeight == -12) || (lfHeight == -14)
|
|
|| (lfHeight == -15) || (lfHeight == -17) || (lfHeight == -18) || (lfHeight > -11)
|
|
|| ((lfHeight > -24) && (lfHeight < -19))
|
|
|| ((lfHeight > -32) && (lfHeight < -24)) || (lfHeight < -32)
|
|
))
|
|
{
|
|
DbgPrint("\tNTFONT: MS Shell Dlg used at size %d ppem\n, dialog may be clipped",-lfHeight);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (lfHeight > 0)
|
|
{
|
|
efHeightNum = (LONG)lfHeight;
|
|
efHeightDen = (LONG)ifio.lfHeight();
|
|
}
|
|
else // lfHeight < 0
|
|
{
|
|
efHeightNum = (LONG)(-lfHeight);
|
|
efHeightDen = (LONG) ifio.fwdUnitsPerEm();
|
|
}
|
|
|
|
efDefaultScale.eqDiv(efHeightNum,efHeightDen);
|
|
|
|
pmxNW->efM22 = efDefaultScale;
|
|
efHeightScale = efDefaultScale;
|
|
|
|
if (bDoXform)
|
|
{
|
|
EFLOATEXT efPD22;
|
|
|
|
// first check if hock wants us to use his page to device scale factors
|
|
|
|
if (bUseMeta)
|
|
{
|
|
efPD11 = pdco->pdc->efMetaPtoD11();
|
|
efPD22 = pdco->pdc->efMetaPtoD22();
|
|
}
|
|
else if (!pdco->pdc->bPageToDeviceScaleIdentity())
|
|
{
|
|
if (!pdco->pdc->bWorldToPageIdentity())
|
|
{
|
|
// need to compute page to device scaling coefficients
|
|
// that will be used in computing crippled win31 style
|
|
// notional to world scaling coefficients
|
|
// This is because PtoD is not stored on the server side
|
|
// any more. This somewhat slow code path is infrequent
|
|
// and not perf critical
|
|
|
|
EFLOATEXT efTmp;
|
|
|
|
efPD11 = pdco->pdc->lViewportExtCx();
|
|
efTmp = pdco->pdc->lWindowExtCx();
|
|
efPD11.eqDiv(efPD11,efTmp);
|
|
|
|
efPD22 = pdco->pdc->lViewportExtCy();
|
|
efTmp = pdco->pdc->lWindowExtCy();
|
|
efPD22.eqDiv(efPD22,efTmp);
|
|
}
|
|
else // page to device == world to device:
|
|
{
|
|
efPD11 = pdco->pdc->efM11();
|
|
efPD22 = pdco->pdc->efM22();
|
|
|
|
// Compensate for the fact that for the font driver, one
|
|
// device unit corresponds to the distance between pixels,
|
|
// whereas for the engine, one device unit corresponds to
|
|
// 1/16'th the way between pixels
|
|
|
|
efPD11.vDivBy16();
|
|
efPD22.vDivBy16();
|
|
|
|
ASSERTGDI(pdco->pdc->efM12().bIsZero(), "GDISRV: nonzero m12 IN WIN31 MODE\n");
|
|
ASSERTGDI(pdco->pdc->efM21().bIsZero(), "GDISRV: nonzero m21 IN WIN31 MODE\n");
|
|
}
|
|
|
|
}
|
|
#if DBG
|
|
else
|
|
RIP("gdisrv!ntow_win31\n");
|
|
#endif
|
|
|
|
bPD11Is1 = efPD11.bIs1();
|
|
bPD22IsNeg = efPD22.bIsNegative();
|
|
|
|
if (!efPD22.bIs1())
|
|
efHeightScale.eqMul(efHeightScale,efPD22);
|
|
|
|
// In win31 possible y flip or x flip on the text are not respected
|
|
// so that signs do not make it into the xform
|
|
|
|
efHeightScale.vAbs();
|
|
}
|
|
|
|
if (bPD22IsNeg)
|
|
{
|
|
// change the sign if necessary so that
|
|
// pmxNW->efM22 * efPtoD22 == efHeightScale, which is enforced to be > 0
|
|
|
|
pmxNW->efM22.vNegate();
|
|
}
|
|
|
|
|
|
PDEVOBJ pdo(pdco->hdev());
|
|
if (!pdo.bValid())
|
|
{
|
|
RIP("gdisrv!bGetNtoW_Win31, pdevobj problem\n");
|
|
return FALSE;
|
|
}
|
|
|
|
// In the case that lfWidth is zero or in the MSBADWIDTH case we will need
|
|
// to adjust efWidthScale if VerRes != HorRez
|
|
|
|
BOOL bMustCheckResolution = TRUE;
|
|
|
|
if (pelfw->lfWidth)
|
|
{
|
|
// This makes no sense, but has to be here for win31 compatibility.
|
|
// Win31 is computing the number of
|
|
// pixels in x direction of the avgchar width scaled along y.
|
|
// I find this a little bizzare [bodind]
|
|
|
|
EFLOAT efAveChPixelWidth;
|
|
efAveChPixelWidth = (LONG) ifio.fwdAveCharWidth();
|
|
|
|
// take the resolution into account,
|
|
|
|
#if 0
|
|
|
|
if ((pdo.ulLogPixelsX() != pdo.ulLogPixelsY()) && !bUseMeta)
|
|
{
|
|
EFLOAT efTmp;
|
|
efTmp = (LONG)pdo.ulLogPixelsY();
|
|
efAveChPixelWidth.eqMul(efAveChPixelWidth,efTmp);
|
|
efTmp = (LONG)pdo.ulLogPixelsX();
|
|
efAveChPixelWidth.eqDiv(efAveChPixelWidth,efTmp);
|
|
}
|
|
|
|
#endif
|
|
|
|
efWidthDen = efAveChPixelWidth; // save the result for later
|
|
|
|
efAveChPixelWidth.eqMul(efAveChPixelWidth,efHeightScale);
|
|
|
|
LONG lAvChPixelW, lReqPixelWidth;
|
|
|
|
// requested width in pixels:
|
|
|
|
EFLOAT efReqPixelWidth;
|
|
lReqPixelWidth = (LONG)ABS(pelfw->lfWidth);
|
|
efReqPixelWidth = lReqPixelWidth;
|
|
|
|
BOOL bOk = TRUE;
|
|
|
|
if (bDoXform)
|
|
{
|
|
if (!bPD11Is1)
|
|
{
|
|
efReqPixelWidth.eqMul(efReqPixelWidth,efPD11);
|
|
bOk = efReqPixelWidth.bEfToL(lReqPixelWidth);
|
|
}
|
|
efReqPixelWidth.vAbs();
|
|
if (lReqPixelWidth < 0)
|
|
lReqPixelWidth = -lReqPixelWidth;
|
|
}
|
|
|
|
// win 31 does not allow tt fonts of zero width. This makes sense,
|
|
// as we know rasterizer chokes on these.
|
|
// Win31 does not allow fonts that are very wide either.
|
|
// The code below is exactly what win31 is doing. Win31 has a bogus
|
|
// criterion for determining a cut off for width.
|
|
// Below this cut off, because of the bug in win31 code,
|
|
// the text goes from right to left.
|
|
// For even smaller lfWidth
|
|
// we get the expected "good" behavior. NT eliminates the Win31 bug
|
|
// where for range of lfWidhts width scaling factor is negative.
|
|
|
|
if
|
|
(
|
|
(
|
|
efAveChPixelWidth.bEfToL(lAvChPixelW) &&
|
|
(lAvChPixelW > 0) && // not too narrow !
|
|
bOk &&
|
|
((lReqPixelWidth / 256) < lAvChPixelW) // bogus win31 criterion
|
|
)
|
|
||
|
|
ifio.bStroke() // vector fonts can be arbitrarily wide or narrow
|
|
)
|
|
{
|
|
bMustCheckResolution = FALSE;
|
|
efWidthScale.eqDiv(efReqPixelWidth,efWidthDen);
|
|
}
|
|
/*
|
|
else
|
|
{
|
|
// win31 in either of these cases branches into MSFBadWidth case
|
|
// which is equivalent to setting lfWidth == 0 [bodind]
|
|
}
|
|
*/
|
|
}
|
|
|
|
if (bMustCheckResolution)
|
|
{
|
|
// must compute width scale because it has not been
|
|
// computed in lfWidth != 0 case
|
|
|
|
if (ifio.bStroke())
|
|
{
|
|
// win31 behaves differently for vector fonts:
|
|
// unlike tt fonts, vector fonts stretch along x, respecting
|
|
// page to device xform. However, they ignore the request to flip
|
|
// either x or y axis
|
|
|
|
efWidthScale = efDefaultScale;
|
|
if (!bPD11Is1)
|
|
{
|
|
efWidthScale.eqMul(efWidthScale,efPD11);
|
|
efWidthScale.vAbs();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// tt fonts make x scaling the same as y scaling,
|
|
|
|
efWidthScale = efHeightScale;
|
|
}
|
|
|
|
POINTL ptlRes = *ifio.pptlAspect();
|
|
|
|
// If VertRez != HorRez and we are using the default width we need to
|
|
// adjust for the differences in resolution.
|
|
// This is done in order to ensure that fonts look the same on printers
|
|
// of different resolutions [bodind]
|
|
|
|
if ((pdo.ulLogPixelsX() != pdo.ulLogPixelsY()) && !bUseMeta)
|
|
{
|
|
ptlRes.y *= (LONG)pdo.ulLogPixelsX();
|
|
ptlRes.x *= (LONG)pdo.ulLogPixelsY();
|
|
}
|
|
|
|
if (ptlRes.x != ptlRes.y)
|
|
{
|
|
EFLOAT efTmp;
|
|
efTmp = ptlRes.y;
|
|
efWidthScale *= efTmp ;
|
|
efTmp = ptlRes.x;
|
|
efWidthScale /= efTmp;
|
|
}
|
|
|
|
}
|
|
|
|
// now that we have width scale we can compute pmxNW->efM11. We factor out
|
|
// (PtoD)11 out of width scale to obtain the effective NW x scale:
|
|
|
|
if (!bPD11Is1)
|
|
pmxNW->efM11.eqDiv(efWidthScale,efPD11);
|
|
else
|
|
pmxNW->efM11 = efWidthScale;
|
|
|
|
pmxNW->efDx.vSetToZero();
|
|
pmxNW->efDy.vSetToZero();
|
|
pmxNW->efM12.vSetToZero();
|
|
pmxNW->efM21.vSetToZero();
|
|
|
|
EXFORMOBJ xoNW(pmxNW, DONT_COMPUTE_FLAGS);
|
|
|
|
// see if orientation angle has to be taken into account:
|
|
|
|
if (ifio.bStroke())
|
|
{
|
|
// allow esc != orientation for vector fonts because win31 does it
|
|
// also note that for vector fonts Orientation is treated as world space
|
|
// concept, so we multiply here before applying world to device transform
|
|
// while for tt fonts esc is treated as device space concept so that
|
|
// this multiplication is occuring after world to page transform is applied
|
|
|
|
if (pelfw->lfOrientation)
|
|
{
|
|
EFLOATEXT efAngle = pelfw->lfOrientation;
|
|
efAngle /= (LONG) 10;
|
|
|
|
MATRIX mxRot, mxTmp;
|
|
|
|
mxRot.efM11 = efCos(efAngle);
|
|
mxRot.efM22 = mxRot.efM11;
|
|
mxRot.efM12 = efSin(efAngle);
|
|
mxRot.efM21 = mxRot.efM12;
|
|
mxRot.efM21.vNegate();
|
|
mxRot.efDx.vSetToZero();
|
|
mxRot.efDy.vSetToZero();
|
|
|
|
mxTmp = *pmxNW;
|
|
|
|
if (!xoNW.bMultiply(&mxTmp,&mxRot))
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
// take into account different orientation of y axes of notional
|
|
// and world spaces:
|
|
|
|
pmxNW->efM12.vNegate();
|
|
pmxNW->efM22.vNegate();
|
|
|
|
xoNW.vComputeAccelFlags();
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* BOOL bParityViolatingXform(DCOBJ *pdco)
|
|
*
|
|
* History:
|
|
* 04-Jun-1993 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL bParityViolatingXform(DCOBJ *pdco)
|
|
{
|
|
|
|
if (pdco->pdc->bWorldToPageIdentity())
|
|
{
|
|
if (pdco->pdc->bPageToDeviceScaleIdentity())
|
|
{
|
|
// identity except maybe for translations
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
return (pdco->pdc->efM11().lSignum() != pdco->pdc->efM22().lSignum());
|
|
}
|
|
else
|
|
{
|
|
// we are in the metafile code
|
|
|
|
return( pdco->pdc->efMetaPtoD11().lSignum() != pdco->pdc->efMetaPtoD22().lSignum() );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* bGetNtoD_Win31
|
|
*
|
|
* Called by:
|
|
* PFEOBJ::bSetFontXform [PFEOBJ.CXX]
|
|
*
|
|
* History:
|
|
* Tue 12-Jan-1993 11:58:41 by Kirk Olynyk [kirko]
|
|
* Added a quick code path for non-transformable (bitmap) fonts.
|
|
* 30-Sep-1992 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
bGetNtoD_Win31(
|
|
FD_XFORM *pfdx, // pointer to the buffer to recieve the
|
|
// notional to device transformation for the
|
|
// font driver. There are a couple of
|
|
// important things to remember. First,
|
|
// according to the conventions of the ISO
|
|
// committee, the coordinate space for notional
|
|
// (font designer) spaces are cartesian.
|
|
// However, due to a series of errors on my part
|
|
// [kirko] the convention that is used by the
|
|
// DDI is that the notional to device transformation
|
|
// passed over the DDI assumes that both the notional
|
|
// and the device space are anti-Cartesian, that is,
|
|
// positive y increases in the downward direction.
|
|
// The fontdriver assumes that
|
|
// one unit in device space corresponds to the
|
|
// distance between pixels. This is different from
|
|
// GDI's internal view, where one device unit
|
|
// corresponds to a sub-pixel unit.
|
|
|
|
LOGFONTW *pelfw, // points to the extended logical font defining
|
|
// the font that is requested by the application.
|
|
// Units are ususally in World coordinates.
|
|
|
|
IFIOBJ& ifio, // font to be used
|
|
|
|
DCOBJ *pdco, // the device context defines the transforms between
|
|
// the various coordinate spaces.
|
|
|
|
FLONG fl, // The flags supported are:
|
|
//
|
|
// ND_IGNORE_ESC_AND_ORIENT
|
|
//
|
|
// The presence of this flag indicates that
|
|
// the escapement and orientation values
|
|
// of the LOGFONT should be ignored. This
|
|
// is used for GetGlyphOutline which ignores
|
|
// these values on Win 3.1. Corel Draw 5.0
|
|
// relies on this behavior to print rotated
|
|
// text.
|
|
//
|
|
POINTL * const pptlSim,
|
|
BOOL bIsLinkedFont // is passed in as TRUE if the font is linked, FALSE otherwise
|
|
)
|
|
{
|
|
MATRIX mxNW, mxND;
|
|
ASSERTGDI(
|
|
(fl & ~(ND_IGNORE_ESC_AND_ORIENT | ND_IGNORE_MAP_MODE))== 0,
|
|
"gdisrv!bGetNtoD_Win31 -- bad value for fl\n"
|
|
);
|
|
|
|
if((pptlSim->x) && !ifio.bContinuousScaling())
|
|
{
|
|
//
|
|
// This code path is for bitmap / non-scalable fonts. The notional
|
|
// to device transformation is determined by simply looking up
|
|
// the scaling factors for both the x-direction and y-direcion
|
|
//
|
|
|
|
#if DBG
|
|
if (!(0 < pptlSim->x && pptlSim->x <= sizeof(galFloat)/sizeof(LONG)))
|
|
{
|
|
DbgPrint("\t*pptlSim = (%d,%d)\n",pptlSim->x,pptlSim->y);
|
|
RIP("gre -- bad *pptlSim\n");
|
|
}
|
|
#endif
|
|
|
|
|
|
// Win3.1J ignore orientation anytime. But use escapement for rotate Glyph data.
|
|
|
|
// If the font driver that this font provide , has not arbitality flag.
|
|
// Angle should be 0 , 900 , 1800 or 2700
|
|
// for Win31J compatibility
|
|
|
|
ULONG uAngle = 0;
|
|
|
|
if (gbDBCSCodePage)
|
|
{
|
|
if( ifio.b90DegreeRotations() )
|
|
{
|
|
if (pdco->pdc->bYisUp())
|
|
uAngle = (ULONG)(((3600-lNormAngle(pelfw->lfEscapement)) /
|
|
ORIENTATION_90_DEG) % 4);
|
|
else
|
|
uAngle = (ULONG)( lNormAngle(pelfw->lfEscapement) /
|
|
ORIENTATION_90_DEG );
|
|
}
|
|
}
|
|
|
|
switch( uAngle )
|
|
{
|
|
case 0: // 0 Degrees
|
|
SET_FLOAT_WITH_LONG(pfdx->eXX,galFloat[pptlSim->x]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eXY,galFloat[0 ]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eYX,galFloat[0 ]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eYY,galFloatNeg[pptlSim->y]);
|
|
break;
|
|
case 1: // 90 Degrees
|
|
SET_FLOAT_WITH_LONG(pfdx->eYX,galFloatNeg[pptlSim->x]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eXX,galFloat[0 ]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eYY,galFloat[0 ]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eXY,galFloatNeg[pptlSim->y]);
|
|
break;
|
|
case 2: // 180 Degrees
|
|
SET_FLOAT_WITH_LONG(pfdx->eXX,galFloatNeg[pptlSim->x]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eXY,galFloat[0 ]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eYX,galFloat[0 ]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eYY,galFloat[pptlSim->y]);
|
|
break;
|
|
case 3: // 270 Degress
|
|
SET_FLOAT_WITH_LONG(pfdx->eXY,galFloat[pptlSim->y]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eXX,galFloat[0 ]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eYY,galFloat[0 ]);
|
|
SET_FLOAT_WITH_LONG(pfdx->eYX,galFloat[pptlSim->x]);
|
|
break;
|
|
default:
|
|
WARNING("bGetNtoD_Win31():Invalid Angle\n");
|
|
break;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
if (!bGetNtoW_Win31(&mxNW, pelfw, ifio, pdco, fl, bIsLinkedFont))
|
|
return FALSE;
|
|
|
|
EXFORMOBJ xoND(&mxND, DONT_COMPUTE_FLAGS);
|
|
|
|
if( (pdco->pdc->bWorldToDeviceIdentity() == FALSE) &&
|
|
!(fl & ND_IGNORE_MAP_MODE) )
|
|
{
|
|
if (!xoND.bMultiply(&mxNW,&pdco->pdc->mxWorldToDevice()))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Compensate for the fact that for the font driver, one
|
|
// device unit corresponds to the distance between pixels,
|
|
// whereas for the engine, one device unit corresponds to
|
|
// 1/16'th the way between pixels
|
|
//
|
|
mxND.efM11.vDivBy16();
|
|
mxND.efM12.vDivBy16();
|
|
mxND.efM21.vDivBy16();
|
|
mxND.efM22.vDivBy16();
|
|
}
|
|
else
|
|
{
|
|
mxND = mxNW;
|
|
}
|
|
|
|
if (!ifio.bStroke())
|
|
{
|
|
// for tt fonts escapement and orientation are treated as
|
|
// device space concepts. That is why for these fonts we apply
|
|
// rotation by lAngle last
|
|
|
|
LONG lAngle;
|
|
|
|
|
|
if( ifio.b90DegreeRotations() )
|
|
{
|
|
lAngle = (LONG)( ( lNormAngle(pelfw->lfEscapement)
|
|
/ ORIENTATION_90_DEG ) % 4 ) * ORIENTATION_90_DEG;
|
|
}
|
|
else // ifio.bArbXform() is TRUE
|
|
{
|
|
lAngle = pelfw->lfEscapement;
|
|
}
|
|
|
|
if(lAngle != 0 && (!(fl & ND_IGNORE_ESC_AND_ORIENT) || gbDBCSCodePage))
|
|
{
|
|
// more of win31 compatability: the line below would make sense
|
|
// if this was y -> -y type of xform. But they also do it
|
|
// for x -> -x xform. [bodind]
|
|
|
|
if (bParityViolatingXform(pdco))
|
|
{
|
|
lAngle = -lAngle;
|
|
}
|
|
|
|
EFLOATEXT efAngle = lAngle;
|
|
efAngle /= (LONG) 10;
|
|
|
|
MATRIX mxRot, mxTmp;
|
|
|
|
mxRot.efM11 = efCos(efAngle);
|
|
mxRot.efM22 = mxRot.efM11;
|
|
mxRot.efM12 = efSin(efAngle);
|
|
mxRot.efM21 = mxRot.efM12;
|
|
mxRot.efM12.vNegate();
|
|
mxRot.efDx.vSetToZero();
|
|
mxRot.efDy.vSetToZero();
|
|
|
|
mxTmp = mxND;
|
|
|
|
if (!xoND.bMultiply(&mxTmp,&mxRot))
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
// adjust for nonsquare resolution
|
|
|
|
PDEVOBJ pdo(pdco->hdev());
|
|
if (pdo.ulLogPixelsX() != pdo.ulLogPixelsY())
|
|
{
|
|
EFLOATEXT efTmp = (LONG)pdo.ulLogPixelsX();
|
|
efTmp /= (LONG)pdo.ulLogPixelsY();
|
|
MATRIX mxW2D = pdco->pdc->mxWorldToDevice();
|
|
|
|
if(mxW2D.efM12.bIsZero() && mxW2D.efM21.bIsZero()){// for 1,4 -up printing
|
|
mxND.efM12 /= efTmp;
|
|
mxND.efM21 *= efTmp;
|
|
}
|
|
else{ // for 2, 6-up printing, i.e. 270 rotation
|
|
mxND.efM11 *= efTmp;
|
|
mxND.efM22 /= efTmp;
|
|
}
|
|
}
|
|
}
|
|
|
|
SET_FLOAT_WITH_LONG(pfdx->eXX,mxND.efM11.lEfToF());
|
|
SET_FLOAT_WITH_LONG(pfdx->eXY,mxND.efM12.lEfToF());
|
|
SET_FLOAT_WITH_LONG(pfdx->eYX,mxND.efM21.lEfToF());
|
|
SET_FLOAT_WITH_LONG(pfdx->eYY,mxND.efM22.lEfToF());
|
|
|
|
return(TRUE);
|
|
}
|