278 lines
6.2 KiB
C++
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;
|
|
}
|