518 lines
13 KiB
C
518 lines
13 KiB
C
|
/****************************** Module Header ******************************\
|
||
|
* Module Name: DIB.C
|
||
|
*
|
||
|
* Handles all API routines for the device independent bitmap sub-dll of
|
||
|
* the ole dll.
|
||
|
*
|
||
|
* Created: Oct-1990
|
||
|
*
|
||
|
* Copyright (c) 1990, 1991 Microsoft Corporation
|
||
|
*
|
||
|
* History:
|
||
|
* Srinik, Raor (../../1990,91) Designed, coded
|
||
|
* curts created portable version for win16/32
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include "dll.h"
|
||
|
#include "pict.h"
|
||
|
|
||
|
void FARINTERNAL DibGetExtents (LPSTR, LPPOINT);
|
||
|
|
||
|
#ifdef WIN16
|
||
|
#pragma alloc_text(_TEXT, DibSaveToStream, DibLoadFromStream, DibStreamRead, GetBytes, PutBytes, PutStrWithLen, DibGetExtents)
|
||
|
#endif
|
||
|
|
||
|
OLEOBJECTVTBL vtblDIB = {
|
||
|
|
||
|
ErrQueryProtocol, // check whether the speced protocol is supported
|
||
|
|
||
|
DibRelease, // Release
|
||
|
ErrShow, // Show
|
||
|
ErrPlay, // show
|
||
|
DibGetData, // Get the object data
|
||
|
ErrSetData, // Set the object data
|
||
|
ErrSetTargetDevice, //
|
||
|
|
||
|
ErrSetBounds, // set viewport bounds
|
||
|
DibEnumFormat, // enumerate supported formats
|
||
|
ErrSetColorScheme, //
|
||
|
DibRelease, // delete
|
||
|
ErrSetHostNames, //
|
||
|
|
||
|
DibSaveToStream, // write to file
|
||
|
DibClone, // clone object
|
||
|
ErrCopyFromLink, // Create embedded from Lnk
|
||
|
|
||
|
DibEqual, // compares the given objects for data equality
|
||
|
|
||
|
DibCopy, // copy to clip
|
||
|
|
||
|
DibDraw, // draw the object
|
||
|
|
||
|
ErrActivate, // open
|
||
|
ErrExecute, // excute
|
||
|
ErrClose, // Stop
|
||
|
ErrUpdate, // Update
|
||
|
ErrReconnect, // Reconnect
|
||
|
|
||
|
ErrObjectConvert, // convert object to specified type
|
||
|
|
||
|
ErrGetUpdateOptions, // update options
|
||
|
ErrSetUpdateOptions, // update options
|
||
|
|
||
|
ObjRename, // Change Object name
|
||
|
ObjQueryName, // Get current object name
|
||
|
|
||
|
ObjQueryType, // Object type
|
||
|
DibQueryBounds, // QueryBounds
|
||
|
ObjQuerySize, // Find the size of the object
|
||
|
ErrQueryOpen, // Query open
|
||
|
ErrQueryOutOfDate, // query whether object is current
|
||
|
|
||
|
ErrQueryRelease, // release related stuff
|
||
|
ErrQueryRelease,
|
||
|
ErrQueryReleaseMethod,
|
||
|
|
||
|
ErrRequestData, // requestdata
|
||
|
ErrObjectLong, // objectLong
|
||
|
DibChangeData // change data of the existing object
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
OLESTATUS FARINTERNAL DibRelease (LPOLEOBJECT lpoleobj)
|
||
|
{
|
||
|
LPOBJECT_DIB lpobj = (LPOBJECT_DIB)lpoleobj;
|
||
|
HOBJECT hobj;
|
||
|
|
||
|
if (lpobj->hDIB){
|
||
|
GlobalFree (lpobj->hDIB);
|
||
|
lpobj->hDIB = NULL;
|
||
|
}
|
||
|
|
||
|
if (lpobj->head.lhclientdoc)
|
||
|
DocDeleteObject ((LPOLEOBJECT) lpobj);
|
||
|
|
||
|
if (hobj = lpobj->head.hobj){
|
||
|
lpobj->head.hobj = NULL;
|
||
|
GlobalUnlock (hobj);
|
||
|
GlobalFree (hobj);
|
||
|
}
|
||
|
|
||
|
return OLE_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
OLESTATUS FARINTERNAL DibSaveToStream (
|
||
|
LPOLEOBJECT lpoleobj,
|
||
|
LPOLESTREAM lpstream
|
||
|
){
|
||
|
DWORD dwFileVer = GetFileVersion(lpoleobj);
|
||
|
LPOBJECT_DIB lpobj = (LPOBJECT_DIB)lpoleobj;
|
||
|
LPSTR lpDIBbuf;
|
||
|
|
||
|
if (!lpobj->hDIB)
|
||
|
return OLE_ERROR_BLANK;
|
||
|
|
||
|
if (PutBytes (lpstream, (LPSTR) &dwFileVer, sizeof(LONG)))
|
||
|
return OLE_ERROR_STREAM;
|
||
|
|
||
|
if (PutBytes (lpstream, (LPSTR) &lpobj->head.ctype, sizeof(LONG)))
|
||
|
return OLE_ERROR_STREAM;
|
||
|
|
||
|
if (PutStrWithLen (lpstream, (LPSTR)"DIB"))
|
||
|
return OLE_ERROR_STREAM;
|
||
|
|
||
|
if (PutBytes (lpstream, (LPSTR) &lpobj->head.cx, sizeof(LONG)))
|
||
|
return OLE_ERROR_STREAM;
|
||
|
|
||
|
if (PutBytes (lpstream, (LPSTR) &lpobj->head.cy, sizeof(LONG)))
|
||
|
return OLE_ERROR_STREAM;
|
||
|
|
||
|
lpobj->sizeBytes = (DWORD)GlobalSize (lpobj->hDIB);
|
||
|
if (PutBytes (lpstream, (LPSTR) &lpobj->sizeBytes, sizeof(LONG)))
|
||
|
return OLE_ERROR_STREAM;
|
||
|
|
||
|
if (!(lpDIBbuf = GlobalLock (lpobj->hDIB)))
|
||
|
return OLE_ERROR_MEMORY;
|
||
|
|
||
|
if (PutBytes (lpstream, lpDIBbuf, lpobj->sizeBytes))
|
||
|
return OLE_ERROR_STREAM;
|
||
|
|
||
|
GlobalUnlock (lpobj->hDIB);
|
||
|
return OLE_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
OLESTATUS FARINTERNAL DibClone (
|
||
|
LPOLEOBJECT lpoleobjsrc,
|
||
|
LPOLECLIENT lpclient,
|
||
|
LHCLIENTDOC lhclientdoc,
|
||
|
OLE_LPCSTR lpobjname,
|
||
|
LPOLEOBJECT FAR * lplpoleobj
|
||
|
){
|
||
|
LPOBJECT_DIB lpobjsrc = (LPOBJECT_DIB)lpoleobjsrc;
|
||
|
|
||
|
if (!CheckClientDoc ((LPCLIENTDOC) lhclientdoc))
|
||
|
return OLE_ERROR_HANDLE;
|
||
|
|
||
|
if (!(*lplpoleobj = (LPOLEOBJECT)DibCreateObject (lpobjsrc->hDIB, lpclient,
|
||
|
FALSE, lhclientdoc, (LPSTR)lpobjname,
|
||
|
lpobjsrc->head.ctype)))
|
||
|
return OLE_ERROR_MEMORY;
|
||
|
else
|
||
|
return OLE_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
OLESTATUS FARINTERNAL DibEqual (
|
||
|
LPOLEOBJECT lpoleobj1,
|
||
|
LPOLEOBJECT lpoleobj2
|
||
|
){
|
||
|
LPOBJECT_DIB lpobj1 = (LPOBJECT_DIB)lpoleobj1;
|
||
|
LPOBJECT_DIB lpobj2 = (LPOBJECT_DIB)lpoleobj2;
|
||
|
|
||
|
if (CmpGlobals (lpobj1->hDIB, lpobj1->hDIB))
|
||
|
return OLE_OK;
|
||
|
|
||
|
return OLE_ERROR_NOT_EQUAL;
|
||
|
}
|
||
|
|
||
|
|
||
|
OLESTATUS FARINTERNAL DibCopy (LPOLEOBJECT lpoleobj)
|
||
|
{
|
||
|
LPOBJECT_DIB lpobj = (LPOBJECT_DIB)lpoleobj;
|
||
|
HANDLE hDIB;
|
||
|
|
||
|
if (!lpobj->hDIB)
|
||
|
return OLE_ERROR_BLANK;
|
||
|
|
||
|
if (!(hDIB = DuplicateGlobal (lpobj->hDIB, GMEM_MOVEABLE)))
|
||
|
return OLE_ERROR_MEMORY;
|
||
|
|
||
|
SetClipboardData (CF_DIB, hDIB);
|
||
|
return OLE_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
OLESTATUS FARINTERNAL DibQueryBounds (
|
||
|
LPOLEOBJECT lpoleobj,
|
||
|
LPRECT lpRc
|
||
|
){
|
||
|
LPOBJECT_DIB lpobj = (LPOBJECT_DIB)lpoleobj;
|
||
|
|
||
|
Puts("DibQueryBounds");
|
||
|
|
||
|
if (!lpobj->hDIB)
|
||
|
return OLE_ERROR_BLANK;
|
||
|
|
||
|
lpRc->left = 0;
|
||
|
lpRc->top = 0;
|
||
|
lpRc->right = (int) lpobj->head.cx;
|
||
|
lpRc->bottom = (int) lpobj->head.cy;
|
||
|
return OLE_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
OLECLIPFORMAT FARINTERNAL DibEnumFormat (
|
||
|
LPOLEOBJECT lpoleobj,
|
||
|
OLECLIPFORMAT cfFormat
|
||
|
){
|
||
|
LPOBJECT_DIB lpobj = (LPOBJECT_DIB)lpoleobj;
|
||
|
|
||
|
if (!cfFormat)
|
||
|
return CF_DIB;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
OLESTATUS FARINTERNAL DibGetData (
|
||
|
LPOLEOBJECT lpoleobj,
|
||
|
OLECLIPFORMAT cfFormat,
|
||
|
LPHANDLE lphandle
|
||
|
){
|
||
|
LPOBJECT_DIB lpobj = (LPOBJECT_DIB)lpoleobj;
|
||
|
|
||
|
if (cfFormat != CF_DIB)
|
||
|
return OLE_ERROR_FORMAT;
|
||
|
|
||
|
if (!(*lphandle = lpobj->hDIB))
|
||
|
return OLE_ERROR_BLANK;
|
||
|
|
||
|
return OLE_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
LPOBJECT_DIB FARINTERNAL DibCreateObject (
|
||
|
HANDLE hDIB,
|
||
|
LPOLECLIENT lpclient,
|
||
|
BOOL fDelete,
|
||
|
LHCLIENTDOC lhclientdoc,
|
||
|
LPCSTR lpobjname,
|
||
|
LONG objType
|
||
|
){
|
||
|
LPOBJECT_DIB lpobj;
|
||
|
|
||
|
if (lpobj = DibCreateBlank (lhclientdoc, (LPSTR)lpobjname, objType)) {
|
||
|
if (DibChangeData ((LPOLEOBJECT)lpobj, hDIB, lpclient, fDelete) != OLE_OK) {
|
||
|
DibRelease ((LPOLEOBJECT)lpobj);
|
||
|
lpobj = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return lpobj;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// If the routine fails then the object will be left with it's old data.
|
||
|
// If fDelete is TRUE, then hNewDIB will be deleted whether the routine
|
||
|
// is successful or not.
|
||
|
|
||
|
OLESTATUS FARINTERNAL DibChangeData (
|
||
|
LPOLEOBJECT lpoleobj,
|
||
|
HANDLE hNewDIB,
|
||
|
LPOLECLIENT lpclient,
|
||
|
BOOL fDelete
|
||
|
){
|
||
|
LPOBJECT_DIB lpobj = (LPOBJECT_DIB)lpoleobj;
|
||
|
BITMAPINFOHEADER bi;
|
||
|
DWORD dwSize;
|
||
|
LPBITMAPINFOHEADER lpBi;
|
||
|
|
||
|
if (!hNewDIB)
|
||
|
return OLE_ERROR_BLANK;
|
||
|
|
||
|
lpBi = (LPBITMAPINFOHEADER) &bi;
|
||
|
if (!fDelete) {
|
||
|
if (!(hNewDIB = DuplicateGlobal (hNewDIB, GMEM_MOVEABLE)))
|
||
|
return OLE_ERROR_MEMORY;
|
||
|
}
|
||
|
else {
|
||
|
// change the ownership to yourself
|
||
|
|
||
|
HANDLE htmp;
|
||
|
|
||
|
if (!(htmp = GlobalReAlloc (hNewDIB, 0L, GMEM_MODIFY|GMEM_SHARE))) {
|
||
|
htmp = DuplicateGlobal (hNewDIB, GMEM_MOVEABLE);
|
||
|
GlobalFree (hNewDIB);
|
||
|
if (!htmp)
|
||
|
return OLE_ERROR_MEMORY;
|
||
|
}
|
||
|
|
||
|
hNewDIB = htmp;
|
||
|
}
|
||
|
|
||
|
if (!(lpBi = (LPBITMAPINFOHEADER) GlobalLock (hNewDIB))) {
|
||
|
GlobalFree (hNewDIB);
|
||
|
return OLE_ERROR_MEMORY;
|
||
|
}
|
||
|
|
||
|
dwSize = (DWORD)GlobalSize (hNewDIB);
|
||
|
if (lpobj->hDIB)
|
||
|
GlobalFree (lpobj->hDIB);
|
||
|
DibUpdateStruct (lpobj, lpclient, hNewDIB, lpBi, dwSize);
|
||
|
return OLE_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
void INTERNAL DibUpdateStruct (
|
||
|
LPOBJECT_DIB lpobj,
|
||
|
LPOLECLIENT lpclient,
|
||
|
HANDLE hDIB,
|
||
|
LPBITMAPINFOHEADER lpBi,
|
||
|
DWORD dwBytes
|
||
|
){
|
||
|
POINT point;
|
||
|
|
||
|
lpobj->head.lpclient = lpclient;
|
||
|
lpobj->sizeBytes = dwBytes;
|
||
|
|
||
|
#ifdef OLD
|
||
|
lpobj->xSize = point.x = (int) lpBi->biWidth;
|
||
|
lpobj->ySize = point.y = (int) lpBi->biHeight;
|
||
|
ConvertToHimetric (&point);
|
||
|
#else
|
||
|
DibGetExtents ((LPSTR) lpBi, &point);
|
||
|
#endif
|
||
|
|
||
|
lpobj->head.cx = (LONG) point.x;
|
||
|
lpobj->head.cy = (LONG) point.y;
|
||
|
lpobj->hDIB = hDIB;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
OLESTATUS FARINTERNAL DibLoadFromStream (
|
||
|
LPOLESTREAM lpstream,
|
||
|
LPOLECLIENT lpclient,
|
||
|
LHCLIENTDOC lhclientdoc,
|
||
|
LPSTR lpobjname,
|
||
|
LPOLEOBJECT FAR * lplpoleobject,
|
||
|
LONG objType
|
||
|
){
|
||
|
LPOBJECT_DIB lpobj = NULL;
|
||
|
|
||
|
*lplpoleobject = NULL;
|
||
|
|
||
|
if (!(lpobj = DibCreateBlank (lhclientdoc, lpobjname, objType)))
|
||
|
return OLE_ERROR_MEMORY;
|
||
|
|
||
|
lpobj->head.lpclient = lpclient;
|
||
|
if (GetBytes (lpstream, (LPSTR) &lpobj->head.cx, sizeof(LONG)))
|
||
|
goto errLoad;
|
||
|
|
||
|
if (GetBytes (lpstream, (LPSTR) &lpobj->head.cy, sizeof(LONG)))
|
||
|
goto errLoad;
|
||
|
|
||
|
if (GetBytes (lpstream, (LPSTR) &lpobj->sizeBytes, sizeof(LONG)))
|
||
|
goto errLoad;
|
||
|
|
||
|
if (DibStreamRead (lpstream, lpobj)) {
|
||
|
*lplpoleobject = (LPOLEOBJECT) lpobj;
|
||
|
return OLE_OK;
|
||
|
}
|
||
|
|
||
|
errLoad:
|
||
|
OleDelete ((LPOLEOBJECT) lpobj);
|
||
|
return OLE_ERROR_STREAM;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
LPOBJECT_DIB FARINTERNAL DibCreateBlank (
|
||
|
LHCLIENTDOC lhclientdoc,
|
||
|
LPSTR lpobjname,
|
||
|
LONG objType
|
||
|
){
|
||
|
HOBJECT hobj;
|
||
|
LPOBJECT_DIB lpobj;
|
||
|
|
||
|
if((hobj = GlobalAlloc (GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof (OBJECT_DIB)))
|
||
|
== NULL)
|
||
|
return NULL;
|
||
|
|
||
|
if (!(lpobj = (LPOBJECT_DIB) GlobalLock (hobj))){
|
||
|
GlobalFree (hobj);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
// The structure is ZERO initialized at allocation time. So only the
|
||
|
// fields that need to be filled with values other than ZEROS are
|
||
|
// initialized below
|
||
|
|
||
|
lpobj->head.objId[0] = 'L';
|
||
|
lpobj->head.objId[1] = 'E';
|
||
|
lpobj->head.mm = MM_TEXT;
|
||
|
lpobj->head.ctype = objType;
|
||
|
lpobj->head.lpvtbl = (LPOLEOBJECTVTBL)&vtblDIB;
|
||
|
lpobj->head.iTable = INVALID_INDEX;
|
||
|
lpobj->head.hobj = hobj;
|
||
|
|
||
|
if (objType == CT_STATIC)
|
||
|
DocAddObject ((LPCLIENTDOC) lhclientdoc,
|
||
|
(LPOLEOBJECT) lpobj, lpobjname);
|
||
|
|
||
|
return lpobj;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
BOOL INTERNAL DibStreamRead (
|
||
|
LPOLESTREAM lpstream,
|
||
|
LPOBJECT_DIB lpobj
|
||
|
){
|
||
|
HANDLE hDIBbuf;
|
||
|
LPSTR lpDIBbuf;
|
||
|
BOOL retVal = FALSE;
|
||
|
BITMAPINFOHEADER bi;
|
||
|
|
||
|
if (GetBytes (lpstream, (LPSTR) &bi, sizeof(bi)))
|
||
|
return FALSE;
|
||
|
|
||
|
if (hDIBbuf = GlobalAlloc (GMEM_MOVEABLE, lpobj->sizeBytes)) {
|
||
|
if (lpDIBbuf = (LPSTR)GlobalLock (hDIBbuf)){
|
||
|
*((LPBITMAPINFOHEADER) lpDIBbuf) = bi;
|
||
|
if (!GetBytes (lpstream, lpDIBbuf+sizeof(bi),
|
||
|
(lpobj->sizeBytes - sizeof(bi)))) {
|
||
|
|
||
|
lpobj->hDIB = hDIBbuf;
|
||
|
#ifdef OLD
|
||
|
//!!! this info should be part of the stream
|
||
|
if (!lpobj->head.cx) {
|
||
|
DibGetExtents ((LPSTR) lpDIBbuf, &point);
|
||
|
lpobj->head.cx = (LONG) point.x;
|
||
|
lpobj->head.cy = (LONG) point.y;
|
||
|
}
|
||
|
#endif
|
||
|
retVal = TRUE;
|
||
|
}
|
||
|
GlobalUnlock(hDIBbuf);
|
||
|
}
|
||
|
//* Hang on to the memory allocated for the DIB
|
||
|
}
|
||
|
return retVal;
|
||
|
}
|
||
|
|
||
|
|
||
|
OLESTATUS FARINTERNAL DibPaste (
|
||
|
LPOLECLIENT lpclient,
|
||
|
LHCLIENTDOC lhclientdoc,
|
||
|
LPSTR lpobjname,
|
||
|
LPOLEOBJECT FAR * lplpoleobject,
|
||
|
LONG objType
|
||
|
){
|
||
|
HANDLE hDIB;
|
||
|
|
||
|
if ((hDIB = GetClipboardData (CF_DIB)) == NULL)
|
||
|
return OLE_ERROR_MEMORY;
|
||
|
|
||
|
*lplpoleobject = (LPOLEOBJECT) DibCreateObject (hDIB, lpclient, FALSE,
|
||
|
lhclientdoc, lpobjname, objType);
|
||
|
|
||
|
return OLE_OK;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void FARINTERNAL DibGetExtents (
|
||
|
LPSTR lpData,
|
||
|
LPPOINT lpPoint
|
||
|
){
|
||
|
#define HIMET_PER_METER 100000L // number of HIMETRIC units / meter
|
||
|
|
||
|
LPBITMAPINFOHEADER lpbmi;
|
||
|
|
||
|
lpbmi = (LPBITMAPINFOHEADER)lpData;
|
||
|
|
||
|
if (!(lpbmi->biXPelsPerMeter && lpbmi->biYPelsPerMeter)) {
|
||
|
HDC hdc;
|
||
|
|
||
|
if (hdc = GetDC (NULL)){
|
||
|
lpbmi->biXPelsPerMeter = MulDiv (GetDeviceCaps (hdc, LOGPIXELSX),
|
||
|
10000, 254);
|
||
|
lpbmi->biYPelsPerMeter = MulDiv (GetDeviceCaps (hdc, LOGPIXELSY),
|
||
|
10000, 254);
|
||
|
ReleaseDC (NULL, hdc);
|
||
|
} else {
|
||
|
//1000x1000 pixel coordinate system to avoid mod by 0
|
||
|
lpbmi->biXPelsPerMeter = 1000;
|
||
|
lpbmi->biYPelsPerMeter = 1000;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lpPoint->x = (int) (lpbmi->biWidth * HIMET_PER_METER
|
||
|
/ lpbmi->biXPelsPerMeter);
|
||
|
lpPoint->y = -(int) (lpbmi->biHeight * HIMET_PER_METER
|
||
|
/ lpbmi->biYPelsPerMeter);
|
||
|
}
|