📄 rtfwrit2.cpp
字号:
// Get total size of 2bpp dib, (including header and 4 color color-table).
cbResult = sizeof(bmi2bpp) + nBytes;
// Don't change the input pbResult as that is the internal representation of
// the dib. This conversion to 2bpp is only for writing to the output file.
if((hMem2bpp = GlobalAlloc(GMEM_FIXED, cbResult)))
{
if((pbResult = (LPBYTE)GlobalLock(hMem2bpp)))
{
// Copy in the dib header.
memcpy(pbResult, &bmi2bpp.bmih, sizeof(BITMAPINFOHEADER));
// Copy in the 4 color color-table.
memcpy(&pbResult[sizeof(BITMAPINFOHEADER)], (RGBQUAD*)ColorTable2bpp, (1<<PWDV1_BPP) * sizeof(RGBQUAD));
// Now copy in the byte array.
memcpy(&pbResult[sizeof(bmi2bpp)], pbDibDst, nBytes);
_ecParseError = ecNoError;
}
}
DeleteObject(hdibDst);
}
DeleteDC(hdcDst);
DeleteObject(hdibSrc);
}
DeleteDC(hdcSrc);
ReleaseDC(hWnd, hdc);
if(_ecParseError != ecNoError)
{
goto CleanUp;
}
}
}
#endif // CONVERT2BPP
// ************** V-GUYB: End of conversion stuff.
// Start and write picture group
PutCtrlWord( CWF_GRP, i_pict );
// Write that this is dib
PutCtrlWord( CWF_VAL, i_dibitmap,rtfObject.sPictureType );
// V-GUYB:
// rtfObject.*Scale is not updated as the user stretches the picture,
// so don't use those here. But rtfObject.*Ext has been set up in the
// calling routine to account for the current site dimensions.
PutCtrlWord( CWF_VAL, i_picscalex, ((rtfObject.xExt * 100) + (rtfObject.xExtGoal / 2)) / rtfObject.xExtGoal);
PutCtrlWord( CWF_VAL, i_picscaley, ((rtfObject.yExt * 100) + (rtfObject.yExtGoal / 2)) / rtfObject.yExtGoal);
// Write picture render details
PutCtrlWord( CWF_VAL, i_picw, pbmi->bmiHeader.biWidth );
PutCtrlWord( CWF_VAL, i_pich, pbmi->bmiHeader.biHeight );
PutCtrlWord( CWF_VAL, i_picwgoal, rtfObject.xExtGoal );
PutCtrlWord( CWF_VAL, i_pichgoal, rtfObject.yExtGoal );
PutCtrlWord( CWF_VAL, i_wbmbitspixel, pbmi->bmiHeader.biBitCount );
PutCtrlWord( CWF_VAL, i_wbmplanes, pbmi->bmiHeader.biPlanes );
PutCtrlWord( CWF_VAL, i_wbmwidthbytes, rtfObject.cBytesPerLine );
// Write out the data
PutCtrlWord( CWF_VAL, i_bin, cbResult );
if ((UINT) WriteBinData( pbResult, cbResult ) != cbResult)
{
// This "recovery" action needs to be rethought. There is no way
// the reader will be able to get back in synch.
goto CleanUp;
}
_ecParseError = ecNoError;
CleanUp:
// Did we lock or allocate some temporary space for a 2bpp dib?
if(rtfObject.pbResult != pbResult)
{
// Yes, so unlock it now.
GlobalUnlock(pbResult);
}
if(hMem2bpp)
{
GlobalFree(hMem2bpp);
}
// Restore original values.
rtfObject.pbResult = pbResult;
rtfObject.cbResult = cbResult;
PutChar(chEndGroup); // End picture data
leave:
return _ecParseError;
}
/*
* CRTFWrite::WriteObject(LONG cp)
*
* Purpose:
* Writes out an object's header as well as the object's data.
*
* Arguments:
* cp The object position
*
* Returns:
* EC The error code
*/
EC CRTFWrite::WriteObject(LONG cp, COleObject *pobj)
{
TRACEBEGIN(TRCSUBSYSRTFW, TRCSCOPEINTERN, "CRTFWrite::WriteObject");
RTFOBJECT rtfObject;
REOBJECT reObject = { 0} ;
Assert(pobj);
reObject.cbStruct = sizeof (REOBJECT) ;
reObject.cp = cp;
if (FAILED(pobj->GetObjectData(&reObject, REO_GETOBJ_POLESITE
| REO_GETOBJ_PSTG | REO_GETOBJ_POLEOBJ))) // todo fix Release
{
TRACEERRORSZ("Error geting object ");
}
GetRtfObject(reObject, rtfObject);
HGLOBAL hdata = pobj->GetHdata();
if (hdata)
{
COleObject::ImageInfo *pimageinfo = pobj->GetImageInfo();
rtfObject.pbResult = (LPBYTE) GlobalLock( hdata );
rtfObject.cbResult = GlobalSize( hdata );
rtfObject.sType = ROT_DIB;
rtfObject.xExt = (SHORT) TwipsFromHimetric( reObject.sizel.cx );
rtfObject.yExt = (SHORT) TwipsFromHimetric( reObject.sizel.cy );
rtfObject.xScale = pimageinfo->xScale;
rtfObject.yScale = pimageinfo->yScale;
rtfObject.xExtGoal = pimageinfo->xExtGoal;
rtfObject.yExtGoal = pimageinfo->yExtGoal;
rtfObject.cBytesPerLine = pimageinfo->cBytesPerLine;
WriteDib( reObject, rtfObject );
GlobalUnlock( rtfObject.pbResult );
// Make sure to release otherwise the object won't go away
if (reObject.pstg) reObject.pstg->Release();
if (reObject.polesite) reObject.polesite->Release();
if (reObject.poleobj) reObject.poleobj->Release();
return _ecParseError;
}
switch(rtfObject.sType) // Handle pictures in our own
{ // special way
case ROT_Embedded:
case ROT_Link:
case ROT_AutoLink:
break;
case ROT_Metafile:
case ROT_DIB:
case ROT_Bitmap:
WritePicture( reObject, rtfObject );
goto CleanUpNoEndGroup;
#ifdef DEBUG
default:
AssertSz(FALSE, "CRTFW::WriteObject: Unknown ROT");
break;
#endif DEBUG
}
// Start and write object group
PutCtrlWord( CWF_GRP, i_object );
PutCtrlWord( CWF_STR, IndexROT[rtfObject.sType] );
// PutCtrlWord(CWF_STR, i_objupdate); // TODO may be it needs more smart decision
if (rtfObject.szClass) // Write object class
{
PutCtrlWord( CWF_AST, i_objclass );
WritePcData( rtfObject.szClass );
PutChar( chEndGroup );
}
if (rtfObject.szName) // Write object name
{
PutCtrlWord( CWF_AST, i_objname );
WritePcData( rtfObject.szName );
PutChar( chEndGroup );
}
if (rtfObject.fSetSize) // Write object sizing
{ // options
PutCtrlWord( CWF_STR, i_objsetsize );
}
WriteRtfObject( rtfObject, FALSE ) ; // Write object render info
PutCtrlWord( CWF_AST, i_objdata ) ; // info, start object
Puts( szLineBreak, sizeof(szLineBreak) - 1); // data group
if (!ObjectWriteToEditstream( reObject, rtfObject ))
{
TRACEERRORSZ("Error writing object data");
if (!_ecParseError)
_ecParseError = ecStreamOutObj;
PutChar( chEndGroup ); // End object data
goto CleanUp;
}
PutChar( chEndGroup ); // End object data
PutCtrlWord( CWF_GRP, i_result ); // Start results group
WritePicture( reObject,rtfObject ); // Write results group
PutChar( chEndGroup ); // End results group
CleanUp:
PutChar( chEndGroup ); // End object group
CleanUpNoEndGroup:
if (reObject.pstg) reObject.pstg->Release();
if (reObject.polesite) reObject.polesite->Release();
if (reObject.poleobj) reObject.poleobj->Release();
if (rtfObject.pbResult)
{
HGLOBAL hmem;
hmem = GlobalHandle( rtfObject.pbResult );
GlobalUnlock( hmem );
GlobalFree( hmem );
}
if (rtfObject.szClass)
{
pCoTaskMemFree( rtfObject.szClass );
}
return _ecParseError;
}
/*
* GetRtfObjectMetafilePict
*
* @mfunc
* Gets information about an metafile into a structure.
*
* Arguments:
* HGLOBAL The object data
* RTFOBJECT Where to put the information.
*
* @rdesc
* BOOL TRUE on success, FALSE if object cannot be written to RTF.
*/
BOOL CRTFWrite::GetRtfObjectMetafilePict(HGLOBAL hmfp, RTFOBJECT &rtfobject, SIZEL &sizelGoal)
{
#ifndef NOMETAFILES
BOOL fSuccess = FALSE;
LPMETAFILEPICT pmfp = (LPMETAFILEPICT)GlobalLock(hmfp);
HGLOBAL hmem = NULL;
ULONG cb;
if (!pmfp)
goto Cleanup;
// Build the header
rtfobject.sPictureType = (SHORT) pmfp->mm;
rtfobject.xExtPict = (SHORT) pmfp->xExt;
rtfobject.yExtPict = (SHORT) pmfp->yExt;
rtfobject.xExtGoal = TwipsFromHimetric(sizelGoal.cx);
rtfobject.yExtGoal = TwipsFromHimetric(sizelGoal.cy);
// Find out how much room we'll need
cb = GetMetaFileBitsEx(pmfp->hMF, 0, NULL);
if (!cb)
goto Cleanup;
// Allocate that space
hmem = GlobalAlloc(GHND, cb);
if (!hmem)
goto Cleanup;
rtfobject.pbResult = (LPBYTE)GlobalLock(hmem);
if (!rtfobject.pbResult)
{
GlobalFree(hmem);
goto Cleanup;
}
// Get the data
rtfobject.cbResult = (ULONG) GetMetaFileBitsEx(pmfp->hMF, (UINT) cb,
rtfobject.pbResult);
if (rtfobject.cbResult != cb)
{
rtfobject.pbResult = NULL;
GlobalFree(hmem);
goto Cleanup;
}
fSuccess = TRUE;
Cleanup:
GlobalUnlock(hmfp);
return fSuccess;
#else
return FALSE;
#endif
}
/*
* GetRtfObject (REOBJECT &reobject, RTFOBJECT &rtfobject)
*
* Purpose:
* Gets information about an RTF object into a structure.
*
* Arguments:
* REOBJECT Information from GetObject
* RTFOBJECT Where to put the information. Strings are read only and
* are owned by the object subsystem, not the caller.
*
* Returns:
* BOOL TRUE on success, FALSE if object cannot be written to RTF.
*/
BOOL CRTFWrite::GetRtfObject(REOBJECT &reobject, RTFOBJECT &rtfobject)
{
BOOL fSuccess = FALSE;
const BOOL fStatic = !!(reobject.dwFlags & REO_STATIC);
SIZEL sizelObj = reobject.sizel;
//COMPATIBILITY: RICHED10 code had a frame size. Do we need something similiar.
LPTSTR szProgId;
// Blank out the full structure
ZeroMemory(&rtfobject, sizeof(RTFOBJECT));
// If the object has no storage it cannot be written.
if (!reobject.pstg)
return FALSE;
// If we don't have the progID for a real OLE object, get it now
if (!fStatic )
{
rtfobject.szClass = NULL;
// We need a ProgID to put into the RTF stream.
//$ REVIEW: MAC This call is incorrect for the Mac. It may not matter though
// if ole support in RichEdit is not needed for the Mac.
if (FAILED(pProgIDFromCLSID(reobject.clsid, &szProgId)))
return FALSE;
rtfobject.szClass = szProgId;
}
#ifndef NOMETAFILES
HGLOBAL hmfp = NULL;
hmfp = OleStdGetMetafilePictFromOleObject(reobject.poleobj,
reobject.dvaspect, &sizelObj,
NULL);
if (hmfp)
{
LPMETAFILEPICT pmfp = NULL;
fSuccess = GetRtfObjectMetafilePict(hmfp, rtfobject, sizelObj);
if (pmfp = (LPMETAFILEPICT)GlobalLock(hmfp))
{
if (pmfp->hMF)
DeleteMetaFile(pmfp->hMF);
GlobalUnlock(hmfp);
}
GlobalFree(hmfp);
}
#endif
if (!fStatic)
{
// Fill in specific fields
rtfobject.sType = ROT_Embedded; //$ FUTURE: set for links
rtfobject.xExt = (SHORT) TwipsFromHimetric(sizelObj.cx);
rtfobject.yExt = (SHORT) TwipsFromHimetric(sizelObj.cy);
// fSuccess set even if we couldn't retreive a metafile
// because we don't need a metafile in the non-static case,
// it's just nice to have one
fSuccess = TRUE;
}
rtfobject.fSetSize = 0; //$ REVIEW: Hmmm
return fSuccess;
}
/*
* ObjectWriteToEditstream
*
* Purpose:
* Writes an OLE object data to the RTF output stream.
*
* Arguments:
* REOBJECT Information from GetObject
* RTFOBJECT Where to get icon data.
*
* Returns:
* BOOL TRUE on success, FALSE on failure.
*/
BOOL CRTFWrite::ObjectWriteToEditstream(REOBJECT &reObject, RTFOBJECT &rtfobject)
{
HRESULT hr = 0;
// Force the object to update its storage //// ????
reObject.polesite->SaveObject();
// If the object is iconic we do some special magic
if (reObject.dvaspect == DVASPECT_ICON)
{
HANDLE hGlobal;
STGMEDIUM med;
// Force the presentation to be the iconic view.
med.tymed = TYMED_HGLOBAL;
hGlobal = GlobalHandle(rtfobject.pbResult);
med.hGlobal = hGlobal;
hr = pOleConvertIStorageToOLESTREAMEx(reObject.pstg,
CF_METAFILEPICT,
rtfobject.xExtPict,
rtfobject.yExtPict,
rtfobject.cbResult, &med,
(LPOLESTREAM) &RTFWriteOLEStream);
}
else
{
// Do the standard conversion
hr = pOleConvertIStorageToOLESTREAM(reObject.pstg, (LPOLESTREAM) &RTFWriteOLEStream);
}
return SUCCEEDED(hr);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -