Leaked source code of windows server 2003
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.
 
 
 
 
 
 

4694 lines
129 KiB

/******************************Module*Header*******************************\
* Module Name: metarec.cxx
*
* Metafile recording functions.
*
* Created: 12-June-1991 13:46:00
* Author: Hock San Lee [hockl]
*
* Copyright (c) 1991-1999 Microsoft Corporation
\**************************************************************************/
#define NO_STRICT
extern "C" {
#if defined(_GDIPLUS_)
#include <gpprefix.h>
#endif
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <stddef.h>
#include <windows.h> // GDI function declarations.
#include <winerror.h>
#include "firewall.h"
#define __CPLUSPLUS
#include <winspool.h>
#include <w32gdip.h>
#include "ntgdistr.h"
#include "winddi.h"
#include "icm.h"
#include "hmgshare.h"
#include "local.h" // Local object support.
#include "gdiicm.h"
#include "font.h"
#include "metadef.h" // Metafile record type constants.
#include "metarec.h" // Metafile recording functions.
#include "mf16.h"
#include "nlsconv.h"
#include "ntgdi.h"
#include "xfflags.h"
#include "..\inc\mapfile.h"
}
#include "rectl.hxx"
#include "mfdc.hxx" // Metafile DC class declarations.
#include "mfrec.hxx" // Metafile record class declarations.
extern "C" {
#include "mfrec16.h" // 3.x Metafile recording functions
}
extern "C" BOOL bDoFontChange(HDC hdc, WCHAR *pwsz, int c, UINT fl);
extern "C" BOOL bRecordEmbedFonts(HDC hdc);
XFORM xformIdentity = { 1.00000000f, 0.00000000f, 0.00000000f, 1.00000000f,
0.00000000f, 0.00000000f };
#ifdef LANGPACK
extern LONG gdwDisableMetafileRec ;
#endif
// SaveDC
// BeginPath
// EndPath
// CloseFigure
// FlattenPath
// WidenPath
// AbortPath
// SetMetaRgn
// RealizePalette
extern "C" BOOL MF_Record(HDC hdc,DWORD mrType)
{
PMR pmr;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_Record\n");
if (!(pmr = (PMR) pmdc->pvNewRecord(SIZEOF_MR)))
return(FALSE);
pmr->vInit(mrType);
pmr->vCommit(pmdc);
return(TRUE);
}
// FillPath
// StrokeAndFillPath
// StrokePath
extern "C" BOOL MF_BoundRecord(HDC hdc,DWORD mrType)
{
PMRB pmrb;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_BoundRecord\n");
if (!(pmrb = (PMRB) pmdc->pvNewRecord(SIZEOF_MRB)))
return(FALSE);
pmrb->vInit(mrType, pmdc);
pmrb->vCommit(pmdc);
return(TRUE);
}
// SetMapperFlags
// SetMapMode
// SetBkMode
// SetPolyFillMode
// SetROP2
// SetStretchBltMode
// SetTextAlign
// SetTextColor
// SetBkColor
// RestoreDC
// SetArcDirection
// SetMiterLimit
// SelectClipPath
// SetLayout
extern "C" BOOL MF_SetD(HDC hdc,DWORD d1,DWORD mrType)
{
PMRD pmrd;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_SetD\n");
if( ( mrType == EMR_SETMAPMODE ) ||
( mrType == EMR_SETMAPPERFLAGS ) ||
( mrType == EMR_SETLAYOUT ) ||
( mrType == EMR_RESTOREDC ) )
{
pldc->fl |= LDC_FONT_CHANGE;
}
if (!(pmrd = (PMRD) pmdc->pvNewRecord(SIZEOF_MRD)))
return(FALSE);
pmrd->vInit(mrType, d1);
pmrd->vCommit(pmdc);
return(TRUE);
}
// OffsetWindowOrgEx
// OffsetViewportOrgEx
// SetWindowExtEx
// SetWindowOrgEx
// SetViewportExtEx
// SetViewportOrgEx
// SetBrushOrgEx
// OffsetClipRgn
// MoveToEx
// LineTo
// SetTextJustification
extern "C" BOOL MF_SetDD(HDC hdc,DWORD d1,DWORD d2,DWORD mrType)
{
PMRDD pmrdd;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_SetDD\n");
if( ( mrType == EMR_SETVIEWPORTEXTEX ) || ( mrType == EMR_SETWINDOWEXTEX ) )
{
pldc->fl |= LDC_FONT_CHANGE;
}
if (!(pmrdd = (PMRDD) pmdc->pvNewRecord(SIZEOF_MRDD)))
return(FALSE);
pmrdd->vInit(mrType, d1, d2);
pmrdd->vCommit(pmdc);
return(TRUE);
}
// ExcludeClipRect
// IntersectClipRect
// ScaleViewportExtEx
// ScaleWindowExtEx
extern "C" BOOL MF_SetDDDD(HDC hdc,DWORD d1,DWORD d2,DWORD d3,DWORD d4,DWORD mrType)
{
PMRDDDD pmrdddd;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_SetDDDD\n");
if( ( mrType == EMR_SCALEVIEWPORTEXTEX ) || ( mrType == EMR_SCALEWINDOWEXTEX ) )
{
pldc->fl |= LDC_FONT_CHANGE;
}
if (!(pmrdddd = (PMRDDDD) pmdc->pvNewRecord(SIZEOF_MRDDDD)))
return(FALSE);
pmrdddd->vInit(mrType, d1, d2, d3, d4);
pmrdddd->vCommit(pmdc);
return(TRUE);
}
// SetMetaRgn
extern "C" BOOL MF_SetMetaRgn(HDC hdc)
{
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_SetMetaRgn\n");
// Record it first.
if (!MF_Record(hdc,EMR_SETMETARGN))
return(FALSE);
// We have to flush the bounds before we change the clipping region
// because the bounds are clipped to the current clipping region bounds.
pmdc->vFlushBounds();
// Now update the clipping bounds to prepare for the next flush.
pmdc->vSetMetaBounds();
return(TRUE);
}
// SelectClipPath
extern "C" BOOL MF_SelectClipPath(HDC hdc,int iMode)
{
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_SelectClipPath\n");
// Record it first.
if (!MF_SetD(hdc, (DWORD) iMode, EMR_SELECTCLIPPATH))
return(FALSE);
// We have to flush the bounds before we change the clipping region
// because the bounds are clipped to the current clipping region bounds.
pmdc->vFlushBounds();
// Now mark the clipping bounds dirty. The clipping bounds is updated
// when it is needed.
pmdc->vMarkClipBoundsDirty();
return(TRUE);
}
// OffsetClipRgn
extern "C" BOOL MF_OffsetClipRgn(HDC hdc,int x1,int y1)
{
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_OffsetClipRgn\n");
// Record it first.
if (!MF_SetDD(hdc, (DWORD) x1, (DWORD) y1, EMR_OFFSETCLIPRGN))
return(FALSE);
// We have to flush the bounds before we change the clipping region
// because the bounds are clipped to the current clipping region bounds.
pmdc->vFlushBounds();
// Now mark the clipping bounds dirty. The clipping bounds is updated
// when it is needed.
pmdc->vMarkClipBoundsDirty();
return(TRUE);
}
// ExcludeClipRect
// IntersectClipRect
extern "C" BOOL MF_AnyClipRect(HDC hdc,int x1,int y1,int x2,int y2,DWORD mrType)
{
BOOL bRet = FALSE;
HRGN hrgnTmp;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_AnyClipRect\n");
// Record it first.
if (!MF_SetDDDD(hdc, (DWORD) x1, (DWORD) y1, (DWORD) x2, (DWORD) y2, mrType))
return(bRet);
// We have to flush the bounds before we change the clipping region
// because the bounds are clipped to the current clipping region bounds.
pmdc->vFlushBounds();
// Now mark the clipping bounds dirty. The clipping bounds is updated
// when it is needed.
pmdc->vMarkClipBoundsDirty();
// For ExcludeClipRect and InteresectClipRect, this is a little tricky.
// If there is no initial clip region, we have to create a default clipping
// region. Otherwise, GDI will create some random default clipping region
// for us!
// Find out if we have a clip region.
if (!(hrgnTmp = CreateRectRgn(0, 0, 0, 0)))
return(bRet);
switch (GetClipRgn(hdc, hrgnTmp))
{
case -1: // error
ASSERTGDI(FALSE, "GetClipRgn failed");
break;
case 0: // no initial clip region
// We need to select in our default clipping region.
// First, make our default clipping region.
if (!SetRectRgn(hrgnTmp,
(int) (SHORT) MINSHORT,
(int) (SHORT) MINSHORT,
(int) (SHORT) MAXSHORT,
(int) (SHORT) MAXSHORT))
{
ASSERTGDI(FALSE, "SetRectRgn failed");
break;
}
// Now select our default region but don't metafile the call.
{
INT iRet;
iRet = NtGdiExtSelectClipRgn(hdc, hrgnTmp, RGN_COPY);
bRet = (iRet != RGN_ERROR);
}
break;
case 1: // has initial clip region
bRet = TRUE;
break;
}
if (!DeleteObject(hrgnTmp))
{
ASSERTGDI(FALSE, "DeleteObject failed");
}
return(bRet);
}
// Always store the relative level.
extern "C" BOOL MF_RestoreDC(HDC hdc,int iLevel)
{
int cLevel = (int) GetDCDWord(hdc,DDW_SAVEDEPTH,0);
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
// Compute the relative level.
if (iLevel > 0)
{
iLevel = iLevel - cLevel;
}
// Check bad levels.
if ((iLevel >= 0) || (iLevel + cLevel <= 0))
return(FALSE);
if (!MF_SetD(hdc,(DWORD)iLevel,EMR_RESTOREDC))
return(FALSE);
// We have to flush the bounds before we change the clipping region
// because the bounds are clipped to the current clipping region bounds.
pmdc->vFlushBounds();
// Now mark the clipping bounds dirty. The clipping bounds is updated
// when it is needed.
pmdc->vMarkClipBoundsDirty();
pmdc->vMarkMetaBoundsDirty();
return(TRUE);
}
extern "C" BOOL MF_SetViewportExtEx(HDC hdc,int x,int y)
{
return(MF_SetDD(hdc,(DWORD)x,(DWORD)y,EMR_SETVIEWPORTEXTEX));
}
extern "C" BOOL MF_SetViewportOrgEx(HDC hdc,int x,int y)
{
return(MF_SetDD(hdc,(DWORD)x,(DWORD)y,EMR_SETVIEWPORTORGEX));
}
extern "C" BOOL MF_SetWindowExtEx(HDC hdc,int x,int y)
{
return(MF_SetDD(hdc,(DWORD)x,(DWORD)y,EMR_SETWINDOWEXTEX));
}
extern "C" BOOL MF_SetWindowOrgEx(HDC hdc,int x,int y)
{
return(MF_SetDD(hdc,(DWORD)x,(DWORD)y,EMR_SETWINDOWORGEX));
}
// Map it to SetViewportOrgEx record.
extern "C" BOOL MF_OffsetViewportOrgEx(HDC hdc,int x,int y)
{
POINTL ptl;
if (!GetViewportOrgEx(hdc, (LPPOINT) &ptl))
return(FALSE);
return
(
MF_SetDD
(
hdc,
(DWORD)(ptl.x + (LONG) x),
(DWORD)(ptl.y + (LONG) y),
EMR_SETVIEWPORTORGEX
)
);
}
// Map it to SetWindowOrgEx record.
extern "C" BOOL MF_OffsetWindowOrgEx(HDC hdc,int x,int y)
{
POINTL ptl;
if (!GetWindowOrgEx(hdc, (LPPOINT) &ptl))
return(FALSE);
return
(
MF_SetDD
(
hdc,
(DWORD) (ptl.x + (LONG) x),
(DWORD) (ptl.y + (LONG) y),
EMR_SETWINDOWORGEX
)
);
}
extern "C" BOOL MF_SetBrushOrgEx(HDC hdc,int x,int y)
{
return(MF_SetDD(hdc,(DWORD)x,(DWORD)y,EMR_SETBRUSHORGEX));
}
// PolyBezier
// Polygon
// Polyline
// PolyBezierTo
// PolylineTo
extern "C" BOOL MF_Poly(HDC hdc, CONST POINT *pptl,DWORD cptl,DWORD mrType)
{
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_Poly\n");
// Check input assumptions.
ASSERTGDI
(
mrType == EMR_POLYBEZIER
|| mrType == EMR_POLYGON
|| mrType == EMR_POLYLINE
|| mrType == EMR_POLYBEZIERTO
|| mrType == EMR_POLYLINETO,
"MF_Poly: Bad record type"
);
ASSERTGDI
(
EMR_POLYGON - EMR_POLYBEZIER == EMR_POLYGON16 - EMR_POLYBEZIER16
&& EMR_POLYLINE - EMR_POLYBEZIER == EMR_POLYLINE16 - EMR_POLYBEZIER16
&& EMR_POLYBEZIERTO - EMR_POLYBEZIER == EMR_POLYBEZIERTO16 - EMR_POLYBEZIER16
&& EMR_POLYLINETO - EMR_POLYBEZIER == EMR_POLYLINETO16 - EMR_POLYBEZIER16,
"MF_Poly: Bad record type"
);
// Store 16-bit record if possible.
if (bIsPoly16((PPOINTL) pptl, cptl))
{
PMRBP16 pmrbp16;
if (!(pmrbp16 = (PMRBP16) pmdc->pvNewRecord(SIZEOF_MRBP16(cptl))))
return(FALSE);
pmrbp16->vInit
(
mrType - EMR_POLYBEZIER + EMR_POLYBEZIER16,
cptl,
(PPOINTL) pptl,
pmdc
);
pmrbp16->vCommit(pmdc);
}
else
{
PMRBP pmrbp;
if (!(pmrbp = (PMRBP) pmdc->pvNewRecord(SIZEOF_MRBP(cptl))))
return(FALSE);
pmrbp->vInit(mrType, cptl, (PPOINTL) pptl, pmdc);
pmrbp->vCommit(pmdc);
}
return(TRUE);
}
// PolyPolygon
// PolyPolyline
extern "C" BOOL MF_PolyPoly(HDC hdc, CONST POINT *pptl, CONST DWORD *pc,DWORD cPoly,DWORD mrType)
{
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_PolyPoly\n");
// Check input assumptions.
ASSERTGDI
(
mrType == EMR_POLYPOLYGON
|| mrType == EMR_POLYPOLYLINE,
"MF_PolyPoly: Bad record type"
);
ASSERTGDI
(
EMR_POLYPOLYLINE - EMR_POLYPOLYGON == EMR_POLYPOLYLINE16 - EMR_POLYPOLYGON16,
"MF_Poly: Bad record type"
);
// Compute the size of the PolyPoly record.
DWORD cptl = 0;
for (DWORD i = 0; i < cPoly; i++)
cptl += pc[i];
// Store 16-bit record if possible.
if (bIsPoly16((PPOINTL) pptl, cptl))
{
PMRBPP16 pmrbpp16;
if (!(pmrbpp16 = (PMRBPP16) pmdc->pvNewRecord(SIZEOF_MRBPP16(cptl,cPoly))))
return(FALSE);
pmrbpp16->vInit
(
mrType - EMR_POLYPOLYGON + EMR_POLYPOLYGON16,
cPoly,
cptl,
(LPDWORD) pc,
(PPOINTL) pptl,
pmdc
);
pmrbpp16->vCommit(pmdc);
}
else
{
PMRBPP pmrbpp;
if (!(pmrbpp = (PMRBPP) pmdc->pvNewRecord(SIZEOF_MRBPP(cptl,cPoly))))
return(FALSE);
pmrbpp->vInit(mrType, cPoly, cptl, (LPDWORD) pc, (PPOINTL) pptl, pmdc);
pmrbpp->vCommit(pmdc);
}
return(TRUE);
}
/******************************Public*Routine******************************\
* MF_TriangleMesh
*
*
* Arguments:
*
*
*
* Return Value:
*
*
*
* History:
*
* 12/3/1996 Mark Enstrom [marke]
*
\**************************************************************************/
extern "C" BOOL
MF_GradientFill(
HDC hdc,
CONST PTRIVERTEX pVertex,
ULONG nVertex,
CONST PVOID pMesh,
ULONG nMesh,
ULONG ulMode
)
{
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_TriangleMesh\n");
PMRGRADIENTFILL pmrtr;
if (!(pmrtr = (PMRGRADIENTFILL) pmdc->pvNewRecord(SIZEOF_MRGRADIENTFILL(nVertex,nMesh))))
{
return(FALSE);
}
pmrtr->vInit(nVertex,pVertex,nMesh,pMesh,ulMode,pmdc);
pmrtr->vCommit(pmdc);
SET_COLOR_PAGE(pldc);
return(TRUE);
}
// PolyDraw
extern "C" BOOL MF_PolyDraw(HDC hdc, CONST POINT *pptl, CONST BYTE *pb, DWORD cptl)
{
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_PolyDraw\n");
// Store 16-bit record if possible.
if (bIsPoly16((PPOINTL) pptl, cptl))
{
PMRPOLYDRAW16 pmrpd16;
if (!(pmrpd16 = (PMRPOLYDRAW16) pmdc->pvNewRecord(SIZEOF_MRPOLYDRAW16(cptl))))
return(FALSE);
pmrpd16->vInit(pmdc, (PPOINTL) pptl, pb, cptl);
pmrpd16->vCommit(pmdc);
}
else
{
PMRPOLYDRAW pmrpd;
if (!(pmrpd = (PMRPOLYDRAW) pmdc->pvNewRecord(SIZEOF_MRPOLYDRAW(cptl))))
return(FALSE);
pmrpd->vInit(pmdc, (PPOINTL) pptl, pb, cptl);
pmrpd->vCommit(pmdc);
}
return(TRUE);
}
// InvertRgn
// PaintRgn
extern "C" BOOL MF_InvertPaintRgn(HDC hdc,HRGN hrgn,DWORD mrType)
{
PMRBR pmrbr;
DWORD cRgnData;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_InvertPaintRgn\n");
// Get the size of the region data.
if (!(cRgnData = GetRegionData(hrgn, 0, (LPRGNDATA) NULL)))
return(FALSE);
// Allocate dword aligned structure.
if (!(pmrbr = (PMRBR) pmdc->pvNewRecord(SIZEOF_MRBR(cRgnData))))
return(FALSE);
if (!pmrbr->bInit(mrType, pmdc, hrgn, cRgnData, sizeof(MRBR)))
return(FALSE);
pmrbr->vCommit(pmdc);
return(TRUE);
}
// FillRgn
extern "C" BOOL MF_FillRgn(HDC hdc,HRGN hrgn,HBRUSH hbrush)
{
PMRFILLRGN pmrfr;
DWORD cRgnData;
DWORD imheBrush;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_FillRgn\n");
// Create the brush first.
if (!(imheBrush = MF_InternalCreateObject(hdc, hbrush)))
return(FALSE);
// Get the size of the region data.
if (!(cRgnData = GetRegionData(hrgn, 0, (LPRGNDATA) NULL)))
return(FALSE);
// Allocate dword aligned structure.
if (!(pmrfr = (PMRFILLRGN) pmdc->pvNewRecord(SIZEOF_MRFILLRGN(cRgnData))))
return(FALSE);
if (!pmrfr->bInit(pmdc, hrgn, cRgnData, imheBrush))
return(FALSE);
pmrfr->vCommit(pmdc);
return(TRUE);
}
// FrameRgn
extern "C" BOOL MF_FrameRgn(HDC hdc,HRGN hrgn,HBRUSH hbrush,int cx,int cy)
{
PMRFRAMERGN pmrfr;
DWORD cRgnData;
DWORD imheBrush;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_FrameRgn\n");
// Create the brush first.
if (!(imheBrush = MF_InternalCreateObject(hdc, hbrush)))
return(FALSE);
// Get the size of the region data.
if (!(cRgnData = GetRegionData(hrgn, 0, (LPRGNDATA) NULL)))
return(FALSE);
// Allocate dword aligned structure.
if (!(pmrfr = (PMRFRAMERGN) pmdc->pvNewRecord(SIZEOF_MRFRAMERGN(cRgnData))))
return(FALSE);
if (!pmrfr->bInit(pmdc, hrgn, cRgnData, imheBrush, (LONG) cx, (LONG) cy))
return(FALSE);
pmrfr->vCommit(pmdc);
return(TRUE);
}
// SelectClipRgn
// ExtSelectClipRgn
// SelectObject(hdc,hrgn)
extern "C" BOOL MF_ExtSelectClipRgn(HDC hdc,HRGN hrgn,int iMode)
{
PMREXTSELECTCLIPRGN pmrescr;
DWORD cRgnData;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_ExtSelectClipRgn\n");
// Get the size of the region data.
if (iMode == RGN_COPY && hrgn == (HRGN) 0)
cRgnData = 0;
else if (!(cRgnData = GetRegionData(hrgn, 0, (LPRGNDATA) NULL)))
return(FALSE);
// Allocate dword aligned structure.
if (!(pmrescr = (PMREXTSELECTCLIPRGN) pmdc->pvNewRecord
(SIZEOF_MREXTSELECTCLIPRGN(cRgnData))))
return(FALSE);
if (!pmrescr->bInit(hrgn, cRgnData, (DWORD) iMode))
return(FALSE);
pmrescr->vCommit(pmdc);
// We have to flush the bounds before we change the clipping region
// because the bounds are clipped to the current clipping region bounds.
pmdc->vFlushBounds();
// Now mark the clipping bounds dirty. The clipping bounds is updated
// when it is needed.
pmdc->vMarkClipBoundsDirty();
return(TRUE);
}
// SetPixel
// SetPixelV
extern "C" BOOL MF_SetPixelV(HDC hdc,int x,int y,COLORREF color)
{
PMRSETPIXELV pmrspv;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_SetPixelV\n");
if (!(pmrspv = (PMRSETPIXELV) pmdc->pvNewRecord(SIZEOF_MRSETPIXELV)))
return(FALSE);
pmrspv->vInit(x, y, color);
pmrspv->vCommit(pmdc);
CHECK_COLOR_PAGE(pldc,color);
return(TRUE);
}
// AngleArc
extern "C" BOOL MF_AngleArc(HDC hdc,int x,int y,DWORD r,FLOAT eA,FLOAT eB)
{
PMRANGLEARC pmraa;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_AngleArc\n");
if (!(pmraa = (PMRANGLEARC) pmdc->pvNewRecord(SIZEOF_MRANGLEARC)))
return(FALSE);
pmraa->vInit(x, y, r, eA, eB);
pmraa->vCommit(pmdc);
return(TRUE);
}
// SetArcDirection - This is recorded only when used.
extern "C" BOOL MF_ValidateArcDirection(HDC hdc)
{
PLDC pldc;
BOOL bClockwiseMeta, bClockwiseAdvanced;
DC_PLDC(hdc,pldc,FALSE);
PUTS("MF_ValidateArcDirection\n");
// Get the current arc direction recorded in the metafile.
// The metafile is recorded in the advanced graphics mode only.
bClockwiseMeta = (pldc->fl & LDC_META_ARCDIR_CLOCKWISE) ? TRUE : FALSE;
// Get the current arc direction in the advanced graphics mode.
bClockwiseAdvanced = (GetArcDirection(hdc) == AD_CLOCKWISE);
if (GetGraphicsMode(hdc) == GM_COMPATIBLE)
{
switch (GetMapMode(hdc))
{
case MM_LOMETRIC:
case MM_HIMETRIC:
case MM_LOENGLISH:
case MM_HIENGLISH:
case MM_TWIPS:
bClockwiseAdvanced = !bClockwiseAdvanced;
break;
//
// If it is MM_ANISOTROPIC and MM_ISOTROPIC
// and negative transform, we flip the arc direction.
// related bugs - 3026, 74010 [lingyunw]
//
case MM_ANISOTROPIC:
case MM_ISOTROPIC:
{
PDC_ATTR pDcAttr;
PVOID pvUser;
PSHARED_GET_VALIDATE(pvUser,hdc,DC_TYPE);
if (pvUser)
{
pDcAttr = (PDC_ATTR)pvUser;
//
// if the xform has changed, we call to the kernel
// to update it
//
if(pDcAttr->flXform &
(PAGE_XLATE_CHANGED | PAGE_EXTENTS_CHANGED | WORLD_XFORM_CHANGED))
{
if (!NtGdiUpdateTransform(hdc))
return(FALSE);
};
if (((pDcAttr->flXform & PTOD_EFM11_NEGATIVE) != 0) ^
((pDcAttr->flXform & PTOD_EFM22_NEGATIVE) != 0))
{
bClockwiseAdvanced = !bClockwiseAdvanced;
}
}
}
break;
}
}
// Record it only if the new arc direction differs from the recorded one.
if (bClockwiseMeta == bClockwiseAdvanced)
return(TRUE);
pldc->fl ^= LDC_META_ARCDIR_CLOCKWISE;
return
(
MF_SetD
(
hdc,
(DWORD) (bClockwiseAdvanced ? AD_CLOCKWISE : AD_COUNTERCLOCKWISE),
EMR_SETARCDIRECTION
)
);
}
// Ellipse
// Rectangle
extern "C" BOOL MF_EllipseRect(HDC hdc,int x1,int y1,int x2,int y2,DWORD mrType)
{
PMRE pmre;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_EllipseRect\n");
// Validate the arc direction in the metafile first.
if (!MF_ValidateArcDirection(hdc))
return(FALSE);
if (!(pmre = (PMRE) pmdc->pvNewRecord(SIZEOF_MRE)))
return(FALSE);
// If the box is empty, don't record it and return success.
switch (pmre->iInit(mrType, hdc, x1, y1, x2, y2))
{
case MRI_ERROR: return(FALSE);
case MRI_NULLBOX: return(TRUE);
case MRI_OK: break;
default: ASSERTGDI(FALSE, "MRE::iInit returned bad value");
break;
}
pmre->vCommit(pmdc);
return(TRUE);
}
// RoundRect
extern "C" BOOL MF_RoundRect(HDC hdc,int x1,int y1,int x2,int y2,int x3,int y3)
{
PMRROUNDRECT pmrrr;
PUTS("MF_RoundRect\n");
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
// Validate the arc direction in the metafile first.
if (!MF_ValidateArcDirection(hdc))
return(FALSE);
if (!(pmrrr = (PMRROUNDRECT) pmdc->pvNewRecord(SIZEOF_MRROUNDRECT)))
return(FALSE);
// If the box is empty, don't record it and return success.
switch (pmrrr->iInit(hdc, x1, y1, x2, y2, x3, y3))
{
case MRI_ERROR: return(FALSE);
case MRI_NULLBOX: return(TRUE);
case MRI_OK: break;
default: ASSERTGDI(FALSE, "MRROUNDRECT::iInit returned bad value");
break;
}
pmrrr->vCommit(pmdc);
return(TRUE);
}
// Arc
// ArcTo
// Chord
// Pie
extern "C" BOOL MF_ArcChordPie(HDC hdc,int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,DWORD mrType)
{
PMREPP pmrepp;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_ArcChordPie\n");
// Validate the arc direction in the metafile first.
if (!MF_ValidateArcDirection(hdc))
return(FALSE);
if (!(pmrepp = (PMREPP) pmdc->pvNewRecord(SIZEOF_MREPP)))
return(FALSE);
// If the box is empty, don't record it and return success.
switch (pmrepp->iInit(mrType, hdc, x1, y1, x2, y2, x3, y3, x4, y4))
{
case MRI_ERROR: return(FALSE);
case MRI_NULLBOX: return(TRUE);
case MRI_OK: break;
default: ASSERTGDI(FALSE, "MREPP::iInit returned bad value");
break;
}
pmrepp->vCommit(pmdc);
return(TRUE);
}
// SetWorldTransform
extern "C" BOOL MF_SetWorldTransform(HDC hdc, CONST XFORM *pxform)
{
PMRX pmrx;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_SetWorldTransform\n");
pldc->fl |= LDC_FONT_CHANGE;
if (!(pmrx = (PMRX) pmdc->pvNewRecord(SIZEOF_MRX)))
return(FALSE);
pmrx->vInit(EMR_SETWORLDTRANSFORM, *pxform);
pmrx->vCommit(pmdc);
return(TRUE);
}
// ModifyWorldTransform
extern "C" BOOL MF_ModifyWorldTransform(HDC hdc, CONST XFORM *pxform, DWORD iMode)
{
PMRXD pmrxd;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_ModifyWorldTransform\n");
pldc->fl |= LDC_FONT_CHANGE;
if (!(pmrxd = (PMRXD) pmdc->pvNewRecord(SIZEOF_MRXD)))
return(FALSE);
// If the mode is set to identity transform, use our identity transform
// since there may not be an input transform.
pmrxd->vInit
(
EMR_MODIFYWORLDTRANSFORM,
(iMode == MWT_IDENTITY) ? xformIdentity : *pxform,
iMode
);
pmrxd->vCommit(pmdc);
return(TRUE);
}
// SelectObject
// SelectPalette
extern "C" BOOL MF_SelectAnyObject(HDC hdc,HANDLE h,DWORD mrType)
{
DWORD imhe;
#ifdef LANGPACK
if(gbLpk && gdwDisableMetafileRec) // if there is alangpack, then don't record this (since we are in the middle of an exttextout call)
{
ASSERTGDI(LO_TYPE(h) == LO_FONT_TYPE, "gdwDisableMetafileRec\n");
return TRUE ;
}
#endif
// Do not do regions. Region call goes to ExtSelectClipRgn.
// Do not do bitmap. Metafile DC is not a memory device.
// MF_InternalCreateObject will return an error if given a bitmap handle.
PUTS("MF_SelectAnyObject\n");
// we need to set the DCBrush and DCPen here if they are selected
if ((h == ghbrDCBrush) || (h == ghbrDCPen))
{
PVOID p;
PDC_ATTR pDcAttr;
PSHARED_GET_VALIDATE(p,hdc,DC_TYPE);
pDcAttr = (PDC_ATTR)p;
if (pDcAttr)
{
if (h == ghbrDCBrush)
{
if (pDcAttr->ulDCBrushClr != CLR_INVALID)
{
// Dont know why they were creating a new brush. ghbrDCBrush is a stock object and can be used as such.
// h = (HANDLE) CreateSolidBrush (pDcAttr->ulDCBrushClr);
}
else
{
return (FALSE);
}
}
if (h == ghbrDCPen)
{
if (pDcAttr->ulDCPenClr != CLR_INVALID)
{
// Dont know why they were creating a new brush. ghbrDCPen is a stock object and can be used as such.
// h = (HANDLE) CreatePen (PS_SOLID, 0, pDcAttr->ulDCPenClr);
}
else
{
return (FALSE);
}
}
if (h == NULL)
{
return (FALSE);
}
}
}
if (!(imhe = MF_InternalCreateObject(hdc, h)))
return(FALSE);
return(MF_SetD(hdc, imhe, mrType));
}
// CreatePen
// CreatePenIndirect
// ExtCreatePen
// CreateBrushIndirect
// CreateDIBPatternBrush
// CreateDIBPatternBrushPt
// CreateHatchBrush
// CreatePatternBrush
// CreateSolidBrush
// CreatePalette
// CreateFont
// CreateFontIndirect
// CreateColorSpace
// Create an object if it does not exist. The object must not be a region.
// It also does not create bitmap objects since we keep them in the drawing
// records.
// Return the metafile handle index of the object. For stock objects,
// return the special object index.
// Return 0 on error.
DWORD MF_InternalCreateObject(HDC hdc,HANDLE hobj)
{
DWORD imhe;
UINT ii;
int iType;
int iRet;
LOGBRUSH lb;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_InternalCreateObject\n");
if (hobj == NULL)
{
return(0);
}
// Do not do bitmaps. We don't keep bitmap handles in metafiles.
iType = LO_TYPE(hobj);
if ((iType == LO_BITMAP_TYPE) || (iType == LO_DIBSECTION_TYPE))
{
ERROR_ASSERT(FALSE,
"MF_InternalCreateObject: Cannot select bitmap into an enhanced metafile DC");
return(0);
}
// Do not do regions. Regions are stored in the drawing records.
ASSERTGDI(iType != LO_REGION_TYPE,
"MF_InternalCreateObject: Bad object type");
// If this is a stock object, just return a special object index.
if (IS_STOCKOBJ(hobj))
{
for (ii = 0; ii <= STOCK_LAST; ii++)
{
if (GetStockObject(ii) == hobj)
{
if (iType == LO_FONT_TYPE)
{
pldc->fl |= LDC_FONT_CHANGE;
}
break;
}
}
return((DWORD) ENHMETA_STOCK_OBJECT + ii);
}
// Check if the metafile DC knows this object.
METALINK metalink(pmetalink16Get(hobj));
while (metalink.bValid() && (metalink.ihdc != H_INDEX(hdc)))
metalink.vNext();
// If the metafile DC knows this object, just return the metafile handle index.
if (metalink.bValid())
{
if( iType == LO_FONT_TYPE )
{
pldc->fl |= LDC_FONT_CHANGE;
}
return((DWORD) metalink.imhe);
}
// Create the object.
DWORD ulRet = 0; // Assume failure
// Allocate a metafile handle entry and update the metalink.
if ((imhe = imheAllocMHE(hdc, hobj)) == INVALID_INDEX)
return(ulRet);
switch (iType)
{
// Do brush.
case LO_BRUSH_TYPE:
iRet = GetObject(hobj,sizeof(lb),&lb);
// Stock objects is handled above.
ASSERTGDI(iRet,"MF_InternalCreateObject: Brush error");
switch (lb.lbStyle)
{
case BS_HATCHED:
case BS_SOLID:
CHECK_COLOR_PAGE (pldc,lb.lbColor);
case BS_HOLLOW:
PMRCREATEBRUSHINDIRECT pmrcbi;
if (!(pmrcbi = (PMRCREATEBRUSHINDIRECT) pmdc->pvNewRecord
(SIZEOF_MRCREATEBRUSHINDIRECT)))
break;
pmrcbi->vInit(imhe, lb);
pmrcbi->vCommit(pmdc);
ulRet = imhe;
break;
case BS_PATTERN:
case BS_DIBPATTERN:
case BS_DIBPATTERNPT:
{
UINT iUsage;
HBITMAP hbmRemote;
BMIH bmih;
DWORD cbBitsInfo;
DWORD cbBits;
BOOL bMonoBrush = FALSE;
if (!(hbmRemote = GetObjectBitmapHandle((HBRUSH)hobj, &iUsage)))
{
ASSERTGDI(FALSE,
"MF_InternalCreateObject: GetObjectBitmapHandle failed");
break;
}
// For a pattern brush, the usage should be set to DIB_PAL_INDICES
// if it is monochrome. If it is color, it becomes a dib pattern
// brush with DIB_RGB_COLORS usage.
if (lb.lbStyle == BS_PATTERN)
{
bMonoBrush = MonoBitmap(hbmRemote);
if (bMonoBrush)
iUsage = DIB_PAL_INDICES;
else
iUsage = DIB_RGB_COLORS;
}
// Get the bitmap info header and sizes.
if (!bMetaGetDIBInfo(hdc, hbmRemote, &bmih,
&cbBitsInfo, &cbBits, iUsage, 0, FALSE))
break;
// Finally create the record and get the bits.
PMRBRUSH pmrbr;
if (!(pmrbr = (PMRBRUSH) pmdc->pvNewRecord
(SIZEOF_MRBRUSH(cbBitsInfo,cbBits))))
break;
if (!pmrbr->bInit
(
bMonoBrush
? EMR_CREATEMONOBRUSH
: EMR_CREATEDIBPATTERNBRUSHPT,
hdc,
imhe,
hbmRemote,
bmih,
iUsage,
cbBitsInfo, // size of bitmap info
cbBits // size of bits buffer
)
)
break;
// Check whether this is a color brush
if (pmrbr->fColor)
{
SET_COLOR_PAGE(pldc);
}
pmrbr->vCommit(pmdc);
ulRet = imhe;
}
break;
default:
ASSERTGDI(FALSE, "MF_InternalCreateObject: Brush error");
}
break;
// Do pen.
case LO_PEN_TYPE:
PMRCREATEPEN pmrcpn;
// Allocate dword aligned structure.
if (!(pmrcpn = (PMRCREATEPEN) pmdc->pvNewRecord(SIZEOF_MRCREATEPEN)))
break;
if (!pmrcpn->bInit(hobj, imhe))
break;
CHECK_COLOR_PAGE (pldc,pmrcpn->GetPenColor());
pmrcpn->vCommit(pmdc);
ulRet = imhe;
break;
// Do extended pen.
case LO_EXTPEN_TYPE:
EXTLOGPEN elp;
PEXTLOGPEN pelp;
int cbelp,tcbelp;
// Get the size of the ExtPen.
if (!(cbelp = GetObjectA(hobj, 0, (LPVOID) NULL)))
break;
ASSERTGDI(cbelp % 4 == 0, "MF_InternalCreateObject: Bad ext pen size");
if (cbelp <= sizeof(EXTLOGPEN))
pelp = &elp;
else if (!(pelp = (PEXTLOGPEN) LocalAlloc(LMEM_FIXED, (UINT) cbelp)))
break;
// Get the ExtPen.
if (GetObjectA(hobj, cbelp, (LPVOID) pelp) == cbelp)
{
UINT iUsage;
HBITMAP hbmRemote = (HBITMAP) 0;
BMIH bmih;
DWORD cbBitsInfo = 0;
DWORD cbBits = 0;
BOOL bMonoBrush = FALSE;
// Use switch statement so we can use the break statement on error.
// The following code is similiar to the brush creation code.
switch (pelp->elpBrushStyle)
{
case BS_DIBPATTERN:
pelp->elpBrushStyle = BS_DIBPATTERNPT; // fall through
case BS_PATTERN:
case BS_DIBPATTERNPT:
if (!(hbmRemote = GetObjectBitmapHandle((HBRUSH)hobj, &iUsage)))
{
ASSERTGDI(FALSE,
"MF_InternalCreateObject: GetObjectBitmapHandle failed");
break;
}
// For a pattern brush, the usage should be set to
// DIB_PAL_INDICES if it is monochrome. If it is color,
// it becomes a dib pattern brush with DIB_RGB_COLORS usage.
if (pelp->elpBrushStyle == BS_PATTERN)
{
bMonoBrush = MonoBitmap(hbmRemote);
if (bMonoBrush)
iUsage = DIB_PAL_INDICES;
else
iUsage = DIB_RGB_COLORS;
}
// Get the bitmap info header and sizes.
if (!bMetaGetDIBInfo(hdc, hbmRemote, &bmih,
&cbBitsInfo, &cbBits, (DWORD) iUsage, 0, FALSE))
break;
// Record DIB bitmap if possible.
pelp->elpBrushStyle = bMonoBrush
? BS_PATTERN
: BS_DIBPATTERNPT;
*(PDWORD) &pelp->elpColor = (DWORD) iUsage;
pelp->elpHatch = 0;
// fall through
default:
tcbelp = cbelp;
#if !defined(_X86_)
// Adjust the elp to be EXTLOGPEN32 for IA64
// We do this by shifting all DWORDS from
// &(pelp->elpNumEntries) up by 4 bytes.
// This is to make sure the disk format is the same
// as the X86 compatible EXTLOGPEN32 bassed format.
MoveMemory((PBYTE)(&pelp->elpNumEntries)-4,
(PBYTE)(&pelp->elpNumEntries),
tcbelp-FIELD_OFFSET(EXTLOGPEN,elpNumEntries));
tcbelp -= 4;
#endif
// Finally create the record (and get the bits).
PMREXTCREATEPEN pmrecp;
// Allocate dword aligned structure.
if (!(pmrecp = (PMREXTCREATEPEN) pmdc->pvNewRecord
(SIZEOF_MREXTCREATEPEN(tcbelp,cbBitsInfo,cbBits))))
break;
if (!pmrecp->bInit
(
hdc,
imhe,
tcbelp,
(PEXTLOGPEN32)pelp,
hbmRemote,
bmih,
cbBitsInfo, // size of bitmap info
cbBits // size of bits buffer
)
)
break;
// Check for color page info
if (pelp->elpBrushStyle == BS_SOLID || pelp->elpBrushStyle == BS_HATCHED)
{
CHECK_COLOR_PAGE (pldc,pelp->elpColor);
}
else if (hbmRemote && pmrecp->fColor)
{
SET_COLOR_PAGE(pldc);
}
pmrecp->vCommit(pmdc);
ulRet = imhe;
break;
}
}
if (cbelp > sizeof(EXTLOGPEN))
{
if (LocalFree(pelp))
{
ASSERTGDI(FALSE, "MF_InternalCreateObject: LocalFree failed");
}
}
break;
// Do palette.
case LO_PALETTE_TYPE:
PMRCREATEPALETTE pmrcp;
USHORT cEntries;
if (GetObjectA(hobj, sizeof(USHORT), (LPVOID) &cEntries) != 2)
{
ASSERTGDI(FALSE, "MF_InternalCreateObject: GetObjectA failed");
break;
}
if (!(pmrcp = (PMRCREATEPALETTE) pmdc->pvNewRecord
(SIZEOF_MRCREATEPALETTE(cEntries))))
break;
// Also clear peFlags.
if (!pmrcp->bInit((HPALETTE) hobj, imhe, cEntries))
break;
// Also update the metafile palette.
if (!pmrcp->bCommit(pmdc))
break;
ulRet = imhe;
break;
// Do font.
case LO_FONT_TYPE:
PMREXTCREATEFONTINDIRECTW pmecfiw;
PLDC pldc;
int iSize;
ENUMLOGFONTEXDVW elfw;
pldc = GET_PLDC(hdc);
iSize = GetObjectW(hobj, (int)sizeof(ENUMLOGFONTEXDVW), (LPVOID)&elfw);
if (!iSize)
break;
ASSERTGDI(
((DWORD)iSize) == (offsetof(ENUMLOGFONTEXDVW,elfDesignVector) + SIZEOFDV(elfw.elfDesignVector.dvNumAxes)),
"sizeof enumlogfontexdvw is broken\n"
);
ASSERTGDI(
sizeof(EXTLOGFONTW) < (offsetof(ENUMLOGFONTEXDVW,elfDesignVector) + SIZEOFDV(0)),
"sizeof(EXTLOGFONTW) problem\n");
pldc->fl |= LDC_FONT_CHANGE;
if (!(pmecfiw = (PMREXTCREATEFONTINDIRECTW) pmdc->pvNewRecord
(SIZEOF_MRCREATEFONTINDIRECTEXW(iSize))))
break;
pmecfiw->vInit((HFONT) hobj, imhe, &elfw);
pmecfiw->vCommit(pmdc);
ulRet = imhe;
break;
// Do color space.
case LO_ICMLCS_TYPE:
if (!MF_InternalCreateColorSpace(hdc,hobj,imhe))
{
break;
}
ulRet = imhe;
break;
case LO_BITMAP_TYPE:
case LO_DIBSECTION_TYPE:
default:
ASSERTGDI(FALSE, "MF_InternalCreateObject: Bad object type\n");
break;
}
// Check for error.
if (ulRet == 0)
{
ERROR_ASSERT(FALSE,
"MF_InternalCreateObject: unable to record the object");
vFreeMHE(hdc, imhe);
return(ulRet);
}
ASSERTGDI(ulRet == imhe, "MF_InternalCreateObject: Bad return value");
// Update number of handles in the metafile header record.
pmdc->vUpdateNHandles(imhe);
// Return the metafile handle index of the object.
return(imhe);
}
// DeleteObject
extern "C" BOOL MF_DeleteObject(HANDLE h)
{
// We don't get called if it is a stock object.
HDC hdc;
METALINK metalink;
PUTS("MF_DeleteObject\n");
ASSERTGDI(pmetalink16Get(h) != NULL,
"MF_DeleteObject: No object to delete");
// Delete the object from each metafile DC which references it.
while (TRUE)
{
metalink.vInit(pmetalink16Get(h));
if (!metalink.bValid())
break;
hdc = hdcFromIhdc(metalink.ihdc);
#if DBG
ASSERTGDI(GET_PMDC(hdc)->pmhe[metalink.imhe].lhObject == h,
"MF_DeleteObject: Bad metalink");
ASSERTGDI(metalink.imhe != 0, // Index zero is reserved.
"MF_DeleteObject: Bad metalink");
#endif
// Send a delete object record.
(VOID) MF_SetD(hdc, (DWORD) metalink.imhe, EMR_DELETEOBJECT);
vFreeMHE(hdc, (ULONG) metalink.imhe);
}
return(TRUE);
}
// SetPaletteEntries
extern "C" BOOL MF_SetPaletteEntries
(
HPALETTE hpal,
UINT iStart,
UINT cEntries,
CONST PALETTEENTRY *pPalEntries
)
{
// We don't get called if it is a stock object.
PUTS("MF_SetPaletteEntries\n");
// Create a record in each metafile DC which references it.
// Note that if an object has been previously selected in a metafile DC
// and currently deselected, it is still referenced by the metafile DC.
for
(
METALINK metalink(pmetalink16Get(hpal));
metalink.bValid();
metalink.vNext()
)
{
// Get a metafile DC.
PMDC pmdc = GET_PMDC(hdcFromIhdc(metalink.ihdc));
PMRSETPALETTEENTRIES pmrspe;
ASSERTGDI(pmdc->pmhe[metalink.imhe].lhObject == hpal,
"MF_SetPaletteEntries: Bad metalink");
ASSERTGDI(metalink.imhe != 0, // Index zero is reserved.
"MF_SetPaletteEntries: Bad metalink");
// Send a SetPaletteEntries record.
if (!(pmrspe = (PMRSETPALETTEENTRIES) pmdc->pvNewRecord
(SIZEOF_MRSETPALETTEENTRIES(cEntries))))
return(FALSE);
// Also clear peFlags.
pmrspe->vInit(metalink.imhe, iStart, cEntries, pPalEntries);
// Also update the metafile palette.
if (!pmrspe->bCommit(pmdc))
return(FALSE);
}
return(TRUE);
}
/******************************Public*Routine******************************\
* MF_ColorCorrectPalette
*
*
* Arguments:
*
*
*
* Return Value:
*
*
*
* History:
*
* 9/23/1996 Mark Enstrom [marke]
*
\**************************************************************************/
extern "C"
BOOL
MF_ColorCorrectPalette(
HDC hdc,
HPALETTE hpal,
ULONG FirstEntry,
ULONG NumberOfEntries)
{
PMRDDDD pmrdddd;
DWORD imhePal;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_SetDDDD : ColorCorrectPalette\n");
//
// get palette
//
if (!(imhePal = MF_InternalCreateObject(hdc, hpal)))
{
return(FALSE);
}
if (!(pmrdddd = (PMRDDDD) pmdc->pvNewRecord(SIZEOF_MRDDDD)))
{
return(FALSE);
}
pmrdddd->vInit(EMR_COLORCORRECTPALETTE,imhePal,FirstEntry,NumberOfEntries,0);
pmrdddd->vCommit(pmdc);
return(TRUE);
}
// ResizePalette
extern "C" BOOL MF_ResizePalette(HPALETTE hpal,UINT c)
{
// We don't get called if it is a stock object.
PUTS("MF_ResizePalette\n");
// Create a record in each metafile DC which references it.
// Note that if an object has been previously selected in a metafile DC
// and currently deselected, it is still referenced by the metafile DC.
for
(
METALINK metalink(pmetalink16Get(hpal));
metalink.bValid();
metalink.vNext()
)
{
HDC hdc = hdcFromIhdc(metalink.ihdc);
ASSERTGDI(GET_PMDC(hdc)->pmhe[metalink.imhe].lhObject == hpal,
"MF_ResizePalette: Bad metalink");
ASSERTGDI(metalink.imhe != 0, // Index zero is reserved.
"MF_ResizePalette: Bad metalink");
// Send a ResizePalette record.
if
(
!MF_SetDD
(
hdc,
(DWORD)metalink.imhe,
(DWORD)c,
EMR_RESIZEPALETTE
)
)
return(FALSE);
}
return(TRUE);
}
// RealizePalette
//
// This function takes a hpal, not a hdc! We want to metafile RealizePalette
// calls in other DC which affect the metafile DCs as well. For example,
// if a palette is selected into a display DC and a metafile DC, a
// RealizePalette on the display DC will cause a record to be generated in
// the metafile DC. The reason is applications may expect this behavior
// in Windows although we do not completely agree with this. In any case,
// we do the right thing when they realize a palette on metafile DCs.
//
// Note that no record is generated if the stock palette is realized. This
// is compatible with the current design for palette management in metafiles.
extern "C" BOOL MF_RealizePalette(HPALETTE hpal)
{
// We don't get called if it is a stock object.
PUTS("MF_RealizePalette\n");
// Create a record in each metafile DC which selects it (NOT references it!).
// Note that if an object has been previously selected in a metafile DC
// and currently deselected, it is still referenced by the metafile DC.
for
(
METALINK metalink(pmetalink16Get(hpal));
metalink.bValid();
metalink.vNext()
)
{
HDC hdc = hdcFromIhdc(metalink.ihdc);
ASSERTGDI(GET_PMDC(hdc)->pmhe[metalink.imhe].lhObject == hpal,
"MF_RealizePalette: Bad metalink");
ASSERTGDI(metalink.imhe != 0, // Index zero is reserved.
"MF_RealizePalette: Bad metalink");
// Send a RealizePalette record.
if (GetDCObject(hdc,LO_PALETTE_TYPE) == hpal)
if (!MF_Record(hdc,EMR_REALIZEPALETTE))
return(FALSE);
}
return(TRUE);
}
// EOF - emit an EOF metafile record.
// This function is called by CloseEnhMetaFile to emit the last metafile record.
// The EOF record includes the metafile palette if any logical palette is
// used in the metafile.
extern "C" BOOL MF_EOF(HDC hdc, ULONG cEntries, PPALETTEENTRY pPalEntries)
{
PMREOF pmreof;
DWORD cbEOF;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_EOF\n");
cbEOF = SIZEOF_MREOF(cEntries);
if (!(pmreof = (PMREOF) pmdc->pvNewRecord(cbEOF)))
return(FALSE);
pmreof->vInit(cEntries, pPalEntries, cbEOF);
pmreof->vCommit(pmdc);
return(TRUE);
}
// GdiComment - emit a metafile comment record.
extern "C" BOOL MF_GdiComment(HDC hdc, UINT nSize, CONST BYTE *lpData)
{
PMRGDICOMMENT pmrc;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_GdiComment\n");
// Ignore GDICOMMENT_WINDOWS_METAFILE and other non-embeddable public comments.
// These comments are now extra baggage.
if (nSize >= 2 * sizeof(DWORD)
&& ((PDWORD) lpData)[0] == GDICOMMENT_IDENTIFIER
&& ((PDWORD) lpData)[1] & GDICOMMENT_NOEMBED)
return(TRUE);
if (!(pmrc = (PMRGDICOMMENT) pmdc->pvNewRecord(SIZEOF_MRGDICOMMENT(nSize))))
return(FALSE);
// If it is a GDICOMMENT_MULTIFORMATS or other public comments containing
// logical bounds, we need to accumulate the bounds.
// We assume that applications set up metafile palette properly before
// embedding so we do not have to accumulate the metafile palette here.
// We do the bounds after pvNewRecord so that the previous bounds is
// accounted for properly.
if (nSize >= 2 * sizeof(DWORD)
&& ((PDWORD) lpData)[0] == GDICOMMENT_IDENTIFIER
&& ((PDWORD) lpData)[1] & GDICOMMENT_ACCUMBOUNDS)
{
POINT aptBounds[4];
RECT rcBounds;
// The logical output rectangle follows the ident and iComment fields.
CONST RECTL *prclOutput = (PRECTL) &lpData[2 * sizeof(DWORD)];
aptBounds[0].x = prclOutput->left;
aptBounds[0].y = prclOutput->top;
aptBounds[1].x = prclOutput->right;
aptBounds[1].y = prclOutput->top;
aptBounds[2].x = prclOutput->right;
aptBounds[2].y = prclOutput->bottom;
aptBounds[3].x = prclOutput->left;
aptBounds[3].y = prclOutput->bottom;
if (!LPtoDP(hdc, aptBounds, 4))
return(FALSE);
rcBounds.left = MIN4(aptBounds[0].x,aptBounds[1].x,aptBounds[2].x,aptBounds[3].x);
rcBounds.right = MAX4(aptBounds[0].x,aptBounds[1].x,aptBounds[2].x,aptBounds[3].x);
rcBounds.top = MIN4(aptBounds[0].y,aptBounds[1].y,aptBounds[2].y,aptBounds[3].y);
rcBounds.bottom = MAX4(aptBounds[0].y,aptBounds[1].y,aptBounds[2].y,aptBounds[3].y);
(void) SetBoundsRectAlt(hdc, &rcBounds, (UINT) (DCB_WINDOWMGR | DCB_ACCUMULATE));
}
pmrc->vInit(nSize, lpData);
pmrc->vCommit(pmdc);
return(TRUE);
}
//
// Emit a EMF comment record which contains embedded font information
//
BOOL
WriteFontDataAsEMFComment(
PLDC pldc,
DWORD ulID,
PVOID buf1,
DWORD size1,
PVOID buf2,
DWORD size2
)
{
static struct {
DWORD reserved;
DWORD signature;
} FontCommentHeader = { 0, 'TONF' };
EMFITEMHEADER emfi = { ulID, size1+size2 };
COMMENTDATABUF databuf[4] = {
{ sizeof(FontCommentHeader), &FontCommentHeader },
{ sizeof(emfi), &emfi },
{ size1, buf1 },
{ size2, buf2 }
};
PMRGDICOMMENT pmrc;
UINT n;
PMDC pmdc = (PMDC) pldc->pvPMDC;
BOOL result;
if (!pmdc || !pmdc->bIsEMFSpool())
{
ASSERTGDI(FALSE, "WriteFontDataAsEMFComment: pmdc is NULL\n");
return FALSE;
}
//
// Record the font data as EMF comment and remember
// its location in the EMF spool file.
//
n = sizeof(FontCommentHeader) + sizeof(emfi) + size1 + size2;
if (!(pmrc = (PMRGDICOMMENT) pmdc->pvNewRecord(SIZEOF_MRGDICOMMENT(n))))
return FALSE;
n = SIZEOF_MRGDICOMMENT(0) + sizeof(FontCommentHeader);
result = pmdc->SaveFontCommentOffset(ulID, n);
pmrc->vInit(4, databuf);
pmrc->vCommit(pmdc);
return result;
}
// Emit a metafile comment record for embedded windows metafile.
extern "C" BOOL MF_GdiCommentWindowsMetaFile(HDC hdc, UINT nSize, CONST BYTE *lpData)
{
PMRGDICOMMENT pmrc;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_GdiCommentWindowsMetaFile\n");
if (!(pmrc = (PMRGDICOMMENT) pmdc->pvNewRecord(SIZEOF_MRGDICOMMENT_WINDOWS_METAFILE(nSize))))
return(FALSE);
pmrc->vInitWindowsMetaFile(nSize, lpData);
pmrc->vCommit(pmdc);
return(TRUE);
}
// Emit a metafile comment record for begin group. This is used to identify
// the beginning of an embedded enhanced metafile.
extern "C" BOOL MF_GdiCommentBeginGroupEMF(HDC hdc, PENHMETAHEADER pemfHeader)
{
PMRGDICOMMENT pmrc;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_GdiCommentBeginGroupEMF\n");
if (!(pmrc = (PMRGDICOMMENT) pmdc->pvNewRecord(SIZEOF_MRGDICOMMENT_BEGINGROUP(pemfHeader->nDescription))))
return(FALSE);
pmrc->vInitBeginGroupEMF(pemfHeader);
pmrc->vCommit(pmdc);
return(TRUE);
}
// Emit a metafile comment record for end group. This is used to identify
// the end of an embedded enhanced metafile.
extern "C" BOOL MF_GdiCommentEndGroupEMF(HDC hdc)
{
DWORD ad[2];
PUTS("MF_GdiCommentEndGroupEMF\n");
ad[0] = GDICOMMENT_IDENTIFIER; // ident
ad[1] = GDICOMMENT_ENDGROUP; // iComment
return(MF_GdiComment(hdc, (UINT) sizeof(ad), (LPBYTE) &ad));
}
// MF_AnyBitBlt helper.
extern "C" BOOL MF_DoBitBlt
(
PMDC pmdcDst,
int xDst,
int yDst,
int cxDst,
int cyDst,
DWORD rop,
int xSrc = 0,
int ySrc = 0,
PXFORM pxformSrc = &xformIdentity,
COLORREF clrBkSrc = 0,
PBMIH pbmihSrc = (PBMIH) NULL,
HBITMAP hbmSrc = (HBITMAP) 0,
DWORD cbBitsInfoSrc = 0,
DWORD cbBitsSrc = 0
)
{
PMRBB pmrbb;
if (!(pmrbb = (PMRBB) pmdcDst->pvNewRecord
(SIZEOF_MRBB(cbBitsInfoSrc,cbBitsSrc))))
return(FALSE);
// Use compression option
if (!pmrbb->bInit
(
EMR_BITBLT,
pmdcDst, // pmdcDst
xDst, // xDst
yDst, // yDst
cxDst, // cxDst
cyDst, // cyDst
rop, // rop
xSrc, // xSrc
ySrc, // ySrc
pxformSrc, // source DC transform
clrBkSrc, // source DC BkColor
pbmihSrc, // source bitmap info header
hbmSrc, // source bitmap to save
hbmSrc ? sizeof(MRBB) : 0, // offset to bitmap info
cbBitsInfoSrc, // size of bitmap info
hbmSrc ? sizeof(MRBB) + cbBitsInfoSrc : 0,// offset to bits
cbBitsSrc // size of bits buffer
)
)
return(FALSE);
pmrbb->vCommit(pmdcDst);
return(TRUE);
}
/******************************Public*Routine******************************\
* MF_DoAlphaBlend
*
*
* Arguments:
*
*
*
* Return Value:
*
*
*
* History:
*
* 12/3/1996 Mark Enstrom [marke]
*
\**************************************************************************/
extern "C" BOOL MF_DoAlphaBlend
(
PMDC pmdcDst,
int xDst,
int yDst,
int cxDst,
int cyDst,
DWORD Blend,
int xSrc,
int ySrc,
int cxSrc,
int cySrc,
PXFORM pxformSrc,
COLORREF clrBkSrc,
PBMIH pbmihSrc,
HBITMAP hbmSrc,
DWORD cbBitsInfoSrc,
DWORD cbBitsSrc
)
{
PMRALPHABLEND pmrai;
// We always have a source bitmap here. AlphaImage without a source is not valid
ASSERTGDI(hbmSrc != (HBITMAP) 0, "MF_DoAlphaBlend: Bad hbmSrc");
if (!(pmrai = (PMRALPHABLEND) pmdcDst->pvNewRecord
(SIZEOF_MRALPHABLEND(cbBitsInfoSrc,cbBitsSrc))))
return(FALSE);
// Use compression option
if (!pmrai->bInit
(
pmdcDst, // pmdcDst
xDst, // xDst
yDst, // yDst
cxDst, // cxDst
cyDst, // cyDst
Blend, // replaves rop
xSrc, // xSrc
ySrc, // ySrc
cxSrc, // cxSrc
cySrc, // cySrc
pxformSrc, // source DC transform
clrBkSrc, // source DC BkColor
pbmihSrc, // source bitmap info header
hbmSrc, // source bitmap to save
sizeof(MRALPHABLEND),// offset to bitmap info
cbBitsInfoSrc, // size of bitmap info
sizeof(MRALPHABLEND) + cbBitsInfoSrc,// offset to bits
cbBitsSrc // size of bits buffer
)
)
return(FALSE);
pmrai->vCommit(pmdcDst);
return(TRUE);
}
/******************************Public*Routine******************************\
* MF_DoTransparentBlt
*
*
* Arguments:
*
*
*
* Return Value:
*
*
*
* History:
*
* 12/3/1996 Mark Enstrom [marke]
*
\**************************************************************************/
extern "C" BOOL MF_DoTransparentBlt
(
PMDC pmdcDst,
int xDst,
int yDst,
int cxDst,
int cyDst,
DWORD Blend,
int xSrc,
int ySrc,
int cxSrc,
int cySrc,
PXFORM pxformSrc,
COLORREF clrBkSrc,
PBMIH pbmihSrc,
HBITMAP hbmSrc,
DWORD cbBitsInfoSrc,
DWORD cbBitsSrc
)
{
PMRTRANSPARENTBLT pmrai;
// We always have a source bitmap here. TransparentImage without a source is not valid
ASSERTGDI(hbmSrc != (HBITMAP) 0, "MF_DoTransparentImage: Bad hbmSrc");
if (!(pmrai = (PMRTRANSPARENTBLT) pmdcDst->pvNewRecord
(SIZEOF_MRTRANSPARENTBLT(cbBitsInfoSrc,cbBitsSrc))))
return(FALSE);
// Use compression option
if (!pmrai->bInit
(
pmdcDst, // pmdcDst
xDst, // xDst
yDst, // yDst
cxDst, // cxDst
cyDst, // cyDst
Blend, // color
xSrc, // xSrc
ySrc, // ySrc
cxSrc,
cySrc,
pxformSrc, // source DC transform
clrBkSrc, // source DC BkColor
pbmihSrc, // source bitmap info header
hbmSrc, // source bitmap to save
sizeof(MRTRANSPARENTBLT),// offset to bitmap info
cbBitsInfoSrc, // size of bitmap info
sizeof(MRTRANSPARENTBLT) + cbBitsInfoSrc,// offset to bits
cbBitsSrc // size of bits buffer
)
)
return(FALSE);
pmrai->vCommit(pmdcDst);
return(TRUE);
}
// MF_AnyBitBlt helper.
extern "C" BOOL MF_DoStretchBlt
(
PMDC pmdcDst,
int xDst,
int yDst,
int cxDst,
int cyDst,
DWORD rop,
int xSrc,
int ySrc,
int cxSrc,
int cySrc,
PXFORM pxformSrc,
COLORREF clrBkSrc,
PBMIH pbmihSrc,
HBITMAP hbmSrc,
DWORD cbBitsInfoSrc,
DWORD cbBitsSrc
)
{
PMRSTRETCHBLT pmrsb;
// We always have a source bitmap here. StretchBlt without a source is
// recorded as BitBlt.
ASSERTGDI(hbmSrc != (HBITMAP) 0, "MF_DoStretchBlt: Bad hbmSrc");
if (!(pmrsb = (PMRSTRETCHBLT) pmdcDst->pvNewRecord
(SIZEOF_MRSTRETCHBLT(cbBitsInfoSrc,cbBitsSrc))))
return(FALSE);
// Use compression option
if (!pmrsb->bInit
(
pmdcDst, // pmdcDst
xDst, // xDst
yDst, // yDst
cxDst, // cxDst
cyDst, // cyDst
rop, // rop
xSrc, // xSrc
ySrc, // ySrc
cxSrc, // cxSrc
cySrc, // cySrc
pxformSrc, // source DC transform
clrBkSrc, // source DC BkColor
pbmihSrc, // source bitmap info header
hbmSrc, // source bitmap to save
sizeof(MRSTRETCHBLT),// offset to bitmap info
cbBitsInfoSrc, // size of bitmap info
sizeof(MRSTRETCHBLT) + cbBitsInfoSrc,// offset to bits
cbBitsSrc // size of bits buffer
)
)
return(FALSE);
pmrsb->vCommit(pmdcDst);
return(TRUE);
}
// MF_AnyBitBlt helper.
extern "C" BOOL MF_DoMaskBlt
(
PMDC pmdcDst,
int xDst,
int yDst,
int cxDst,
int cyDst,
DWORD rop3,
PBMIH pbmihMask,
HBITMAP hbmMask,
DWORD cbBitsInfoMask,
DWORD cbBitsMask,
int xMask,
int yMask,
int xSrc,
int ySrc,
PXFORM pxformSrc,
COLORREF clrBkSrc = 0,
PBMIH pbmihSrc = (PBMIH) NULL,
HBITMAP hbmSrc = (HBITMAP) 0,
DWORD cbBitsInfoSrc = 0,
DWORD cbBitsSrc = 0
)
{
PMRMASKBLT pmrmb;
DWORD offBase = sizeof(MRMASKBLT);
DWORD offBitsInfoSrc = 0;
DWORD offBitsSrc = 0;
DWORD offBitsInfoMask = 0;
DWORD offBitsMask = 0;
if (hbmSrc)
{
offBitsInfoSrc = offBase;
offBitsSrc = offBitsInfoSrc + cbBitsInfoSrc;
offBase = offBitsSrc + cbBitsSrc;
}
if (hbmMask)
{
offBitsInfoMask = offBase;
offBitsMask = offBitsInfoMask + cbBitsInfoMask;
}
// Now create the record.
if (!(pmrmb = (PMRMASKBLT) pmdcDst->pvNewRecord
(SIZEOF_MRMASKBLT(cbBitsInfoSrc,cbBitsSrc,cbBitsInfoMask,cbBitsMask))))
return(FALSE);
// Use compression option
if (!pmrmb->bInit
(
pmdcDst, // pmdcDst
xDst, // xDst
yDst, // yDst
cxDst, // cxDst
cyDst, // cyDst
rop3, // rop3
xSrc, // xSrc
ySrc, // ySrc
pxformSrc, // source DC transform
clrBkSrc, // source DC BkColor
pbmihSrc, // source bitmap info header
hbmSrc, // source bitmap to save
offBitsInfoSrc, // offset to bitmap info
cbBitsInfoSrc, // size of bitmap info
offBitsSrc, // offset to bits
cbBitsSrc, // size of bits buffer
xMask, // xMask
yMask, // yMask
pbmihMask, // mask bitmap info header
hbmMask, // mask bitmap
offBitsInfoMask, // offset to mask bitmap info
cbBitsInfoMask, // size of mask bitmap info
offBitsMask, // offset to mask bits
cbBitsMask // size of mask bits buffer
)
)
return(FALSE);
pmrmb->vCommit(pmdcDst);
return(TRUE);
}
// MF_AnyBitBlt helper.
extern "C" BOOL MF_DoPlgBlt
(
PMDC pmdcDst,
CONST POINT *pptDst,
PBMIH pbmihMask,
HBITMAP hbmMask,
DWORD cbBitsInfoMask,
DWORD cbBitsMask,
int xMask,
int yMask,
int xSrc,
int ySrc,
int cxSrc,
int cySrc,
PXFORM pxformSrc,
COLORREF clrBkSrc,
PBMIH pbmihSrc,
HBITMAP hbmSrc,
DWORD cbBitsInfoSrc,
DWORD cbBitsSrc
)
{
PMRPLGBLT pmrpb;
// We always have a source bitmap here. Destination to destination PlgBlt
// is not allowed.
ASSERTGDI(hbmSrc != (HBITMAP) 0, "MF_DoPlgBlt: Bad hbmSrc");
// Now create the record.
if (!(pmrpb = (PMRPLGBLT) pmdcDst->pvNewRecord
(SIZEOF_MRPLGBLT(cbBitsInfoSrc,cbBitsSrc,cbBitsInfoMask,cbBitsMask))))
return(FALSE);
// Use compression option
if (!pmrpb->bInit
(
pmdcDst, // pmdcDst
pptDst, // pptDst
xSrc, // xSrc
ySrc, // ySrc
cxSrc, // cxSrc
cySrc, // cySrc
pxformSrc, // source DC transform
clrBkSrc, // source DC BkColor
pbmihSrc, // source bitmap info header
hbmSrc, // source bitmap to save
sizeof(MRPLGBLT), // offset to bitmap info
cbBitsInfoSrc, // size of bitmap info
sizeof(MRPLGBLT) + cbBitsInfoSrc,// offset to bits
cbBitsSrc, // size of bits buffer
xMask, // xMask
yMask, // yMask
pbmihMask, // mask bitmap info header
hbmMask, // mask bitmap
hbmMask // offset to mask bitmap info
? sizeof(MRPLGBLT) + cbBitsInfoSrc + cbBitsSrc
: 0,
cbBitsInfoMask, // size of mask bitmap info
hbmMask // offset to mask bits
? sizeof(MRPLGBLT) + cbBitsInfoSrc + cbBitsSrc + cbBitsInfoMask
: 0,
cbBitsMask // size of mask bits buffer
)
)
return(FALSE);
pmrpb->vCommit(pmdcDst);
return(TRUE);
}
// bMetaGetDIBInfo
//
// Gets the bitmap info header and sizes.
//
// If hbm or hbmRemote is given, it queries the bitmap info header and
// fills in the BITMAPINFOHERADER structure at pBmih. A hdc is required
// if iUsage is DIB_PAL_COLORS.
//
// If no hbm or hbmRemote is given, it assumes that it is called by
// SetDIBitsToDevice or StretchDIBits and pBmih already points to a
// bitmap info header (BITMAPINFOHEADER) or core header (BITMAPCOREHEADER).
//
// In any case, the size for bitmap info (BITMAPINFO) with color table
// and the size for the bitmap bits is returned in pcbBmi and pcbBits
// respectively. We do not store BITMAPCOREINFO structure in the metafiles.
//
// If cScans is non zero, only the size for the bitmap bits of this many
// scans is given. The callers in this case are SetDIBitsToDevice or
// StretchDIBits.
//
// This function is called in many places and any modifications have to
// be verified carefully! It should be kept current with the
// cjBitmapSize and cjBitmapBitsSize functions.
//
// Returns TRUE if successful, FALSE otherwise.
BOOL bMetaGetDIBInfo
(
HDC hdc,
HBITMAP hbm,
PBMIH pBmih,
PDWORD pcbBmi,
PDWORD pcbBits,
DWORD iUsage,
LONG cScans,
BOOL bMeta16
)
{
DWORD cjClr;
DWORD cbBmi;
DWORD cbBits;
PUTS("bMetaGetDIBInfo\n");
if (pBmih == NULL)
return(FALSE);
// If hbm is given, we need to get the bitmap info header.
// Otherwise, pBmih already has the bitmap info header.
if (hbm)
{
pBmih->biSize = sizeof(BMIH);
pBmih->biBitCount = 0; // don't fill in color table
pBmih->biCompression = BI_RGB;
if (!GetDIBits(hdc, hbm, 0, 0, (LPBYTE) NULL,
(LPBITMAPINFO) pBmih, (UINT) iUsage))
{
ASSERTGDI(FALSE, "bMetaGetDIBInfo: InternalGetDIBits failed");
return(FALSE);
}
// Windows always zeros the clrUsed and clrImportant fields.
// 16-bit metafiles also do not support 16/32bpp bitmaps.
if (bMeta16)
{
pBmih->biClrUsed = 0;
pBmih->biClrImportant = 0;
if (pBmih->biPlanes != 1
|| pBmih->biBitCount == 16 || pBmih->biBitCount == 32)
{
pBmih->biPlanes = 1;
pBmih->biBitCount = 24;
pBmih->biCompression = BI_RGB;
pBmih->biSizeImage = 0;
iUsage = DIB_RGB_COLORS;
}
}
}
// Compute size of a color entry.
switch (iUsage)
{
case DIB_RGB_COLORS:
cjClr = sizeof(RGBQUAD);
break;
case DIB_PAL_COLORS:
cjClr = sizeof(WORD);
ASSERTGDI(sizeof(WORD) == 2, "bMetaGetDIBInfo: Bad size");
break;
case DIB_PAL_INDICES:
cjClr = 0;
break;
default:
ASSERTGDI(FALSE, "bMetaGetDIBInfo: Bad iUsage");
return(FALSE);
}
// Compute size of the bitmap info (with color table) and bitmap bits buffer.
// We will store only BITMAPINFO in the record only. The BITMAPCOREINFO
// structure will be stored as BITMAPINFO in the metafile.
if (pBmih->biSize > sizeof(BMIH))
{
cbBmi = pBmih->biSize;
}
else
{
cbBmi = sizeof(BMIH);
}
if (pBmih->biSize == sizeof(BMCH))
{
if (((LPBMCH) pBmih)->bcBitCount == 16 || ((LPBMCH) pBmih)->bcBitCount == 32)
{
ASSERTGDI(FALSE, "bMetaGetDIBInfo: 16/32bpp bitmap not allowed in core bitmap info");
return(FALSE);
}
if (((LPBMCH) pBmih)->bcBitCount < 16)
cbBmi += (1 << ((LPBMCH) pBmih)->bcBitCount) * cjClr;
cbBits = CJSCAN(((LPBMCH) pBmih)->bcWidth,
((LPBMCH) pBmih)->bcPlanes,
((LPBMCH) pBmih)->bcBitCount)
* (cScans ? cScans : (DWORD) ((LPBMCH) pBmih)->bcHeight);
}
else
{
if (pBmih->biBitCount == 16 || pBmih->biBitCount == 32)
{
if (pBmih->biCompression == BI_BITFIELDS)
cbBmi += 3 * sizeof(DWORD);
}
else if (pBmih->biBitCount == 24)
{
// BI_BITFIELDS not allowed
}
else if ((pBmih->biCompression == BI_JPEG) ||
(pBmih->biCompression == BI_PNG))
{
// No color table for JPEG and PNG images
}
else if (pBmih->biClrUsed)
cbBmi += pBmih->biClrUsed * cjClr;
else if (pBmih->biBitCount < 16)
cbBmi += (1 << pBmih->biBitCount) * cjClr;
// compute cbBits. We first do the computation and then use biSizeImage
// if it is smaller than cbBits.
cbBits = CJSCAN(pBmih->biWidth, pBmih->biPlanes, pBmih->biBitCount)
* (cScans ? cScans : ABS(pBmih->biHeight));
if (((pBmih->biSizeImage > 0) &&
(pBmih->biSizeImage < cbBits ||
pBmih->biCompression == BI_RLE8 ||
pBmih->biCompression == BI_RLE4)) ||
(pBmih->biCompression == BI_PNG) ||
(pBmih->biCompression == BI_JPEG))
cbBits = pBmih->biSizeImage;
}
*pcbBmi = cbBmi;
*pcbBits = cbBits;
return(TRUE);
}
// BitBlt
// PatBlt
// StretchBlt
// MaskBlt
// PlgBlt
extern "C" BOOL MF_AnyBitBlt
(
HDC hdcDst,
int xDst,
int yDst,
int cxDst,
int cyDst,
CONST POINT *pptDst,
HDC hdcSrc,
int xSrc,
int ySrc,
int cxSrc,
int cySrc,
HBITMAP hbmMask,
int xMask,
int yMask,
DWORD rop, // For MaskBlt, this is rop3!
// For PlgBlt, this must be 0xCCAA0000!
DWORD mrType
)
{
DWORD cbBitsInfoMask = 0;
DWORD cbBitsMask = 0;
BMIH bmihMask;
PBMIH pbmihMask = (PBMIH) NULL;
XFORM xformSrc;
PLDC pldc;
DC_PLDC(hdcDst,pldc,FALSE);
PMDC pmdcDst = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdcDst,"no pmdc\n");
PUTS("MF_AnyBitBlt\n");
ASSERTGDI(mrType == EMR_BITBLT
|| mrType == EMR_STRETCHBLT
|| mrType == EMR_MASKBLT
|| mrType == EMR_PLGBLT
|| mrType == EMR_ALPHABLEND
|| mrType == EMR_TRANSPARENTBLT,
"MF_AnyBitBlt: Bad mrType");
// Do mask first.
if (hbmMask)
{
// Get the mask's bitmap info header and sizes.
pbmihMask = &bmihMask;
if (!bMetaGetDIBInfo(hdcDst, hbmMask, &bmihMask,
&cbBitsInfoMask, &cbBitsMask, DIB_PAL_INDICES, 0, FALSE))
return(FALSE);
// Make sure that it is monochrome.
if (bmihMask.biPlanes != 1 && bmihMask.biBitCount != 1)
return(FALSE);
}
// These two checks are needed to make sure that the following rop test works.
if ((mrType == EMR_BITBLT || mrType == EMR_STRETCHBLT)
&& (rop & (0xff000000 & ~NOMIRRORBITMAP)) != 0)
{
WARNING("MF_AnyBitBlt: Bad BitBlt/StretchBlt rop");
return(FALSE);
}
ASSERTGDI(mrType != EMR_PLGBLT || rop == 0xCCAA0000,
"MF_AnyBitBlt: Bad PlgBlt rop");
// Get the source transform if a source is required by the rop.
// For MaskBlt, we always need the source transform.
if (
ISSOURCEINROP3(rop) ||
(mrType == EMR_MASKBLT) ||
(mrType == EMR_ALPHABLEND) ||
(mrType == EMR_TRANSPARENTBLT)
)
{
// Get source transform.
if (!GetTransform(hdcSrc, XFORM_WORLD_TO_DEVICE, &xformSrc))
return(FALSE);
// Make sure that it is a scale.
if (xformSrc.eM12 != 0.0f || xformSrc.eM21 != 0.0f)
return(FALSE);
// Set color page flag
SET_COLOR_PAGE(pldc);
}
// Do blts with a source. The source must allow bit query operation.
if (
ISSOURCEINROP3(rop) ||
(mrType == EMR_TRANSPARENTBLT) ||
(mrType == EMR_ALPHABLEND)
)
{
COLORREF clrBkSrc;
BOOL bRet = FALSE; // assume failure
// We need to record the source bitmap. The source DC must be a memory
// DC or a direct DC that allows bits to be retrieved. As a result, the
// source DC cannot be an enhanced metafile DC. That is, destination
// to destination blts are not allowed in an enhanced metafile!
if (IS_ALTDC_TYPE(hdcSrc))
{
PLDC pldcSrc;
DC_PLDC(hdcSrc,pldcSrc,FALSE);
if (pldcSrc->iType == LO_METADC)
return(FALSE);
}
// Get source bk color.
if ((clrBkSrc = GetNearestColor(hdcSrc, GetBkColor(hdcSrc)))
== CLR_INVALID)
{
return(FALSE);
}
// Compute the area of the source bitmap to save in the metafile.
// First we find the coordinates of the source rectange in the
// device/bitmap units. Then we expand the rectangle by one pixel
// unit to account for possible rounding errors. Finally we map
// the rectangle to the playback bitmap origin by modifying the
// translation elements in the source transform.
// Verify pdev
LONG lWidthSrc, lHeightSrc;
RECTL rclSrc;
RECTL rclBitmap;
DWORD cbBitsInfoCompat;
DWORD cbBitsCompat;
HBITMAP hbmTmp = 0;
HBITMAP hbmCompat = 0;
HDC hdcCompat = 0;
int iSaveState = 0;
BMIH bmihCompat;
// Get source rectangle in device/bitmap coordinates. Since the
// source transform is a scale, we can simply convert the endpoints
// of the source rectangle.
ASSERTGDI((mrType != EMR_BITBLT && mrType != EMR_MASKBLT)
|| (cxDst == cxSrc && cyDst == cySrc),
"MF_AnyBitBlt: Bad width and height in BitBlt/MaskBlt");
ASSERTGDI(sizeof(RECTL) == sizeof(POINT)*2, "MF_AnyBitBlt: Bad size");
((PERECTL) &rclSrc)->vInit(xSrc, ySrc, xSrc + cxSrc, ySrc + cySrc);
if (!LPtoDP(hdcSrc, (LPPOINT) &rclSrc, 2))
return(FALSE);
// Order the result. We assume it to be inclusive-inclusive.
((PERECTL) &rclSrc)->vOrder();
// Expand it by one pixel.
rclSrc.left--;
rclSrc.top--;
rclSrc.right++;
rclSrc.bottom++;
// Map it to the playback bitmap origin.
xformSrc.eDx -= (FLOAT) rclSrc.left;
xformSrc.eDy -= (FLOAT) rclSrc.top;
// We now have the rectangle which defines the size of the playback
// bitmap. But we still need to clip it to the source device/bitmap
// limits. This is done by reducing the size of the rectangle and
// translating its origin.
((PERECTL) &rclBitmap)->vInit
(0, 0, rclSrc.right - rclSrc.left, rclSrc.bottom - rclSrc.top);
// Get source width and height
// WINBUG #82866 2-7-2000 bhouse Investigate possible bug in MfAnyBitBlt
// Old Comment:
// - if it is a direct DC, we really want to fall through to the
// second case. Will either the GetDCObject or GetObject fail?
HBITMAP hbm = (HBITMAP)GetDCObject(hdcSrc, LO_BITMAP_TYPE);
BITMAP bmSrc;
if (hbm && GetObjectA((HANDLE)hbm,sizeof(BITMAP),(LPVOID) &bmSrc))
{
lWidthSrc = bmSrc.bmWidth;
lHeightSrc = bmSrc.bmHeight;
}
else
{
lWidthSrc = GetDeviceCaps(hdcDst, DESKTOPHORZRES);
lHeightSrc = GetDeviceCaps(hdcDst, DESKTOPVERTRES);
}
// Clip the source rectangle to the source device/bitmap limits.
// Adjust the playback bitmap size and source transform at the
// same time.
if (rclSrc.left < 0) // Shift and clip the left edge.
{
rclBitmap.right += rclSrc.left;
xformSrc.eDx += (FLOAT) rclSrc.left;
rclSrc.left = 0;
}
if (rclSrc.right >= lWidthSrc) // Clip the right edge.
{
rclBitmap.right -= (rclSrc.right - lWidthSrc + 1);
rclSrc.right -= (rclSrc.right - lWidthSrc + 1);
}
if (rclSrc.top < 0) // Shift and clip the top edge.
{
rclBitmap.bottom += rclSrc.top;
xformSrc.eDy += (FLOAT) rclSrc.top;
rclSrc.top = 0;
}
if (rclSrc.bottom >= lHeightSrc) // Clip the bottom edge.
{
rclBitmap.bottom -= (rclSrc.bottom - lHeightSrc + 1);
rclSrc.bottom -= (rclSrc.bottom - lHeightSrc + 1);
}
// If the rectangle is completely clipped, there is no playback
// bitmap and nothing to blt.
if (rclBitmap.right < 0 || rclBitmap.bottom < 0)
return(TRUE);
// We now have the size of the playback bitmap. We will create a bitmap
// compatible to the source, copy the bits to the compatible bitmap
// and finally retrieve and store the bits in the metafile record.
// Create a compatible DC.
if (!(hdcCompat = CreateCompatibleDC(hdcSrc)))
goto mfbb_src_exit;
// Create a compatible bitmap.
if (!(hbmCompat = CreateCompatibleBitmap
(
hdcSrc,
(int) rclBitmap.right + 1,
(int) rclBitmap.bottom + 1
)
)
)
goto mfbb_src_exit;
// Select the bitmap.
if (!(hbmTmp = (HBITMAP)SelectObject(hdcCompat, (HANDLE)hbmCompat)))
goto mfbb_src_exit;
// Set up the source DC to have the same identity transform as the
// compatible DC so that the following bitblt call will not scale.
if (!(iSaveState = SaveDC(hdcSrc)))
goto mfbb_src_exit;
// Must be in the advanced graphics mode to modify the world transform.
SetGraphicsMode(hdcSrc, GM_ADVANCED);
if (!SetMapMode(hdcSrc, MM_TEXT)
|| !ModifyWorldTransform(hdcSrc, (LPXFORM) NULL, MWT_IDENTITY)
|| !SetWindowOrgEx(hdcSrc, 0, 0, (LPPOINT) NULL)
|| !SetViewportOrgEx(hdcSrc, 0, 0, (LPPOINT) NULL))
goto mfbb_src_exit;
// Copy the source bits into the compatible bitmap.
if (!BitBlt(hdcCompat, // Dest dc
0, // Dest x
0, // Dest y
(int) rclBitmap.right + 1, // Width
(int) rclBitmap.bottom + 1, // Height
hdcSrc, // Src dc
(int) rclSrc.left, // Src x
(int) rclSrc.top, // Src y
SRCCOPY)) // Rop
goto mfbb_src_exit;
// Retrieve the bitmap info header.
SelectObject(hdcCompat, hbmTmp);
hbmTmp = 0; // don't deselect it again later.
// Get the bitmap info header and sizes.
if (!bMetaGetDIBInfo(hdcCompat, hbmCompat, &bmihCompat,
&cbBitsInfoCompat, &cbBitsCompat, DIB_RGB_COLORS, 0, FALSE))
goto mfbb_src_exit;
// Finally create the record and get the bits.
pmdcDst->hdcSrc = hdcSrc;
switch (mrType)
{
case EMR_BITBLT:
bRet = MF_DoBitBlt
(
pmdcDst, // pmdcDst
xDst, // xDst
yDst, // yDst
cxDst, // cxDst
cyDst, // cyDst
rop, // rop
xSrc, // xSrc
ySrc, // ySrc
&xformSrc, // source DC transform
clrBkSrc, // source DC BkColor
&bmihCompat, // source bitmap info header
hbmCompat, // source bitmap to save
cbBitsInfoCompat, // size of bitmap info
cbBitsCompat // size of bits buffer
);
break;
case EMR_STRETCHBLT:
bRet = MF_DoStretchBlt
(
pmdcDst, // pmdcDst
xDst, // xDst
yDst, // yDst
cxDst, // cxDst
cyDst, // cyDst
rop, // rop
xSrc, // xSrc
ySrc, // ySrc
cxSrc, // cxSrc
cySrc, // cySrc
&xformSrc, // source DC transform
clrBkSrc, // source DC BkColor
&bmihCompat, // source bitmap info header
hbmCompat, // source bitmap to save
cbBitsInfoCompat, // size of bitmap info
cbBitsCompat // size of bits buffer
);
break;
case EMR_MASKBLT:
bRet = MF_DoMaskBlt
(
pmdcDst, // pmdcDst
xDst, // xDst
yDst, // yDst
cxDst, // cxDst
cyDst, // cyDst
rop, // rop
pbmihMask, // mask bitmap info header
hbmMask, // hbmMask
cbBitsInfoMask, // size of mask bitmap info
cbBitsMask, // size of mask bits buffer
xMask, // xMask
yMask, // yMask
xSrc, // xSrc
ySrc, // ySrc
&xformSrc, // source DC transform
clrBkSrc, // source DC BkColor
&bmihCompat, // source bitmap info header
hbmCompat, // source bitmap to save
cbBitsInfoCompat, // size of bitmap info
cbBitsCompat // size of bits buffer
);
break;
case EMR_PLGBLT:
bRet = MF_DoPlgBlt
(
pmdcDst, // pmdcDst
pptDst, // pptDst
pbmihMask, // mask bitmap info header
hbmMask, // hbmMask
cbBitsInfoMask, // size of mask bitmap info
cbBitsMask, // size of mask bits buffer
xMask, // xMask
yMask, // yMask
xSrc, // xSrc
ySrc, // ySrc
cxSrc, // cxSrc
cySrc, // cySrc
&xformSrc, // source DC transform
clrBkSrc, // source DC BkColor
&bmihCompat, // source bitmap info header
hbmCompat, // source bitmap to save
cbBitsInfoCompat, // size of bitmap info
cbBitsCompat // size of bits buffer
);
break;
case EMR_ALPHABLEND:
bRet = MF_DoAlphaBlend(
pmdcDst, // pmdcDst
xDst, // xDst
yDst, // yDst
cxDst, // cxDst
cyDst, // cyDst
rop, // rop
xSrc, // xSrc
ySrc, // ySrc
cxSrc, // cxSrc
cySrc, // cySrc
&xformSrc, // source DC transform
clrBkSrc, // source DC BkColor
&bmihCompat, // source bitmap info header
hbmCompat, // source bitmap to save
cbBitsInfoCompat, // size of bitmap info
cbBitsCompat // size of bits buffer
);
break;
case EMR_TRANSPARENTBLT:
bRet = MF_DoTransparentBlt(
pmdcDst, // pmdcDst
xDst, // xDst
yDst, // yDst
cxDst, // cxDst
cyDst, // cyDst
rop, // rop
xSrc, // xSrc
ySrc, // ySrc
cxSrc,
cySrc,
&xformSrc, // source DC transform
clrBkSrc, // source DC BkColor
&bmihCompat, // source bitmap info header
hbmCompat, // source bitmap to save
cbBitsInfoCompat, // size of bitmap info
cbBitsCompat // size of bits buffer
);
break;
}
mfbb_src_exit:
// Clean up and go home.
if (iSaveState)
{
if (!RestoreDC(hdcSrc, -1))
{
ASSERTGDI(FALSE, "MF_AnyBitBlt: RestoreDC failed");
}
}
if (hbmTmp)
{
if (!SelectObject(hdcCompat, hbmTmp))
{
ASSERTGDI(FALSE, "MF_AnyBitBlt: SelectObject failed");
}
}
if (hbmCompat)
{
if (!DeleteObject(hbmCompat))
{
ASSERTGDI(FALSE, "MF_AnyBitBlt: DeleteObject failed");
}
}
if (hdcCompat)
{
if (!DeleteDC(hdcCompat))
{
ASSERTGDI(FALSE, "MF_AnyBitBlt: DeleteDC failed");
}
}
return(bRet);
}
// It requires no source DC.
switch (mrType)
{
// StretchBlt is just a BitBlt here.
case EMR_BITBLT:
case EMR_STRETCHBLT:
return
(
MF_DoBitBlt
(
pmdcDst,
xDst,
yDst,
cxDst,
cyDst,
rop
)
);
case EMR_MASKBLT:
return
(
MF_DoMaskBlt
(
pmdcDst,
xDst,
yDst,
cxDst,
cyDst,
rop,
pbmihMask,
hbmMask,
cbBitsInfoMask,
cbBitsMask,
xMask,
yMask,
xSrc,
ySrc,
&xformSrc
)
);
// PlgBlt requires a source.
case EMR_PLGBLT:
ASSERTGDI(FALSE, "MF_AnyBitBlt: Source needed in PlgBlt");
return(FALSE);
}
return FALSE;
}
// SetDIBitsToDevice (for both 16- and 32-bit metafiles)
// StretchDIBits (for both 16- and 32-bit metafiles)
extern "C" BOOL MF_AnyDIBits
(
HDC hdcDst,
int xDst,
int yDst,
int cxDst,
int cyDst,
int xDib,
int yDib,
int cxDib,
int cyDib,
DWORD iStartScan,
DWORD cScans,
CONST VOID * pBitsDib,
CONST BITMAPINFO *pBitsInfoDib,
DWORD iUsageDib,
DWORD rop,
DWORD mrType
)
{
DWORD cbBitsInfoDib = 0;
DWORD cbBitsDib = 0;
DWORD cbProfData = 0;
VOID *pProfData = NULL;
PUTS("MF_AnyDIBits\n");
ASSERTGDI(mrType == EMR_SETDIBITSTODEVICE || mrType == EMR_STRETCHDIBITS
|| mrType == META_SETDIBTODEV || mrType == META_STRETCHDIB,
"MF_AnyDIBits: Bad mrType");
ASSERTGDI(mrType == EMR_STRETCHDIBITS || mrType == META_STRETCHDIB
|| rop == SRCCOPY,
"MF_AnyDIBits: Bad rop");
if (ISSOURCEINROP3(rop))
{
// Get the bitmap sizes.
// We will store only BITMAPINFO in the record only. The
// BITMAPCOREINFO structure will be converted and stored as
// BITMAPINFO in the metafile.
// If it is a SetDIBitsToDevice, cScans cannot be zero.
// If it is a StretchDIBits, cScans must be zero.
if (mrType == EMR_SETDIBITSTODEVICE || mrType == META_SETDIBTODEV)
if (!cScans)
return(FALSE);
if (!bMetaGetDIBInfo(hdcDst, (HBITMAP) 0, (PBMIH) pBitsInfoDib,
&cbBitsInfoDib, &cbBitsDib, iUsageDib, cScans, FALSE))
return(FALSE);
// If there is any attached color space data, get pointer to that.
// (only for BITMAPV5 headers.
if (pBitsInfoDib->bmiHeader.biSize == sizeof(BITMAPV5HEADER))
{
PBITMAPV5HEADER pBmih5 = (PBITMAPV5HEADER)pBitsInfoDib;
// if there is any attached profile data, count it on.
if (((pBmih5->bV5CSType == PROFILE_EMBEDDED) ||
(pBmih5->bV5CSType == PROFILE_LINKED))
&&
(pBmih5->bV5ProfileData != 0))
{
ICMMSG(("MF_AnyDIBits(): Metafiling attached color profile data\n"));
pProfData = (BYTE *)pBmih5 + pBmih5->bV5ProfileData;
cbProfData = pBmih5->bV5ProfileSize;
}
}
}
switch (mrType)
{
case EMR_SETDIBITSTODEVICE:
{
PMRSETDIBITSTODEVICE pmrsdb;
PLDC pldc;
DC_PLDC(hdcDst,pldc,FALSE);
PMDC pmdcDst = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdcDst,"no pmdc\n");
if (!(pmrsdb = (PMRSETDIBITSTODEVICE) pmdcDst->pvNewRecord
(SIZEOF_MRSETDIBITSTODEVICE(cbBitsInfoDib,cbBitsDib,cbProfData))))
return(FALSE);
pmrsdb->vInit
(
pmdcDst, // pmdcDst
(LONG) xDst, // xDst
(LONG) yDst, // yDst
(LONG) xDib, // xDib
(LONG) yDib, // yDib
(DWORD) cxDib, // cxDib
(DWORD) cyDib, // cyDib
iStartScan, // iStartScan
cScans, // cScans
cbBitsDib, // size of bits buffer
pBitsDib, // dib bits
cbBitsInfoDib, // size of bitmap info
pBitsInfoDib, // dib info
cbProfData, // size of color profile data (if BITMAPV5)
pProfData, // color profile data
iUsageDib // dib info usage
);
pmrsdb->vCommit(pmdcDst);
SET_COLOR_PAGE(pldc);
}
break;
case EMR_STRETCHDIBITS:
{
PMRSTRETCHDIBITS pmrstrdb;
PLDC pldc;
DC_PLDC(hdcDst,pldc,FALSE);
PMDC pmdcDst = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdcDst,"no pmdc\n");
if (!(pmrstrdb = (PMRSTRETCHDIBITS) pmdcDst->pvNewRecord
(SIZEOF_MRSTRETCHDIBITS(cbBitsInfoDib,cbBitsDib,cbProfData))))
return(FALSE);
pmrstrdb->vInit
(
pmdcDst, // pmdcDst
(LONG) xDst, // xDst
(LONG) yDst, // yDst
(LONG) cxDst, // cxDst
(LONG) cyDst, // cyDst
(LONG) xDib, // xDib
(LONG) yDib - iStartScan, // yDib
(LONG) cxDib, // cxDib
(LONG) cyDib, // cyDib
cScans, // cScans
cbBitsDib, // size of bits buffer
cScans ? ((PBYTE)pBitsDib) +
CJSCAN(pBitsInfoDib->bmiHeader.biWidth,pBitsInfoDib->bmiHeader.biPlanes,
pBitsInfoDib->bmiHeader.biBitCount)* iStartScan
: pBitsDib, // dib bits
cbBitsInfoDib, // size of bitmap info
pBitsInfoDib, // dib info
iUsageDib, // dib info usage
cbProfData, // size of color profile data (if BITMAPV5)
pProfData, // color profile data
rop // rop
);
pmrstrdb->vCommit(pmdcDst);
SET_COLOR_PAGE(pldc);
}
break;
case META_SETDIBTODEV:
case META_STRETCHDIB:
{
// Do not handle DIB_PAL_INDICES because there is no palette
// information available.
if (cbBitsInfoDib != 0 && iUsageDib == DIB_PAL_INDICES)
return(FALSE);
// Convert new bitmap formats to win3 bitmap formats
if (cbBitsInfoDib != 0
&& (pBitsInfoDib->bmiHeader.biSize == sizeof(BMIH))
&& (pBitsInfoDib->bmiHeader.biPlanes != 1
||pBitsInfoDib->bmiHeader.biBitCount == 16
||pBitsInfoDib->bmiHeader.biBitCount == 32))
{
BOOL b = FALSE;
HDC hdc = (HDC) 0;
HBITMAP hbm = (HBITMAP) 0;
PBYTE pBits24 = (PBYTE) NULL;
DWORD cbBits24;
BMIH bmih;
if (iUsageDib == DIB_PAL_COLORS)
return(FALSE); // illegal usage
hdc = CreateCompatibleDC((HDC) 0);
if (!(hbm = CreateDIBitmap(hdc,
(LPBITMAPINFOHEADER) pBitsInfoDib,
CBM_CREATEDIB, (LPBYTE) NULL, pBitsInfoDib, DIB_RGB_COLORS)))
goto error_exit;
if (!SetDIBits(hdc, hbm,
cScans ? (UINT) iStartScan : 0,
cScans ? (UINT) cScans : (UINT) pBitsInfoDib->bmiHeader.biHeight,
(CONST VOID *) pBitsDib, pBitsInfoDib, (UINT) iUsageDib))
goto error_exit;
bmih = *(PBITMAPINFOHEADER) pBitsInfoDib;
bmih.biPlanes = 1;
bmih.biBitCount = 24;
bmih.biCompression = BI_RGB;
bmih.biSizeImage = 0;
bmih.biClrUsed = 0;
bmih.biClrImportant = 0;
cbBits24 = CJSCAN(bmih.biWidth,bmih.biPlanes,bmih.biBitCount)
* (cScans ? cScans : ABS(bmih.biHeight));
pBits24 = (LPBYTE) LocalAlloc(LMEM_FIXED, (UINT) cbBits24);
if (pBits24 == (LPBYTE) NULL)
goto error_exit;
// Get bitmap info and bits in 24bpp.
if (!GetDIBits(hdc,
hbm,
cScans ? (UINT) iStartScan : 0,
cScans ? (UINT) cScans : (UINT) bmih.biHeight,
(LPVOID) pBits24,
(LPBITMAPINFO) &bmih,
DIB_RGB_COLORS))
goto error_exit;
b = MF16_RecordDIBits
(
hdcDst,
xDst,
yDst,
cxDst,
cyDst,
xDib,
yDib,
cxDib,
cyDib,
iStartScan,
cScans,
cbBits24,
pBits24,
sizeof(bmih),
(LPBMI) &bmih,
DIB_RGB_COLORS,
rop,
mrType
);
error_exit:
if (hdc)
DeleteDC(hdc);
if (hbm)
DeleteObject(hbm);
if (pBits24)
LocalFree((HANDLE) pBits24);
return(b);
}
else
{
return
(
MF16_RecordDIBits
(
hdcDst,
xDst,
yDst,
cxDst,
cyDst,
xDib,
yDib,
cxDib,
cyDib,
iStartScan,
cScans,
cbBitsDib,
pBitsDib,
cbBitsInfoDib,
pBitsInfoDib,
iUsageDib,
rop,
mrType
)
);
}
}
}
return(TRUE);
}
// SetFontXform
// This function is called only by the metafile playback code.
// If hdc is an enhanced metafile DC, we need to remember the scales
// so that we can metafile it in the compatible ExtTextOut or PolyTextOut
// record that follows.
extern "C" BOOL MF_SetFontXform(HDC hdc,FLOAT exScale,FLOAT eyScale)
{
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
pmdc->exFontScale(exScale);
pmdc->eyFontScale(eyScale);
return(TRUE);
}
// TextOutA
// TextOutW
// ExtTextOutA
// ExtTextOutW
extern "C" BOOL MF_ExtTextOut(
HDC hdc
, int x
, int y
, UINT fl
, CONST RECT *prcl
, LPCSTR psz
, int c
, CONST INT *pdx
, DWORD mrType
)
{
#define BUFCOUNT 256
WCHAR awc[BUFCOUNT];
WCHAR *pwsz;
PLDC pldc;
int bAlloc = 0;
BOOL bRet = TRUE;
DWORD dwCP;
INT pDxCaptureBuffer[BUFCOUNT * 2]; // just in case there is pdy
INT cSave;
PVOID pDCAttr;
switch (mrType)
{
case EMR_EXTTEXTOUTW:
pwsz = (WCHAR*) psz;
break;
case EMR_EXTTEXTOUTA:
if (c < BUFCOUNT)
{
// if the multi byte string is small enough then use
// the buffer on the frame
pwsz = awc;
}
else
{
if (!(pwsz = (WCHAR*) LOCALALLOC((c+1) * (sizeof(WCHAR)+
((fl & ETO_PDY) ? (sizeof(INT) * 2) : sizeof(INT))))))
{
WARNING("MF_ExtTextOut: failed memory allocation\n");
return(FALSE);
}
bAlloc = 1;
}
dwCP = GetCodePage(hdc);
if(fFontAssocStatus)
{
dwCP = FontAssocHack(dwCP,(char*)psz,c);
}
cSave = c;
c = MultiByteToWideChar(dwCP, 0, psz, c, pwsz, c*sizeof(WCHAR));
break;
default:
WARNING("MF_ExtTextOut: Bad record type");
return(FALSE);
}
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_ExtTextOut\n");
pldc = GET_PLDC( hdc );
if (pldc == NULL)
{
WARNING("MF_ExtTextOut: unable to retrieve pldc\n");
if (bAlloc)
{
LOCALFREE((void*) pwsz);
}
return(FALSE);
}
if( (pldc->fl & (LDC_FONT_CHANGE | LDC_FONT_SUBSET | LDC_LINKED_FONTS)) &&
(pldc->fl & (LDC_DOWNLOAD_FONTS | LDC_FORCE_MAPPING )) )
{
bDoFontChange(hdc, pwsz, c, fl);
pldc->fl &= ~LDC_FONT_CHANGE;
}
else if (!(pldc->fl & (LDC_DOWNLOAD_FONTS | LDC_FORCE_MAPPING)) && // local printing
(pldc->fl & LDC_EMBED_FONTS)) // current process has embedded fonts
{
bRecordEmbedFonts(hdc);
}
PSHARED_GET_VALIDATE(pDCAttr,hdc,DC_TYPE);
// optimization for printing. If there is no pdx array, lTextExtra, lBreakExtra and cBreak, don't record pdx
if((pldc->fl & LDC_META_PRINT) && (pdx == NULL) && ( ((PDC_ATTR)pDCAttr)->lTextExtra == 0 ) &&
( ((PDC_ATTR)pDCAttr)->lBreakExtra == 0 ) && ( ((PDC_ATTR)pDCAttr)->cBreak == 0) )
{
PMRSMALLTEXTOUT pmrsto;
BOOL bSmallGlyphs = TRUE;
int cGlyphs;
UINT cSize;
for( cGlyphs = 0; cGlyphs < c; cGlyphs++ )
{
if( pwsz[cGlyphs] & 0xFF00 )
{
bSmallGlyphs = FALSE;
break;
}
}
cSize = sizeof(MRSMALLTEXTOUT);
cSize += c * ( ( bSmallGlyphs ) ? sizeof(char) : sizeof(WCHAR) );
cSize += ( prcl == NULL ) ? 0 : sizeof(RECT);
cSize = ( cSize + 3 ) & ~3;
if( !(pmrsto = (PMRSMALLTEXTOUT) pmdc->pvNewRecord(cSize)) )
{
bRet = FALSE;
}
else
{
pmrsto->vInit(hdc,
pmdc,
EMR_SMALLTEXTOUT,
x,
y,
fl,
(RECT*) prcl,
c,
pwsz,
bSmallGlyphs );
pmrsto->vCommit(pmdc);
}
}
else
{
PMREXTTEXTOUT pmreto;
UINT cjCh = sizeof(WCHAR);
INT *pDxCapt = (INT *)pdx;
if((mrType == EMR_EXTTEXTOUTA) && (pdx != NULL))
{
if (IS_ANY_DBCS_CODEPAGE(dwCP))
{
pDxCapt = (bAlloc) ? (INT*) &pwsz[(cSave+1)&~1] : pDxCaptureBuffer;
ConvertDxArray(dwCP,
(char*) psz,
(int*) pdx,
cSave,
pDxCapt,
(BOOL)(fl & ETO_PDY)
);
}
else
{
pDxCapt = (INT *)pdx;
}
}
if(!(pmreto=(PMREXTTEXTOUT)pmdc->pvNewRecord(SIZEOF_MREXTTEXTOUT(c,cjCh,(fl & ETO_PDY)))) ||
!pmreto->bInit(EMR_EXTTEXTOUTW,pmdc,hdc,x,y,fl,prcl,(LPCSTR)pwsz,
c,(CONST INT *)pDxCapt,cjCh))
{
bRet = FALSE;
}
else
{
pmreto->vCommit(pmdc);
}
}
if (bAlloc)
LOCALFREE((void*) pwsz);
return(bRet);
#undef BUFCOUNT
}
// PolyTextOutA
// PolyTextOutW
extern "C" BOOL MF_PolyTextOut(HDC hdc, CONST POLYTEXTA *ppta, int c, DWORD mrType)
{
DWORD mrTypeT;
BOOL b;
CONST POLYTEXTA *pptaT;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_PolyTextOut\n");
// [kirko] 19-Apr-94
//
// I have changed this routine to call off to MF_ExtTextOut for each member
// of the POLYTEXT? array. This is a little sleazy in that we are recording
// a different function than what was sent down by the application. On the
// other hand, it works and it is not incompatible with Chicago since they
// don't support a PolyTextOut function. You may be concerned that we are losing
// speed since we no longer call off to the spiffy fase PolyTextOut routine.
// But, if you look in GDI you will find that that PolyTextOut just calls off
// to ExtTextOut in a loop. We have just moved the loop to the Metafile recording.
// If PolyTextOut is ever made fast again, the Metafile code should then be
// modified to record those calls directly.
switch (mrType)
{
case EMR_POLYTEXTOUTA:
mrTypeT = EMR_EXTTEXTOUTA;
break;
case EMR_POLYTEXTOUTW:
mrTypeT = EMR_EXTTEXTOUTW;
break;
default:
WARNING("MF_PolyTextOut -- bad mrType");
return(FALSE);
}
for (b = TRUE, pptaT = ppta + c; ppta < pptaT && b; ppta++)
{
b = MF_ExtTextOut(hdc, ppta->x, ppta->y, ppta->uiFlags, &(ppta->rcl)
, ppta->lpstr, ppta->n, ppta->pdx, mrTypeT);
}
return(b);
}
extern "C" BOOL MF_ExtFloodFill(HDC hdc,int x,int y,COLORREF color,DWORD iMode)
{
PMREXTFLOODFILL pmreff;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_ExtFloodFill\n");
if (!(pmreff = (PMREXTFLOODFILL) pmdc->pvNewRecord(SIZEOF_MREXTFLOODFILL)))
return(FALSE);
pmreff->vInit(x, y, color, iMode);
pmreff->vCommit(pmdc);
return(TRUE);
}
// SetColorAdjustment
extern "C" BOOL MF_SetColorAdjustment(HDC hdc, CONST COLORADJUSTMENT *pca)
{
PMRSETCOLORADJUSTMENT pmrsca;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
PUTS("MF_SetColorAdjustment\n");
if (!(pmrsca = (PMRSETCOLORADJUSTMENT) pmdc->pvNewRecord(SIZEOF_MRSETCOLORADJUSTMENT(pca))))
return(FALSE);
pmrsca->vInit(pca);
pmrsca->vCommit(pmdc);
return(TRUE);
}
extern "C" BOOL MF_WriteEscape(HDC hdc, int nEscape, int nCount, LPCSTR lpInData, int type )
{
PMRESCAPE pmre;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
MFD2("Recording escape %d\n", nEscape );
// just in case some one (pagemaker) passes in NULL with non 0 count!
if (lpInData == NULL)
nCount = 0;
if (!(pmre = (PMRESCAPE) pmdc->pvNewRecord((sizeof(MRESCAPE)+nCount+3)&~3)))
{
WARNING("MF_WriteEscape: failed memory allocation\n");
return(FALSE);
}
pmre->vInit(type, nEscape, nCount, lpInData);
pmre->vCommit(pmdc);
if (type == EMR_DRAWESCAPE ||
nEscape == PASSTHROUGH ||
nEscape == POSTSCRIPT_DATA ||
nEscape == POSTSCRIPT_PASSTHROUGH ||
nEscape == ENCAPSULATED_POSTSCRIPT)
{
SET_COLOR_PAGE (pldc);
}
return(TRUE);
}
extern "C" BOOL MF_WriteNamedEscape(
HDC hdc,
LPWSTR pwszDriver,
int nEscape,
int nCount,
LPCSTR lpInData)
{
PMRNAMEDESCAPE pmre;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
MFD2("Recording named escape %d\n", nEscape );
INT cjSizeOfRecord = (sizeof(MRNAMEDESCAPE) + nCount +
((wcslen(pwszDriver)+1) * sizeof(WCHAR)) +3)&~3;
if(!(pmre = (PMRNAMEDESCAPE) pmdc->pvNewRecord(cjSizeOfRecord)))
{
WARNING("MF_WriteEscape: failed memory allocation\n");
return(FALSE);
}
pmre->vInit(EMR_NAMEDESCAPE, nEscape, pwszDriver, lpInData, nCount);
pmre->vCommit(pmdc);
return(TRUE);
}
extern "C" BOOL MF_StartDoc(HDC hdc, CONST DOCINFOW *pDocInfo )
{
PMRSTARTDOC pmrs;
DWORD cj;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
MFD1( "Recording MF_StartDocW\n" );
cj = sizeof(MRSTARTDOC);
if( pDocInfo->lpszDocName != NULL )
{
cj += (lstrlenW( pDocInfo->lpszDocName ) + 1) * sizeof(WCHAR);
cj = (cj+3) & ~(0x3);
}
if( pDocInfo->lpszOutput != NULL )
{
cj += (lstrlenW( pDocInfo->lpszOutput ) + 1) * sizeof(WCHAR);
}
cj = (cj+3) & ~(0x3); // make things DWORD alligned
if (!(pmrs = (PMRSTARTDOC) pmdc->pvNewRecord( cj+40 )))
{
WARNING("MF_StartDoc: failed memory allocation\n");
return(FALSE);
}
pmrs->vInit(EMR_STARTDOC, pDocInfo);
pmrs->vCommit(pmdc);
return(TRUE);
}
extern "C" BOOL MF_ForceUFIMapping(HDC hdc, PUNIVERSAL_FONT_ID pufi )
{
PMRFORCEUFIMAPPING pmre;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
MFD1("Recording forced mapping\n");
if (!(pmre = (PMRFORCEUFIMAPPING) pmdc->pvNewRecord(sizeof(MRFORCEUFIMAPPING))))
{
WARNING("MF_ForceUFIMapping: failed memory allocation\n");
return(FALSE);
}
pmre->vInit(EMR_FORCEUFIMAPPING, pufi);
pmre->vCommit(pmdc);
return(TRUE);
}
extern "C" BOOL MF_SetLinkedUFIs(HDC hdc, PUNIVERSAL_FONT_ID pufi,UINT uNumLinkedUFIs )
{
PMRSETLINKEDUFIS pmre;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc,"no pmdc\n");
MFD1("Recording SetLinkedUFIs\n");
UINT AllocationSize = sizeof(MRSETLINKEDUFIS) + sizeof(UNIVERSAL_FONT_ID) *
uNumLinkedUFIs;
if(!(pmre = (PMRSETLINKEDUFIS) pmdc->pvNewRecord(AllocationSize)))
{
WARNING("MF_orceUFIMapping: failed memory allocation\n");
return(FALSE);
}
pmre->vInit(uNumLinkedUFIs, pufi);
pmre->vCommit(pmdc);
return(TRUE);
}
// OpenGL metafile records
BOOL APIENTRY GdiAddGlsRecord(HDC hdc, DWORD cb, BYTE *pb, LPRECTL prclBounds)
{
PMRGLSRECORD pmrgr;
PMRGLSBOUNDEDRECORD pmrgbr;
PLDC pldc;
DC_PLDC(hdc, pldc, FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc, "no pmdc\n");
if (prclBounds == NULL)
{
pmrgr = (PMRGLSRECORD)pmdc->pvNewRecord(SIZEOF_MRGLSRECORD(cb));
if (pmrgr == NULL)
{
return FALSE;
}
pmrgr->vInit(cb, pb);
pmrgr->vCommit(pmdc);
}
else
{
pmrgbr = (PMRGLSBOUNDEDRECORD)
pmdc->pvNewRecord(SIZEOF_MRGLSBOUNDEDRECORD(cb));
if (pmrgbr == NULL)
{
return FALSE;
}
pmrgbr->vInit(cb, pb, prclBounds);
pmrgbr->vCommit(pmdc);
}
// Mark the metafile as containing OpenGL records
pmdc->mrmf.bOpenGL = TRUE;
// NTFIXED #34919(old RaidDB 423900) 02-07-2000 pravins OPENGL PRINT: Prints
// to many color printers in black an white only.
// This page can be a color.
SET_COLOR_PAGE(pldc);
return TRUE;
}
extern "C" BOOL APIENTRY GdiAddGlsBounds(HDC hdc, LPRECTL prclBounds)
{
// Bounds are given as a well-ordered rectangle in
// device coordinates
return SetBoundsRectAlt(hdc, (RECT *)prclBounds,
(UINT)(DCB_WINDOWMGR | DCB_ACCUMULATE)) != 0;
}
extern "C" BOOL APIENTRY MF_SetPixelFormat(HDC hdc,
int iPixelFormat,
CONST PIXELFORMATDESCRIPTOR *ppfd)
{
PMRPIXELFORMAT pmrpf;
PLDC pldc;
DC_PLDC(hdc, pldc, FALSE);
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc, "no pmdc\n");
pmrpf = (PMRPIXELFORMAT)pmdc->pvNewRecord(SIZEOF_MRPIXELFORMAT);
if (pmrpf == NULL)
{
return FALSE;
}
pmrpf->vInit(ppfd);
pmrpf->vCommit(pmdc);
// Fix up the pixel format offset in the header
// This only allows one pixel format to be
// described in the header. This doesn't seem too bad
// but we don't really need the pixel format offset in the
// header since there should always be a pixel format record
// in the metafile (as long as a pixel format is set)
pmdc->mrmf.cbPixelFormat = sizeof(PIXELFORMATDESCRIPTOR);
pmdc->mrmf.offPixelFormat = pmdc->iMem-sizeof(MRPIXELFORMAT)+
FIELD_OFFSET(MRPIXELFORMAT, pfd);
return TRUE;
}
extern "C" BOOL APIENTRY MF_SetICMProfile(HDC hdc, LPBYTE lpFile, PVOID pvColorSpace, DWORD dwRecordType)
{
BOOL bRet = TRUE;
PMRSETICMPROFILE pmsip;
WCHAR UnicFileName[MAX_PATH];
WCHAR PathFileName[MAX_PATH+1];
PCACHED_COLORSPACE pColorSpace = (PCACHED_COLORSPACE) pvColorSpace;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PUTS("MF_SetICMProfile\n");
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc, "no pmdc\n");
ASSERTGDI((dwRecordType == EMR_SETICMPROFILEA) ||
(dwRecordType == EMR_SETICMPROFILEW), "Invalid Record Type\n");
CLIENT_SIDE_FILEVIEW MappedProfile;
DWORD dwFlags = 0;
DWORD dwNameLength = 0;
DWORD dwDataLength = 0;
LPBYTE lpName = NULL;
LPBYTE lpData = NULL;
#if DBG
BOOL bDownload = ((pldc->fl & LDC_DOWNLOAD_PROFILES) || (DbgIcm & DBG_ICM_METAFILE));
#else
BOOL bDownload = (pldc->fl & LDC_DOWNLOAD_PROFILES);
#endif
if (pColorSpace)
{
ICMMSG(("MF_SetICMProfile[A|W]():Metafiling by color space\n"));
//
// Get profile name from CACHED_COLORSPACE.
//
lpName = (PBYTE)&(pColorSpace->LogColorSpace.lcsFilename[0]);
//
// Unicode record.
//
dwRecordType = EMR_SETICMPROFILEW;
}
else if (lpFile)
{
ICMMSG(("MF_SetICMProfile[A|W]():Metafiling by file name\n"));
//
// If ansi API, the lpName is ansi based string, Convert the string to Unicode.
//
if (bDownload && (dwRecordType == EMR_SETICMPROFILEA))
{
//
// Convert ANSI to Unicode.
//
vToUnicodeN(UnicFileName,MAX_PATH,(char *)lpFile,strlen((char *)lpFile)+1);
lpName = (LPBYTE) UnicFileName;
//
// And this is download, which means only EMF-spooling case comes here.
// so this record is only play back on NT. thus we are safe to convert
// record this as Unicode.
//
dwRecordType = EMR_SETICMPROFILEW;
}
else
{
lpName = lpFile;
}
}
else
{
return FALSE;
}
//
// We must have color profile (since this is destination color space).
//
if (dwRecordType == EMR_SETICMPROFILEW)
{
ICMMSG(("MF_SetICMProfileW():Metafiling - %ws\n",lpName));
if (*(WCHAR *)lpName == UNICODE_NULL)
{
ICMMSG(("MF_SetICMProfile() ANSI: no profile name is given\n"));
return FALSE;
}
}
else
{
ICMMSG(("MF_SetICMProfileA():Metafiling - %s\n",lpName));
if (*(char *)lpName == NULL)
{
ICMMSG(("MF_SetICMProfile() UNICODE: no profile name is given\n"));
return FALSE;
}
}
RtlZeroMemory(&MappedProfile,sizeof(CLIENT_SIDE_FILEVIEW));
if (bDownload)
{
//
// We are in profile attached mode.
//
dwFlags = SETICMPROFILE_EMBEDED;
//
// Normalize ICC profile path
//
BuildIcmProfilePath((WCHAR *)lpName, PathFileName, MAX_PATH);
//
// Check we already attached this or not.
//
if (pmdc->bExistColorProfile(PathFileName))
{
ICMMSG(("MF_SetICMProfile():Exist in metafile FileImage - %ws\n",PathFileName));
}
else
{
ICMMSG(("MF_SetICMProfile():Attaching in metafile FileImage - %ws\n",PathFileName));
if (pColorSpace && (pColorSpace->ColorProfile.dwType == PROFILE_MEMBUFFER))
{
lpData = (PBYTE)(pColorSpace->ColorProfile.pProfileData);
dwDataLength = pColorSpace->ColorProfile.cbDataSize;
}
else
{
if (!bMapFileUNICODEClideSide(PathFileName,&MappedProfile,FALSE))
{
return FALSE;
}
lpData = (PBYTE) MappedProfile.pvView;
dwDataLength = MappedProfile.cjView;
}
// Mark we attach this profile into metafile
//
pmdc->vInsertColorProfile((WCHAR *)PathFileName);
}
// WINBUG 365045 4-10-2001 pravins Possible work item in MF_SetICMProfile
//
// Old Comment:
// [THIS PART NEED TO BE RE-CONSIDERRED]
//
// Only record filename, not full path. (when we attach profile)
//
lpName = (LPBYTE) GetFileNameFromPath((WCHAR *)PathFileName);
}
if (dwRecordType == EMR_SETICMPROFILEA)
{
//
// Compute the data length (string is ansi)
//
dwNameLength = strlen((CHAR *)lpName) + 1;
}
else
{
//
// Compute the data length (string is unicode)
//
dwNameLength = (wcslen((WCHAR *)lpName) + 1) * sizeof(WCHAR);
}
pmsip = (PMRSETICMPROFILE)pmdc->pvNewRecord(SIZEOF_MRSETICMPROFILE(dwNameLength+dwDataLength));
if (pmsip == NULL)
{
bRet = FALSE;
}
else
{
pmsip->vInit(dwRecordType,dwFlags,dwNameLength,lpName,dwDataLength,lpData);
pmsip->vCommit(pmdc);
}
if (MappedProfile.hSection)
{
vUnmapFileClideSide(&MappedProfile);
}
return bRet;
}
extern "C" BOOL APIENTRY MF_ColorMatchToTarget(HDC hdc, DWORD dwAction, PVOID pvColorSpace, DWORD dwRecordType)
{
BOOL bRet = TRUE;
PMRCOLORMATCHTOTARGET pmcmt;
WCHAR PathFileName[MAX_PATH+1];
PCACHED_COLORSPACE pColorSpace = (PCACHED_COLORSPACE) pvColorSpace;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PUTS("MF_ColorMatchToTarget\n");
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc, "no pmdc\n");
ASSERTGDI(dwRecordType == EMR_COLORMATCHTOTARGETW, "Invalid Record Type\n");
DWORD dwFlags = 0;
DWORD dwNameLength = 0;
DWORD dwDataLength = 0;
LPBYTE lpName = NULL;
LPBYTE lpData = NULL;
CLIENT_SIDE_FILEVIEW MappedProfile;
RtlZeroMemory(&MappedProfile,sizeof(CLIENT_SIDE_FILEVIEW));
if (dwAction == CS_ENABLE)
{
//
// Get profile name from CACHED_COLORSPACE.
//
lpName = (PBYTE)&(pColorSpace->LogColorSpace.lcsFilename[0]);
//
// We must have color profile (since this is target color space).
//
if (*(WCHAR *)lpName == UNICODE_NULL)
{
ICMMSG(("MF_ColorMatchToTarget():no profile name in LOGCOLORSPACE\n"));
return FALSE;
}
ICMMSG(("MF_ColorMatchToTarget():Metafiling - %ws\n",lpName));
#if DBG
if ((pldc->fl & LDC_DOWNLOAD_PROFILES) || (DbgIcm & DBG_ICM_METAFILE))
#else
if (pldc->fl & LDC_DOWNLOAD_PROFILES)
#endif
{
//
// We are in profile attached mode.
//
dwFlags = COLORMATCHTOTARGET_EMBEDED;
//
// Normalize ICC profile path
//
BuildIcmProfilePath((WCHAR *)lpName, PathFileName, MAX_PATH);
//
// Check we already attached this or not.
//
if (pmdc->bExistColorProfile((WCHAR *)PathFileName))
{
ICMMSG(("MF_ColorMatchToTarget():Exist in metafile FileImage - %ws\n",PathFileName));
}
else
{
ICMMSG(("MF_ColorMatchToTarget():Attaching in metafile FileImage - %ws\n",PathFileName));
if (pColorSpace->ColorProfile.dwType == PROFILE_MEMBUFFER)
{
lpData = (PBYTE)(pColorSpace->ColorProfile.pProfileData);
dwDataLength = pColorSpace->ColorProfile.cbDataSize;
}
else
{
if (!bMapFileUNICODEClideSide(PathFileName,&MappedProfile,FALSE))
{
return FALSE;
}
lpData = (PBYTE) MappedProfile.pvView;
dwDataLength = MappedProfile.cjView;
}
// Mark we attach this profile into metafile
//
pmdc->vInsertColorProfile((WCHAR *)PathFileName);
}
// WINBUG 365045 4-10-2001 pravins Possible work item in MF_SetICMProfile
//
// Old Comment:
// [THIS PART NEED TO BE RE-CONSIDERRED]
//
// Only record filename, not full path. (when we attach profile)
//
lpName = (LPBYTE) GetFileNameFromPath((WCHAR *)PathFileName);
}
//
// Compute the data length (string is unicode)
//
dwNameLength = (wcslen((WCHAR *)lpName) + 1) * sizeof(WCHAR);
}
else
{
ICMMSG(("MF_ColorMatchToTarget():Metafiling - %d",dwAction));
}
pmcmt = (PMRCOLORMATCHTOTARGET)pmdc->pvNewRecord(SIZEOF_MRCOLORMATCHTOTARGET(dwNameLength+dwDataLength));
if (pmcmt == NULL)
{
bRet = FALSE;
}
else
{
pmcmt->vInit(dwRecordType,dwAction,dwFlags,dwNameLength,lpName,dwDataLength,lpData);
pmcmt->vCommit(pmdc);
}
if (MappedProfile.hSection)
{
vUnmapFileClideSide(&MappedProfile);
}
return bRet;
}
extern "C" BOOL APIENTRY MF_CreateColorSpaceA(PMDC pmdc, HGDIOBJ hobj, DWORD imhe)
{
BOOL bRet = TRUE;
PMRCREATECOLORSPACE pmColorSpaceA;
PUTS("MF_CreateColorSpaceA\n");
LOGCOLORSPACEA LogColorSpaceA;
if (!GetLogColorSpaceA((HCOLORSPACE)hobj,&LogColorSpaceA,sizeof(LOGCOLORSPACEA)))
{
ICMMSG(("MF_CreateColorSpaceA():Failed on GetLogColorSpaceW()\n"));
return FALSE;
}
#if DBG
if (LogColorSpaceA.lcsFilename[0] != NULL)
{
ICMMSG(("MF_CreateColorSpaceA():Metafiling - %s\n",LogColorSpaceA.lcsFilename));
}
#endif
pmColorSpaceA = (PMRCREATECOLORSPACE) pmdc->pvNewRecord(SIZEOF_MRCREATECOLORSPACE);
if (pmColorSpaceA == NULL)
{
bRet = FALSE;
}
else
{
pmColorSpaceA->vInit((ULONG)imhe,LogColorSpaceA);
pmColorSpaceA->vCommit(pmdc);
}
return bRet;
}
extern "C" BOOL APIENTRY MF_CreateColorSpaceW(
PMDC pmdc, PLOGCOLORSPACEEXW pLogColorSpaceExW, DWORD imhe, BOOL bDownload)
{
BOOL bRet = TRUE;
PMRCREATECOLORSPACEW pmColorSpaceW;
WCHAR PathFileName[MAX_PATH];
PUTS("MF_CreateColorSpaceW\n");
DWORD dwFlags = 0;
DWORD dwDataLength = 0;
LPBYTE lpData = NULL;
CLIENT_SIDE_FILEVIEW MappedProfile;
RtlZeroMemory(&MappedProfile,sizeof(CLIENT_SIDE_FILEVIEW));
//
// Check LOGCOLORSPACE has color profile.
//
if (pLogColorSpaceExW->lcsColorSpace.lcsFilename[0] != NULL)
{
ICMMSG(("MF_CreateColorSpaceW():Metafiling - %ws\n",
pLogColorSpaceExW->lcsColorSpace.lcsFilename));
}
pmColorSpaceW = (PMRCREATECOLORSPACEW)pmdc->pvNewRecord(SIZEOF_MRCREATECOLORSPACEW(dwDataLength));
if (pmColorSpaceW == NULL)
{
bRet = FALSE;
}
else
{
pmColorSpaceW->vInit((ULONG)imhe,pLogColorSpaceExW->lcsColorSpace,dwFlags,dwDataLength,lpData);
pmColorSpaceW->vCommit(pmdc);
}
return bRet;
}
extern "C" BOOL APIENTRY MF_InternalCreateColorSpace(HDC hdc,HGDIOBJ hobj,DWORD imhe)
{
BOOL bRet = TRUE;
PLDC pldc;
DC_PLDC(hdc,pldc,FALSE);
PUTS("MF_InternalCreateColorSpace\n");
PMDC pmdc = (PMDC)pldc->pvPMDC;
ASSERTGDI(pmdc, "no pmdc\n");
LOGCOLORSPACEEXW LogColorSpaceExW;
//
// Obtain LOGCOLORSPACEEX from handle.
//
if (!NtGdiExtGetObjectW((HCOLORSPACE)hobj,sizeof(LOGCOLORSPACEEXW),&LogColorSpaceExW))
{
ICMMSG(("MF_InternalCreateColorSpace():Failed on NtGdiExtGetObject()\n"));
return (FALSE);
}
#if DBG
BOOL bDownload = ((pldc->fl & LDC_DOWNLOAD_PROFILES) || (DbgIcm & DBG_ICM_METAFILE));
#else
BOOL bDownload = (pldc->fl & LDC_DOWNLOAD_PROFILES);
#endif
ICMMSG(("MF_InternalCreateColorSpace():dwFlags = %x, bDownload = %d\n",
LogColorSpaceExW.dwFlags,bDownload));
//
// If we are EMF spooling (profile attach case), or color space is created by CreateColorSpaceW(),
// use Unicode version of record to keep in metafile.
//
if ((LogColorSpaceExW.dwFlags & LCSEX_ANSICREATED) && (!bDownload))
{
//
// Create Win9x compatible ANSI record.
//
bRet = MF_CreateColorSpaceA(pmdc,hobj,imhe);
}
else
{
//
// Create Unicode record.
//
bRet = MF_CreateColorSpaceW(pmdc,&LogColorSpaceExW,imhe,bDownload);
}
return bRet;
}