Microsoft-3D-Movie-Maker/kauai/SRC/PICWIN.CPP

278 lines
6.2 KiB
C++

/* Copyright (c) Microsoft Corporation.
Licensed under the MIT License. */
/***************************************************************************
Author: ShonK
Project: Kauai
Reviewed:
Copyright (c) Microsoft Corporation
Windows specific picture (metafile) routines.
***************************************************************************/
#include "frame.h"
ASSERTNAME
/***************************************************************************
Constructor for a picture.
***************************************************************************/
PIC::PIC(void)
{
_hpic = hNil;
_rc.Zero();
}
/***************************************************************************
Destructor for a picture.
***************************************************************************/
PIC::~PIC(void)
{
AssertBaseThis(0);
if (hNil != _hpic)
DeleteEnhMetaFile(_hpic);
}
/***************************************************************************
Read a picture from a chunky file. This routine only reads or converts
OS specific representations with the given chid value.
***************************************************************************/
PPIC PIC::PpicFetch(PCFL pcfl, CTG ctg, CNO cno, CHID chid)
{
AssertPo(pcfl, 0);
BLCK blck;
KID kid;
if (!pcfl->FFind(ctg, cno))
return pvNil;
if (pcfl->FGetKidChidCtg(ctg, cno, chid, kctgMeta, &kid) &&
pcfl->FFind(kid.cki.ctg, kid.cki.cno, &blck))
{
return PpicRead(&blck);
}
//REVIEW shonk: convert another type to a MetaFile...
return pvNil;
}
/***************************************************************************
Read a picture from a chunky file. This routine only reads a system
specific pict (Mac PICT or Windows MetaFile) and its header.
***************************************************************************/
PPIC PIC::PpicRead(PBLCK pblck)
{
AssertPo(pblck, fblckReadable);
HPIC hpic;
HQ hq;
PICH *ppich;
PPIC ppic;
RC rc;
long cb;
if (!pblck->FUnpackData())
return pvNil;
cb = pblck->Cb();
if (cb <= size(PICH))
return pvNil;
if (hqNil == (hq = pblck->HqFree()))
return pvNil;
ppich = (PICH *)PvLockHq(hq);
rc = ppich->rc;
if (rc.FEmpty() || ppich->cb != cb)
hpic = hNil;
else
hpic = SetEnhMetaFileBits(cb - size(PICH), (byte *)(ppich + 1));
UnlockHq(hq);
FreePhq(&hq);
if (hNil == hpic)
return pvNil;
if (pvNil == (ppic = NewObj PIC))
{
DeleteEnhMetaFile(hpic);
return pvNil;
}
ppic->_hpic = hpic;
ppic->_rc = rc;
AssertPo(ppic, 0);
return ppic;
}
/***************************************************************************
Return the total size on file.
***************************************************************************/
long PIC::CbOnFile(void)
{
AssertThis(0);
return GetEnhMetaFileBits(_hpic, 0, pvNil) + size(PICH);
}
/***************************************************************************
Write the meta file (and its header) to the given BLCK.
***************************************************************************/
bool PIC::FWrite(PBLCK pblck)
{
AssertThis(0);
AssertPo(pblck, 0);
long cb, cbTot;
bool fT;
PICH *ppich;
cb = GetEnhMetaFileBits(_hpic, 0, pvNil);
if (cb == 0 || (cbTot = cb + size(PICH)) != pblck->Cb())
return fFalse;
if (!FAllocPv((void **)&ppich, cbTot, fmemNil, mprNormal))
return fFalse;
ppich->rc = _rc;
ppich->cb = cbTot;
fT = (GetEnhMetaFileBits(_hpic, cb, (byte *)(ppich + 1)) == (ulong)cb) &&
pblck->FWrite(ppich);
FreePpv((void **)&ppich);
return fT;
}
/***************************************************************************
Static method to read the file as a native picture (EMF or WMF file).
***************************************************************************/
PPIC PIC::PpicReadNative(FNI *pfni)
{
AssertPo(pfni, ffniFile);
HPIC hpic;
PPIC ppic;
RC rc;
ENHMETAHEADER emh;
STN stn;
switch (pfni->Ftg())
{
default:
return pvNil;
case kftgMeta:
hpic = _HpicReadWmf(pfni);
break;
case kftgEnhMeta:
pfni->GetStnPath(&stn);
hpic = GetEnhMetaFile(stn.Psz());
break;
}
if (hNil == hpic)
return pvNil;
if (pvNil == (ppic = NewObj PIC))
{
DeleteEnhMetaFile(hpic);
return pvNil;
}
GetEnhMetaFileHeader(hpic, size(emh), &emh);
rc.Set(
LwMulDiv(emh.rclFrame.left, 72, 2540),
LwMulDiv(emh.rclFrame.top, 72, 2540),
LwMulDiv(emh.rclFrame.right, 72, 2540),
LwMulDiv(emh.rclFrame.bottom, 72, 2540));
ppic->_hpic = hpic;
ppic->_rc = rc;
AssertPo(ppic, 0);
return ppic;
}
/* placeable metafile data definitions */
#define lwMEFH 0x9AC6CDD7
/* placeable metafile header */
typedef struct _MEFH
{
DWORD lwKey;
short w1;
short xpLeft;
short ypTop;
short xpRight;
short ypBottom;
WORD w2;
DWORD dw1;
WORD w3;
} MEFH;
/***************************************************************************
Static method to read an old style WMF file.
***************************************************************************/
HPIC PIC::_HpicReadWmf(FNI *pfni)
{
MEFH mefh;
METAHEADER mh;
HPIC hpic;
long lw;
long cb;
PFIL pfil;
void *pv;
bool fT;
FP fp;
const long kcbMefh = 22;
const long kcbMetaHeader = 18;
if (pvNil == (pfil = FIL::PfilOpen(pfni)))
return hNil;
// check for type of meta file
if (!pfil->FReadRgb(&lw, size(long), 0))
goto LFail;
// read placeable meta file header - NOTE: we can't just use size(MEFH) for
// the cb because the MEFH is padded to a long boundary by the compiler
fp = 0;
if (lw == lwMEFH && !pfil->FReadRgbSeq(&mefh, kcbMefh, &fp))
goto LFail;
// read METAHEADER structure - NOTE: we can't just use size(METAHEADER) for
// the cb because the METAHEADER is padded to a long boundary by the
// compiler
if (!pfil->FReadRgbSeq(&mh, kcbMetaHeader, &fp) || mh.mtVersion < 0x0300 ||
2 * mh.mtHeaderSize != kcbMetaHeader ||
!FIn(cb = 2 * mh.mtSize, kcbMetaHeader + 1, kcbMax))
{
goto LFail;
}
if (!FAllocPv(&pv, cb, fmemNil, mprNormal))
{
LFail:
ReleasePpo(&pfil);
return hNil;
}
*(METAHEADER *)pv = mh;
fT = pfil->FReadRgbSeq(PvAddBv(pv, kcbMetaHeader), cb - kcbMetaHeader, &fp);
ReleasePpo(&pfil);
if (!fT)
{
FreePpv(&pv);
return hNil;
}
//convert the old style metafile to an enhanced metafile
hpic = SetWinMetaFileBits(cb, (byte *)pv, hNil, pvNil);
FreePpv(&pv);
return hpic;
}