mirror of https://github.com/lianthony/NT4.0
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.
3544 lines
99 KiB
3544 lines
99 KiB
|
|
#include <platform.h>
|
|
|
|
#include <sccfi.h>
|
|
#include <sccut.h>
|
|
#include <sccch.h>
|
|
#include <sccvw.h>
|
|
#include <sccd.h>
|
|
|
|
#ifdef WINDOWS
|
|
#include "oimnp_w.h"
|
|
#endif
|
|
|
|
#ifdef MAC
|
|
#include "oimnp_m.h"
|
|
#endif
|
|
|
|
#include "oim.h"
|
|
#include "oimproc.pro"
|
|
#include "oimdraw.pro"
|
|
|
|
#ifdef WINDOWS
|
|
#include "oimnp_w.pro"
|
|
#endif
|
|
|
|
#ifdef MAC
|
|
#include "oimnp_m.pro"
|
|
#endif
|
|
|
|
#define OIMABS(x) (((x)<0)?(-(x)):(x))
|
|
|
|
|
|
VOID InitVectorPlay ( hDC, hRgn, lpDisplay, wPlayState )
|
|
HDC hDC;
|
|
HRGN hRgn;
|
|
POIM_DISPLAY lpDisplay;
|
|
WORD wPlayState;
|
|
{
|
|
LPVECTORINFO lpVectorInfo;
|
|
CHSECTIONINFO SecInfo;
|
|
SOPOINT Pt[2];
|
|
lpVectorInfo = &lpDisplay->VectorInfo;
|
|
|
|
lpDisplay->wPlayState = wPlayState;
|
|
lpDisplay->VectorInfo.wStartChunk = 0;
|
|
|
|
OIMSaveStateNP(lpDisplay);
|
|
|
|
if ( OIMIsNativeNP(lpDisplay) )
|
|
return;
|
|
if ( lpDisplay->wPlayState != OIMF_PLAYTOMETA )
|
|
{
|
|
Pt[0].x = (SHORT)lpDisplay->Image.bbox.left;
|
|
Pt[0].y = (SHORT)lpDisplay->Image.bbox.top;
|
|
Pt[1].x = (SHORT)lpDisplay->Image.bbox.right;
|
|
Pt[1].y = (SHORT)lpDisplay->Image.bbox.bottom;
|
|
VULPtoDP ( hDC, Pt, 2 );
|
|
lpVectorInfo->hSelectRgn = VUCreateRectRgn ( Pt[0].x, Pt[0].y, Pt[1].x, Pt[1].y );
|
|
if ( hRgn )
|
|
VUIntersectRgn ( lpVectorInfo->hSelectRgn, lpVectorInfo->hSelectRgn, hRgn );
|
|
}
|
|
else
|
|
lpVectorInfo->hSelectRgn = NULL;
|
|
|
|
/* Make sure all path and transform info is initialized */
|
|
FreePath ( lpVectorInfo );
|
|
FreeTransform ( &lpVectorInfo->GenTransform );
|
|
FreeTransform ( &lpVectorInfo->ObjectTransform );
|
|
InitTable ( hDC, &lpVectorInfo->FontTable, VUSYSTEM_FONT, sizeof(SOLOGFONT), CreateFontRtnNP, MAXFONTS );
|
|
InitTable ( hDC, &lpVectorInfo->PenTable, VUBLACK_PEN, sizeof(SOLOGPEN), CreatePenRtnNP, MAXPENS );
|
|
InitTable ( hDC, &lpVectorInfo->BrushTable, VUWHITE_BRUSH, sizeof(SOLOGBRUSH), CreateBrushRtnNP, MAXBRUSHES );
|
|
lpVectorInfo->PolyPoints.nCount = 0;
|
|
lpVectorInfo->PolyPoints.nMax = 0;
|
|
lpVectorInfo->PolyPoints.hPoints = NULL;
|
|
lpVectorInfo->BezierPoints.nMax = 0;
|
|
lpVectorInfo->BezierPoints.nCount = 0;
|
|
lpVectorInfo->BezierPoints.hPoints = NULL;
|
|
lpVectorInfo->Frame.WrapInfo.hItems = NULL;
|
|
lpVectorInfo->Frame.WrapInfo.CurWrapItem = 0;
|
|
lpVectorInfo->Frame.WrapInfo.nCount = 0;
|
|
lpVectorInfo->Frame.WrapInfo.nMax = 0;
|
|
lpVectorInfo->TextRotationAngle = 0;
|
|
lpVectorInfo->wPathLevel = 0;
|
|
lpVectorInfo->wGroupLevel = 0;
|
|
lpVectorInfo->wIgnoreGroup = 0;
|
|
lpVectorInfo->bTransforming = 0;
|
|
lpVectorInfo->XDirection = lpDisplay->Image.XDirection;
|
|
lpVectorInfo->YDirection = lpDisplay->Image.YDirection;
|
|
// CHGetSecInfo( lpDisplay->Gen.hFilter, lpDisplay->Gen.wSection, &SecInfo );
|
|
SecInfo = *(CHLockSectionInfo(lpDisplay->Gen.hFilter, lpDisplay->Gen.wSection));
|
|
CHUnlockSectionInfo(lpDisplay->Gen.hFilter, lpDisplay->Gen.wSection);
|
|
|
|
if ( lpDisplay->wPlayState != OIMF_PLAYTOPRINTER &&
|
|
SecInfo.Attr.Vector.Header.wImageFlags & SO_VECTORRGBCOLOR &&
|
|
lpDisplay->wScreenColors == 256 )
|
|
lpVectorInfo->bRgbToPalette = TRUE;
|
|
else
|
|
lpVectorInfo->bRgbToPalette = FALSE;
|
|
OIMCheckPointBuffer ( &(lpVectorInfo->PolyPoints), 25 );
|
|
|
|
OIMDisplayBkgdColor(hDC, SecInfo.Attr.Vector.Header.BkgColor, lpDisplay);
|
|
|
|
lpVectorInfo->wClipMode = 0;
|
|
lpVectorInfo->nPolyFillMode = SOPF_ALTERNATE;
|
|
lpVectorInfo->nBkMode = SOBK_TRANSPARENT;
|
|
lpVectorInfo->nROP2 = SOR2_COPYPEN;
|
|
SetVectorAttribs ( hDC, lpDisplay );
|
|
}
|
|
|
|
BOOL SetVectorAttribs ( hDC, lpDisplay )
|
|
HDC hDC;
|
|
POIM_DISPLAY lpDisplay;
|
|
{
|
|
LPVECTORINFO lpVectorInfo;
|
|
HANDLE hTmp;
|
|
lpVectorInfo = &lpDisplay->VectorInfo;
|
|
|
|
SetClipMode ( hDC, lpVectorInfo, lpDisplay );
|
|
|
|
/*Font*/
|
|
hTmp = lpVectorInfo->FontTable.hObject[0];
|
|
if ( hTmp )
|
|
VUSelectObject ( hDC, hTmp );
|
|
else
|
|
VUSelectStockObject ( hDC, VUSYSTEM_FONT );
|
|
/*Pen*/
|
|
hTmp = lpVectorInfo->PenTable.hObject[0];
|
|
if ( hTmp )
|
|
VUSelectObject ( hDC, hTmp );
|
|
else
|
|
VUSelectStockObject ( hDC, VUBLACK_PEN );
|
|
/*Brush*/
|
|
hTmp = lpVectorInfo->BrushTable.hObject[0];
|
|
if ( hTmp )
|
|
VUSelectObject ( hDC, hTmp );
|
|
else
|
|
VUSelectStockObject ( hDC, VUWHITE_BRUSH );
|
|
|
|
VUSetPolyFillMode ( hDC, lpVectorInfo->nPolyFillMode );
|
|
VUSetTextCharacterExtra ( hDC, lpVectorInfo->nTextCharExtra );
|
|
VUSetROP2 ( hDC, lpVectorInfo->nROP2 );
|
|
VUSetTextColor ( hDC, lpVectorInfo->TextColor );
|
|
VUSetBkMode ( hDC, lpVectorInfo->nBkMode );
|
|
VUSetBkColor ( hDC, lpVectorInfo->BkColor );
|
|
|
|
#ifdef MAC
|
|
SetOutlinePreferred(TRUE); // Outline fonts are nicer.
|
|
#endif
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL PlayNextVectorChunk ( hDC, lpDisplay )
|
|
HDC hDC;
|
|
POIM_DISPLAY lpDisplay;
|
|
{
|
|
WORD wCurTotalChunks;
|
|
CHSECTIONINFO SecInfo;
|
|
HANDLE hChunkData;
|
|
LPSTR pChunkData;
|
|
PCHUNK pChunkTable;
|
|
LPVECTORINFO lpVectorInfo;
|
|
LPVRECORDHEADER lpVectorRecord;
|
|
LPSTR pChunkTop;
|
|
if ( OIMIsNativeNP(lpDisplay) )
|
|
{
|
|
OIMPlayNativeNP (hDC, lpDisplay);
|
|
return(1);
|
|
}
|
|
|
|
lpVectorInfo = &lpDisplay->VectorInfo;
|
|
|
|
//CHGetSecInfo( lpDisplay->Gen.hFilter, lpDisplay->Gen.wSection, &SecInfo );
|
|
SecInfo = *(CHLockSectionInfo(lpDisplay->Gen.hFilter, lpDisplay->Gen.wSection));
|
|
CHUnlockSectionInfo(lpDisplay->Gen.hFilter, lpDisplay->Gen.wSection);
|
|
|
|
wCurTotalChunks = SecInfo.wCurTotalChunks;
|
|
if( wCurTotalChunks )
|
|
{
|
|
pChunkTable = (PCHUNK) UTGlobalLock( SecInfo.hChunkTable );
|
|
|
|
if ( lpVectorInfo->wStartChunk < wCurTotalChunks )
|
|
{
|
|
hChunkData = CHGetChunk( lpDisplay->Gen.wSection, lpVectorInfo->wStartChunk, lpDisplay->Gen.hFilter );
|
|
pChunkData = (LPSTR) UTGlobalLock( hChunkData );
|
|
pChunkTop = pChunkData;
|
|
lpVectorRecord = (LPVRECORDHEADER)pChunkData;
|
|
|
|
lpVectorInfo->Frame.WrapInfo.WrappedPara = FALSE;
|
|
while ( lpVectorRecord->nItemId != (SHORT)SO_VECTORENDOFCHUNK )
|
|
{
|
|
/*
|
|
if ( lpVectorRecord->wDataSize >= 0x8000 )
|
|
break;
|
|
if ( ((LPBYTE)lpVectorRecord - pChunkTop) + lpVectorRecord->wDataSize > 0x0fff )
|
|
break;
|
|
*/
|
|
if(PlayVectorRecord ( hDC, lpDisplay, lpVectorInfo, lpVectorRecord )==0)
|
|
break;
|
|
pChunkData += sizeof(VRECORDHEADER)+lpVectorRecord->wDataSize;
|
|
lpVectorRecord = (LPVRECORDHEADER)pChunkData;
|
|
}
|
|
UTGlobalUnlock( hChunkData );
|
|
lpVectorInfo->wStartChunk++;
|
|
}
|
|
|
|
UTGlobalUnlock( SecInfo.hChunkTable );
|
|
|
|
}
|
|
if ( lpVectorInfo->wStartChunk >= wCurTotalChunks &&
|
|
lpDisplay->wFlags & OIMF_IMAGEPRESENT)
|
|
{
|
|
if ( lpDisplay->wPlayState != OIMF_PLAYTOPRINTER )
|
|
lpDisplay->VectorInfo.bFinalPalette = TRUE;
|
|
}
|
|
if ( lpVectorInfo->wStartChunk >= wCurTotalChunks )
|
|
return(1);
|
|
else
|
|
return(0);
|
|
}
|
|
|
|
|
|
VOID CleanupVectorPlay ( hDC, lpDisplay )
|
|
HDC hDC;
|
|
POIM_DISPLAY lpDisplay;
|
|
{
|
|
LPVECTORINFO lpVectorInfo;
|
|
|
|
lpDisplay->wPlayState = 0;
|
|
|
|
OIMRestoreStateNP(lpDisplay);
|
|
|
|
if ( OIMIsNativeNP(lpDisplay) )
|
|
return;
|
|
|
|
lpVectorInfo = &lpDisplay->VectorInfo;
|
|
ClearTable ( lpDisplay, hDC, &lpVectorInfo->FontTable, VUSYSTEM_FONT );
|
|
ClearTable ( lpDisplay, hDC, &lpVectorInfo->PenTable, VUBLACK_PEN );
|
|
ClearTable ( lpDisplay, hDC, &lpVectorInfo->BrushTable, VUWHITE_BRUSH );
|
|
if ( lpVectorInfo->PolyPoints.hPoints )
|
|
UTGlobalFree ( lpVectorInfo->PolyPoints.hPoints );
|
|
if ( lpVectorInfo->BezierPoints.hPoints )
|
|
UTGlobalFree ( lpVectorInfo->BezierPoints.hPoints );
|
|
if ( lpVectorInfo->Frame.WrapInfo.hItems )
|
|
UTGlobalFree ( lpVectorInfo->Frame.WrapInfo.hItems );
|
|
FreePath ( lpVectorInfo );
|
|
FreeTransform ( &lpVectorInfo->GenTransform );
|
|
FreeTransform ( &lpVectorInfo->ObjectTransform );
|
|
if ( lpVectorInfo->hSelectRgn )
|
|
VUDeleteRgn ( lpVectorInfo->hSelectRgn );
|
|
}
|
|
|
|
|
|
WORD InitTable ( hDC, lpTable, nInitObject, wObjectSize, CreateRtn, nMaxObjects )
|
|
HDC hDC;
|
|
LPOBJECTTABLE lpTable;
|
|
SHORT nInitObject;
|
|
WORD wObjectSize;
|
|
HANDLE (*CreateRtn)(HDC,LPBYTE);
|
|
SHORT nMaxObjects;
|
|
{
|
|
SHORT i;
|
|
VUSelectStockObject ( hDC, nInitObject );
|
|
lpTable->wObjectSize = wObjectSize;
|
|
lpTable->CreateRtn = CreateRtn;
|
|
lpTable->nObjectsSoFar = 0;
|
|
lpTable->nMaxObjects = nMaxObjects;
|
|
lpTable->hData = UTGlobalAlloc ((DWORD)(wObjectSize*nMaxObjects));
|
|
if ( lpTable->hData )
|
|
{
|
|
lpTable->lpObjects = UTGlobalLock ( lpTable->hData );
|
|
for ( i=0; i < nMaxObjects; i++ )
|
|
lpTable->hObject[i] = NULL;
|
|
return(TRUE);
|
|
}
|
|
else
|
|
{
|
|
lpTable->lpObjects = NULL;
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
WORD ClearTable ( lpDisplay, hDC, lpTable, nInitObject )
|
|
POIM_DISPLAY lpDisplay;
|
|
HDC hDC;
|
|
LPOBJECTTABLE lpTable;
|
|
SHORT nInitObject;
|
|
{
|
|
SHORT i;
|
|
VUSelectStockObject ( hDC, nInitObject );
|
|
for ( i=0; i < lpTable->nObjectsSoFar; i++ )
|
|
{
|
|
VUDeleteObject (lpDisplay, lpTable->hObject[i] );
|
|
}
|
|
UTGlobalUnlock ( lpTable->hData );
|
|
UTGlobalFree ( lpTable->hData );
|
|
return(TRUE);
|
|
}
|
|
|
|
SHORT PlayVectorRecord ( hDC, lpDisplay, lpVectorInfo, lpVectorRecord )
|
|
HDC hDC;
|
|
POIM_DISPLAY lpDisplay;
|
|
LPVECTORINFO lpVectorInfo;
|
|
LPVRECORDHEADER lpVectorRecord;
|
|
{
|
|
LPBYTE lpData;
|
|
LPSHORT lpInt;
|
|
LPSTR lpString;
|
|
SHORT nCount, ret;
|
|
SOPOINT TmpPoints[5];
|
|
|
|
if ( lpVectorInfo->wIgnoreGroup )
|
|
{
|
|
switch ( lpVectorRecord->nItemId )
|
|
{
|
|
/* let certain items pass through */
|
|
case SO_BEGINGROUP:
|
|
case SO_ENDGROUP:
|
|
case SO_SELECTFONT:
|
|
case SO_SELECTPEN:
|
|
case SO_SELECTBRUSH:
|
|
case SO_POLYFILLMODE:
|
|
case SO_TEXTCHAREXTRA:
|
|
case SO_DRAWMODE:
|
|
case SO_TEXTCOLOR:
|
|
case SO_BKMODE:
|
|
case SO_POINTRELATION:
|
|
/* Allow these items */
|
|
break;
|
|
|
|
default:
|
|
return(1);
|
|
}
|
|
}
|
|
if ( lpVectorInfo->bTransforming || lpVectorInfo->wPathLevel )
|
|
{
|
|
if ( ApplyTransform ( hDC, lpVectorInfo, lpVectorRecord ))
|
|
{
|
|
lpVectorRecord = (LPVRECORDHEADER)&(lpVectorInfo->TmpRecord);
|
|
if ( lpVectorInfo->wPathLevel )
|
|
{
|
|
AddRecordToPath ( lpVectorInfo, lpVectorRecord );
|
|
return(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
lpData = (LPBYTE)(lpVectorRecord) + sizeof ( VRECORDHEADER );
|
|
lpInt = (LPSHORT)lpData;
|
|
|
|
switch ( lpVectorRecord->nItemId )
|
|
{
|
|
/* Object information */
|
|
|
|
case SO_CPARCTRIPLE:
|
|
{
|
|
SOPOINT TriplePoints[3];
|
|
|
|
TriplePoints[0] = lpVectorInfo->ptCurrentPosition;
|
|
TriplePoints[1] = *(PSOPOINT)lpData;
|
|
TriplePoints[2] = *(PSOPOINT)(lpData + sizeof(SOPOINT));
|
|
RelatePoints ( lpVectorInfo, &TriplePoints[1], 1 );
|
|
lpVectorInfo->ptCurrentPosition = TriplePoints[0];
|
|
RelatePoints ( lpVectorInfo, &TriplePoints[2], 1 );
|
|
if ( ret = ArcTripleToPoints ( lpVectorInfo, (PSOPOINT)lpData, TmpPoints ) )
|
|
{
|
|
lpInt = (LPSHORT)TmpPoints;
|
|
if (ret != 1)
|
|
{
|
|
TmpPoints[4] = TmpPoints[2];
|
|
TmpPoints[2] = TmpPoints[3];
|
|
TmpPoints[3] = TmpPoints[4];
|
|
}
|
|
VUArc ( hDC, lpInt );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SO_ARCTRIPLE:
|
|
|
|
if ( ret = ArcTripleToPoints ( lpVectorInfo, (PSOPOINT)lpData, TmpPoints ) )
|
|
{
|
|
lpInt = (LPSHORT)TmpPoints;
|
|
if (ret != 1)
|
|
{
|
|
TmpPoints[4] = TmpPoints[2];
|
|
TmpPoints[2] = TmpPoints[3];
|
|
TmpPoints[3] = TmpPoints[4];
|
|
}
|
|
VUArc ( hDC, lpInt );
|
|
}
|
|
break;
|
|
|
|
case SO_PIETRIPLE:
|
|
|
|
if ( ret = ArcTripleToPoints ( lpVectorInfo, (PSOPOINT)lpData, TmpPoints ) )
|
|
{
|
|
lpInt = (LPSHORT)TmpPoints;
|
|
if (ret != 1)
|
|
{
|
|
TmpPoints[4] = TmpPoints[2];
|
|
TmpPoints[2] = TmpPoints[3];
|
|
TmpPoints[3] = TmpPoints[4];
|
|
}
|
|
VUPie ( hDC, lpInt );
|
|
}
|
|
break;
|
|
|
|
case SO_CHORDTRIPLE:
|
|
|
|
if ( ret = ArcTripleToPoints ( lpVectorInfo, (PSOPOINT)lpData, TmpPoints ) )
|
|
{
|
|
lpInt = (LPSHORT)TmpPoints;
|
|
if (ret != 1)
|
|
{
|
|
TmpPoints[4] = TmpPoints[2];
|
|
TmpPoints[2] = TmpPoints[3];
|
|
TmpPoints[3] = TmpPoints[4];
|
|
}
|
|
VUChord ( hDC, lpInt );
|
|
}
|
|
break;
|
|
|
|
case SO_CPARCANGLE:
|
|
CpArcToPoints ( lpVectorInfo, (PSOCPARCANGLE)lpData, TmpPoints );
|
|
lpInt = (LPSHORT)TmpPoints;
|
|
VUArc ( hDC, lpInt);
|
|
break;
|
|
|
|
case SO_ARCANGLE:
|
|
lpInt = ArcInfoToPoints ( lpVectorInfo, (PSOARCINFO)lpData, TmpPoints );
|
|
/* Fall through */
|
|
case SO_ARC:
|
|
VUArc ( hDC, lpInt );
|
|
break;
|
|
|
|
case SO_ARCANGLECLOCKWISE:
|
|
lpInt = ArcInfoToPoints ( lpVectorInfo, (PSOARCINFO)lpData, TmpPoints );
|
|
TmpPoints[4] = TmpPoints[2];
|
|
TmpPoints[2] = TmpPoints[3];
|
|
TmpPoints[3] = TmpPoints[4];
|
|
VUArc ( hDC, lpInt);
|
|
break;
|
|
|
|
case SO_ARCCLOCKWISE:
|
|
TmpPoints[0] = *((PSOPOINT)lpInt);
|
|
TmpPoints[1] = *((PSOPOINT)(lpInt+sizeof(SHORT)));
|
|
TmpPoints[2] = *((PSOPOINT)(lpInt+3*sizeof(SHORT)));
|
|
TmpPoints[3] = *((PSOPOINT)(lpInt+2*sizeof(SHORT)));
|
|
VUArc ( hDC, (LPSHORT)TmpPoints);
|
|
break;
|
|
|
|
case SO_CHORDANGLE:
|
|
lpInt = ArcInfoToPoints ( lpVectorInfo, (PSOARCINFO)lpData, TmpPoints );
|
|
/* Fall through */
|
|
case SO_CHORD:
|
|
VUChord ( hDC, lpInt);
|
|
break;
|
|
|
|
case SO_TEXTINRECT:
|
|
{
|
|
PSOTEXTINRECT lpTextInRect;
|
|
lpTextInRect = (PSOTEXTINRECT)lpData;
|
|
lpString = (LPSTR)(lpData+sizeof(SOTEXTINRECT));
|
|
/*
|
|
| There is is no reason why the SetTextAlign call is needed below,
|
|
| except that Windows has a bug where a DrawText with DT_TOP or
|
|
| DT_LEFT actually uses the previous SetTextAlignValues in a bizzare
|
|
| way.
|
|
*/
|
|
VUSetTextAlign ( hDC, SOTA_LEFT|SOTA_TOP );
|
|
VUDrawText ( hDC, lpString, lpTextInRect->nTextLength, &(lpTextInRect->Rect), lpTextInRect->wFormat );
|
|
}
|
|
break;
|
|
|
|
case SO_CPELLIPSE:
|
|
TmpPoints[2] = *(PSOPOINT)lpData;
|
|
TmpPoints[0].x = lpVectorInfo->ptCurrentPosition.x-TmpPoints[2].x;
|
|
TmpPoints[1].x = lpVectorInfo->ptCurrentPosition.x+TmpPoints[2].x;
|
|
TmpPoints[0].y = lpVectorInfo->ptCurrentPosition.y-TmpPoints[2].y;
|
|
TmpPoints[1].y = lpVectorInfo->ptCurrentPosition.y+TmpPoints[2].y;
|
|
VUEllipse ( hDC, (LPSHORT)TmpPoints );
|
|
break;
|
|
|
|
case SO_ELLIPSE:
|
|
VUEllipse ( hDC, lpInt);
|
|
break;
|
|
|
|
case SO_ELLIPSERADII:
|
|
ret = EllipseRadiiToPoints ( lpVectorInfo, (PSOPOINT)lpData, TmpPoints );
|
|
if (ret)
|
|
OIMPolyObject ( hDC, lpVectorInfo, &lpVectorInfo->PolyInfo, &lpVectorInfo->PolyPoints, TRUE );
|
|
else
|
|
VUEllipse ( hDC, (LPSHORT)TmpPoints);
|
|
break;
|
|
|
|
case SO_ARCRADII:
|
|
ret = ArcRadiiToPoints ( lpVectorInfo, (PSOPOINT)lpData, TmpPoints );
|
|
if (ret)
|
|
{
|
|
ArcToPolyObject ( lpVectorInfo, TmpPoints, SO_ARC, ret ); // ret is the rotation angle
|
|
OIMPolyObject ( hDC, lpVectorInfo, &lpVectorInfo->PolyInfo, &lpVectorInfo->PolyPoints, TRUE );
|
|
}
|
|
else
|
|
VUArc ( hDC, (LPSHORT)TmpPoints);
|
|
break;
|
|
|
|
case SO_PIERADII:
|
|
ret = ArcRadiiToPoints ( lpVectorInfo, (PSOPOINT)lpData, TmpPoints );
|
|
if (ret)
|
|
{
|
|
ArcToPolyObject ( lpVectorInfo, TmpPoints, SO_PIE, ret ); // ret is the rotation angle
|
|
OIMPolyObject ( hDC, lpVectorInfo, &lpVectorInfo->PolyInfo, &lpVectorInfo->PolyPoints, TRUE );
|
|
}
|
|
else
|
|
VUPie ( hDC, (LPSHORT)TmpPoints);
|
|
break;
|
|
case SO_CHORDRADII:
|
|
ret = ArcRadiiToPoints ( lpVectorInfo, (PSOPOINT)lpData, TmpPoints );
|
|
if (ret)
|
|
{
|
|
ArcToPolyObject ( lpVectorInfo, TmpPoints, SO_CHORD, ret ); // ret is the rotation angle
|
|
OIMPolyObject ( hDC, lpVectorInfo, &lpVectorInfo->PolyInfo, &lpVectorInfo->PolyPoints, TRUE );
|
|
}
|
|
else
|
|
VUChord ( hDC, (LPSHORT)TmpPoints);
|
|
break;
|
|
|
|
case SO_FLOODFILL:
|
|
VUFloodFill ( hDC, *(lpInt), *(lpInt+1), *(SOCOLORREF VWPTR *)(lpData+sizeof(SOPOINT)) );
|
|
break;
|
|
|
|
case SO_CPLINE:
|
|
TmpPoints[0] = lpVectorInfo->ptCurrentPosition;
|
|
TmpPoints[1] = *(PSOPOINT)lpData;
|
|
RelatePoints ( lpVectorInfo, &TmpPoints[1], 1 );
|
|
lpInt = (LPSHORT)TmpPoints;
|
|
/* Fall through */
|
|
|
|
case SO_LINE:
|
|
VUDrawLine ( hDC, lpInt);
|
|
break;
|
|
|
|
case SO_CPPIEANGLE:
|
|
CpPieToPoints ( lpVectorInfo, (PSOCPPIEANGLE)lpData, TmpPoints );
|
|
lpInt = (LPSHORT)TmpPoints;
|
|
VUPie ( hDC, lpInt);
|
|
break;
|
|
|
|
case SO_PIEANGLE:
|
|
lpInt = ArcInfoToPoints ( lpVectorInfo, (PSOARCINFO)lpData, TmpPoints );
|
|
/* Fall through */
|
|
case SO_PIE:
|
|
VUPie ( hDC, lpInt);
|
|
break;
|
|
|
|
case SO_STARTPOLY:
|
|
lpVectorInfo->PolyInfo = *(PSOPOLYINFO)(lpData);
|
|
lpVectorInfo->PolyPoints.nCount = 0;
|
|
if ( lpVectorInfo->PolyInfo.wFormat == SOPT_CPPOLYLINE ||
|
|
lpVectorInfo->PolyInfo.wFormat == SOPT_CPPOLYGON )
|
|
{
|
|
AddPointsToPolyObject ( lpVectorInfo, 1, &lpVectorInfo->ptCurrentPosition );
|
|
}
|
|
break;
|
|
|
|
case SO_POINTS:
|
|
nCount = (lpVectorRecord->wDataSize)/sizeof(SOPOINT);
|
|
if( OIMCheckPointBuffer ( &(lpVectorInfo->PolyPoints),
|
|
(SHORT)(lpVectorInfo->PolyPoints.nCount+nCount) ) )
|
|
{
|
|
PSOPOINT lpPointDst;
|
|
lpPointDst = (PSOPOINT)UTGlobalLock ( lpVectorInfo->PolyPoints.hPoints );
|
|
lpPointDst += lpVectorInfo->PolyPoints.nCount;
|
|
UTmemcpy ( (LPBYTE)lpPointDst, lpData, sizeof(SOPOINT)*nCount );
|
|
if ( lpVectorInfo->PolyInfo.wFormat == SOPT_CPPOLYLINE ||
|
|
lpVectorInfo->PolyInfo.wFormat == SOPT_CPPOLYGON )
|
|
{
|
|
RelatePoints ( lpVectorInfo, lpPointDst, nCount );
|
|
}
|
|
UTGlobalUnlock ( lpVectorInfo->PolyPoints.hPoints );
|
|
lpVectorInfo->PolyPoints.nCount += nCount;
|
|
}
|
|
break;
|
|
|
|
case SO_ENDPOLY:
|
|
OIMPolyObject ( hDC, lpVectorInfo, &lpVectorInfo->PolyInfo, &lpVectorInfo->PolyPoints, TRUE );
|
|
break;
|
|
|
|
case SO_CPRECTANGLE:
|
|
TmpPoints[0] = lpVectorInfo->ptCurrentPosition;
|
|
TmpPoints[1] = *(PSOPOINT)lpData;
|
|
RelatePoints ( lpVectorInfo, &TmpPoints[1], 1 );
|
|
/* reset cp */
|
|
lpVectorInfo->ptCurrentPosition = TmpPoints[0];
|
|
VURectangle ( hDC, (LPSHORT)TmpPoints );
|
|
break;
|
|
|
|
case SO_RECTANGLE:
|
|
VURectangle ( hDC, lpInt);
|
|
break;
|
|
|
|
case SO_ROUNDRECT:
|
|
VURoundRect ( hDC, lpInt);
|
|
break;
|
|
|
|
case SO_SETPIXEL:
|
|
VUSetPixel ( hDC, *(lpInt), *(lpInt+1), *(SOCOLORREF VWPTR *)(lpData+sizeof(SOPOINT)));
|
|
break;
|
|
|
|
case SO_CPTEXTATPOINT:
|
|
{
|
|
PSOCPTEXTATPOINT lpTextAtPoint;
|
|
lpTextAtPoint = (PSOCPTEXTATPOINT)lpData;
|
|
lpString = (LPSTR)(lpData+sizeof(SOCPTEXTATPOINT));
|
|
VUSetTextAlign ( hDC, lpTextAtPoint->wFormat );
|
|
VUTextOut ( hDC, lpVectorInfo->ptCurrentPosition.x, lpVectorInfo->ptCurrentPosition.y, lpString, lpTextAtPoint->nTextLength );
|
|
}
|
|
break;
|
|
|
|
case SO_TEXTATPOINT:
|
|
{
|
|
PSOTEXTATPOINT lpTextAtPoint;
|
|
lpTextAtPoint = (PSOTEXTATPOINT)lpData;
|
|
lpString = (LPSTR)(lpData+sizeof(SOTEXTATPOINT));
|
|
VUSetTextAlign ( hDC, lpTextAtPoint->wFormat );
|
|
VUTextOut ( hDC, lpTextAtPoint->Point.x, lpTextAtPoint->Point.y, lpString, lpTextAtPoint->nTextLength );
|
|
}
|
|
break;
|
|
|
|
case SO_TEXTATARCANGLE:
|
|
{
|
|
PSOTEXTATARCANGLE lpTextAtArcAngle;
|
|
lpTextAtArcAngle = (PSOTEXTATARCANGLE)lpData;
|
|
lpString = (LPSTR)(lpData+sizeof(SOTEXTATARCANGLE));
|
|
VUSetTextAlign ( hDC, lpTextAtArcAngle->wFormat );
|
|
lpInt = ArcInfoToPoints ( lpVectorInfo, (PSOARCINFO)lpData, TmpPoints );
|
|
VUTextOut ( hDC, *(lpInt+4), *(lpInt+5), lpString, lpTextAtArcAngle->nTextLength );
|
|
}
|
|
break;
|
|
|
|
case SO_BEGINPATH:
|
|
{
|
|
PSOPATHINFO lpPathInfo;
|
|
if ( lpVectorInfo->wPathLevel == 0 )
|
|
FreePath(lpVectorInfo);
|
|
lpPathInfo = (PSOPATHINFO)lpData;
|
|
lpData += sizeof(SOPATHINFO);
|
|
lpVectorInfo->wPathLevel++;
|
|
PushTransform ( lpVectorInfo, &lpVectorInfo->GenTransform, lpPathInfo->nTransforms, lpData );
|
|
SetupTransform ( lpVectorInfo );
|
|
}
|
|
break;
|
|
|
|
case SO_ENDPATH:
|
|
lpVectorInfo->wPathLevel--;
|
|
if ( lpVectorInfo->wPathFlags & CP_BUFFERED &&
|
|
lpVectorInfo->wPathLevel == 0 )
|
|
{
|
|
lpVectorInfo->CurrentPath.nPolys++;
|
|
lpVectorInfo->wPathFlags &= ~CP_BUFFERED;
|
|
}
|
|
PopTransform ( &lpVectorInfo->GenTransform );
|
|
SetupTransform ( lpVectorInfo );
|
|
break;
|
|
|
|
case SO_CLOSESUBPATH:
|
|
CloseSubPath ( lpVectorInfo );
|
|
break;
|
|
|
|
case SO_DRAWPATH:
|
|
DrawPath ( hDC, lpVectorInfo, *(LPWORD)(lpData) );
|
|
break;
|
|
|
|
case SO_BEGINGROUP:
|
|
{
|
|
PSOGROUPINFO lpGroupInfo;
|
|
lpVectorInfo->wGroupLevel++;
|
|
lpGroupInfo = (PSOGROUPINFO)lpData;
|
|
lpData += sizeof(SOGROUPINFO);
|
|
PushTransform ( lpVectorInfo, &lpVectorInfo->GenTransform, lpGroupInfo->nTransforms, lpData );
|
|
SetupTransform ( lpVectorInfo );
|
|
if ((lpVectorInfo->wIgnoreGroup == 0) && ( lpVectorInfo->hSelectRgn))
|
|
{
|
|
/*
|
|
Check if we can ignore entire group because it lies outside
|
|
of the selected display region.
|
|
Note that group has already been transformed by ApplyTransform
|
|
to transformed logical units if appropriate. These points must
|
|
still be transformed to device units for the test.
|
|
*/
|
|
SORECT BoundingRect;
|
|
BoundingRect = lpGroupInfo->BoundingRect;
|
|
VULPtoDP ( hDC, (PSOPOINT)&BoundingRect, 2 );
|
|
if ( VURectInRgn(lpVectorInfo->hSelectRgn,(PSORECT)&BoundingRect) == FALSE )
|
|
{
|
|
lpVectorInfo->wIgnoreGroup = lpVectorInfo->wGroupLevel;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SO_ENDGROUP:
|
|
lpVectorInfo->wGroupLevel--;
|
|
PopTransform ( &lpVectorInfo->GenTransform );
|
|
SetupTransform ( lpVectorInfo );
|
|
if ( lpVectorInfo->wGroupLevel < lpVectorInfo->wIgnoreGroup )
|
|
lpVectorInfo->wIgnoreGroup = 0;
|
|
break;
|
|
|
|
case SO_CPSET:
|
|
TmpPoints[0] = *(PSOPOINT)lpData;
|
|
RelatePoints ( lpVectorInfo, TmpPoints, 1 );
|
|
break;
|
|
|
|
case SO_BEGINSYMBOL:
|
|
|
|
if ( !lpVectorInfo->Frame.WrapInfo.WrappedPara )
|
|
OIMWrapPara ( lpDisplay, lpVectorInfo, (LPBYTE)lpVectorRecord );
|
|
|
|
SetupFrameTransform ( lpVectorInfo );
|
|
break;
|
|
|
|
case SO_ENDSYMBOL:
|
|
lpVectorInfo->Frame.WrapInfo.CurWrapItem++;
|
|
break;
|
|
|
|
case SO_BEGINTEXTFRAME:
|
|
{
|
|
SOTRANSFORM FrameTransform;
|
|
lpVectorInfo->InFrame = TRUE;
|
|
lpVectorInfo->Frame.FrameInfo = *(PSOFRAMEINFO)lpData;
|
|
if ( lpVectorInfo->Frame.FrameInfo.wFlags & SOFF_FIXUPBOUNDS )
|
|
{
|
|
OIMFixupFrameInfo ( hDC, lpVectorInfo );
|
|
}
|
|
FrameTransform.wTransformFlags = SOTF_XOFFSET | SOTF_YOFFSET;
|
|
FrameTransform.Origin.x = lpVectorInfo->Frame.FrameInfo.BoundingRect.left;
|
|
FrameTransform.Origin.y = lpVectorInfo->Frame.FrameInfo.BoundingRect.top;
|
|
FrameTransform.xOffset = FrameTransform.yOffset = 0;
|
|
lpVectorInfo->Frame.TransformOffset = lpVectorInfo->GenTransform.nAllocUsed;
|
|
PushTransform ( lpVectorInfo, &lpVectorInfo->GenTransform, 1, (LPBYTE)&FrameTransform );
|
|
SetupTransform ( lpVectorInfo );
|
|
lpVectorInfo->Frame.CurY = 0;
|
|
lpVectorInfo->Frame.RightWrap = OIMABS ( lpVectorInfo->Frame.FrameInfo.BoundingRect.right-lpVectorInfo->Frame.FrameInfo.BoundingRect.left);
|
|
lpVectorInfo->Frame.WrapInfo.WrappedPara = FALSE;
|
|
}
|
|
break;
|
|
|
|
case SO_ENDTEXTFRAME:
|
|
lpVectorInfo->InFrame = FALSE;
|
|
PopTransform ( &lpVectorInfo->GenTransform );
|
|
SetupTransform ( lpVectorInfo );
|
|
break;
|
|
|
|
case SO_TEXTINPARA:
|
|
if ( !lpVectorInfo->Frame.WrapInfo.WrappedPara )
|
|
OIMWrapPara ( lpDisplay, lpVectorInfo, (LPBYTE)lpVectorRecord );
|
|
|
|
OutputParaText ( hDC, lpVectorInfo, lpData + sizeof(SHORT), *lpInt );
|
|
break;
|
|
|
|
case SO_PARAEND:
|
|
if ( !lpVectorInfo->Frame.WrapInfo.WrappedPara )
|
|
OIMWrapPara ( lpDisplay, lpVectorInfo, (LPBYTE)lpVectorRecord );
|
|
|
|
SetupFrameTransform ( lpVectorInfo );
|
|
lpVectorInfo->Frame.WrapInfo.WrappedPara = FALSE;
|
|
lpVectorInfo->Frame.WrapInfo.CurWrapItem = 0;
|
|
lpVectorInfo->Frame.WrapInfo.nCount = 0;
|
|
break;
|
|
|
|
/*--------------------- Attribute information ---------------------*/
|
|
|
|
case SO_SELECTFONT:
|
|
SelectObjectIndirect ( lpDisplay, hDC, &(lpVectorInfo->FontTable), lpData );
|
|
break;
|
|
|
|
case SO_SELECTPEN:
|
|
if ( lpVectorInfo->bRgbToPalette )
|
|
{
|
|
SOLOGPEN Pen;
|
|
Pen = *(PSOLOGPEN)lpData;
|
|
if ( !lpVectorInfo->bFinalPalette )
|
|
AddToPalette ( hDC, lpDisplay, &Pen.loColor );
|
|
Pen.loColor |= 0x02000000L;
|
|
lpData = (LPBYTE)(&Pen);
|
|
}
|
|
SelectObjectIndirect ( lpDisplay, hDC, &(lpVectorInfo->PenTable), lpData );
|
|
break;
|
|
|
|
case SO_SELECTBRUSH:
|
|
if ( lpVectorInfo->bRgbToPalette )
|
|
{
|
|
SOLOGBRUSH Brush;
|
|
Brush = *(PSOLOGBRUSH)lpData;
|
|
if ( !lpVectorInfo->bFinalPalette )
|
|
AddToPalette ( hDC, lpDisplay, &Brush.lbColor );
|
|
Brush.lbColor |= 0x02000000L;
|
|
lpData = (LPBYTE)(&Brush);
|
|
}
|
|
SelectObjectIndirect ( lpDisplay, hDC, &(lpVectorInfo->BrushTable), lpData );
|
|
break;
|
|
|
|
case SO_POLYFILLMODE:
|
|
lpVectorInfo->nPolyFillMode = *(lpInt);
|
|
VUSetPolyFillMode ( hDC, lpVectorInfo->nPolyFillMode );
|
|
break;
|
|
|
|
case SO_TEXTCHAREXTRA:
|
|
lpVectorInfo->nTextCharExtra = *(lpInt);
|
|
VUSetTextCharacterExtra ( hDC, lpVectorInfo->nTextCharExtra );
|
|
break;
|
|
|
|
case SO_DRAWMODE:
|
|
lpVectorInfo->nROP2 = *(lpInt);
|
|
VUSetROP2 ( hDC, lpVectorInfo->nROP2 );
|
|
break;
|
|
|
|
case SO_TEXTCOLOR:
|
|
if ( lpVectorInfo->bRgbToPalette )
|
|
{
|
|
SOCOLORREF Color;
|
|
Color = *(SOCOLORREF VWPTR *)lpData;
|
|
if ( !lpVectorInfo->bFinalPalette )
|
|
AddToPalette ( hDC, lpDisplay, &Color );
|
|
Color |= 0x02000000L;
|
|
lpData = (LPBYTE)(&Color);
|
|
}
|
|
lpVectorInfo->TextColor = *(SOCOLORREF VWPTR *)lpData;
|
|
VUSetTextColor ( hDC, lpVectorInfo->TextColor );
|
|
break;
|
|
|
|
case SO_BKMODE:
|
|
lpVectorInfo->nBkMode = *(lpInt);
|
|
VUSetBkMode ( hDC, lpVectorInfo->nBkMode );
|
|
break;
|
|
|
|
case SO_BKCOLOR:
|
|
lpVectorInfo->BkColor = *(SOCOLORREF VWPTR *)lpData;
|
|
VUSetBkColor ( hDC, lpVectorInfo->BkColor );
|
|
break;
|
|
|
|
case SO_OBJECTTRANSFORM:
|
|
lpData += sizeof(SHORT);
|
|
lpVectorInfo->ObjectTransform.nAllocUsed = 0;
|
|
lpVectorInfo->ObjectTransform.nTotalTransforms = 0;
|
|
PushTransform ( lpVectorInfo, &lpVectorInfo->ObjectTransform, *lpInt, lpData );
|
|
SetupTransform ( lpVectorInfo );
|
|
break;
|
|
|
|
case SO_CLIPMODE:
|
|
lpVectorInfo->wClipMode = *(LPWORD)lpData;
|
|
SetClipMode ( hDC, lpVectorInfo, lpDisplay );
|
|
break;
|
|
|
|
case SO_POINTRELATION:
|
|
lpVectorInfo->nPointRelation = *(lpInt);
|
|
break;
|
|
|
|
case SO_MPARAINDENT:
|
|
lpVectorInfo->Frame.ParaIndents = *(PSOMPARAINDENTS)lpData;
|
|
lpVectorInfo->Frame.RightWrap = OIMABS ( lpVectorInfo->Frame.FrameInfo.BoundingRect.right-lpVectorInfo->Frame.FrameInfo.BoundingRect.left);
|
|
lpVectorInfo->Frame.RightWrap -= lpVectorInfo->Frame.ParaIndents.RightIndent;
|
|
break;
|
|
|
|
case SO_MPARASPACING:
|
|
lpVectorInfo->Frame.ParaSpacing = *(PSOMPARASPACING)lpData;
|
|
break;
|
|
|
|
case SO_MPARAALIGN:
|
|
lpVectorInfo->Frame.ParaAlign = *(LPWORD)lpData;
|
|
break;
|
|
|
|
default:
|
|
return(0);
|
|
break;
|
|
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
/* START HERE GEOFF */
|
|
SHORT OIMFixupFrameInfo ( hDC, lpVectorInfo )
|
|
HDC hDC;
|
|
LPVECTORINFO lpVectorInfo;
|
|
{
|
|
PSORECT lpRect;
|
|
PSOFRAMEINFO lpFrameInfo;
|
|
SOPOINT Center;
|
|
LONG Radius;
|
|
SOANGLE Angle;
|
|
LONG Width, Height;
|
|
LONG BoundHeight;
|
|
LONG NCos, NSin;
|
|
lpFrameInfo = &lpVectorInfo->Frame.FrameInfo;
|
|
lpRect = &lpFrameInfo->BoundingRect;
|
|
|
|
Center.x = MIDPOINT ( lpRect->left, lpRect->right );
|
|
Center.y = MIDPOINT ( lpRect->top, lpRect->bottom );
|
|
|
|
BoundHeight = OIMABS(lpFrameInfo->BoundingRect.top - lpFrameInfo->BoundingRect.bottom);
|
|
Width = lpFrameInfo->OriginalWidth;
|
|
NCos = cosval(lpFrameInfo->RotationAngle);
|
|
NSin = sinval(lpFrameInfo->RotationAngle);
|
|
if ( NCos == 0 )
|
|
{
|
|
Width = lpRect->bottom - lpRect->top;
|
|
Height = lpRect->right - lpRect->left;
|
|
}
|
|
else if ( Width != 0 )
|
|
{
|
|
Height = (SHORT)(((BoundHeight - (NSin*Width)/10000L) * 10000L) / NCos);
|
|
}
|
|
else
|
|
{
|
|
Radius = (LONG)GetDistance ( lpVectorInfo, &Center, &lpFrameInfo->ReferencePoint );
|
|
Angle = GetAngle ( lpVectorInfo, &Center, &lpFrameInfo->ReferencePoint );
|
|
Angle -= lpFrameInfo->RotationAngle;
|
|
Width = (SHORT)(Radius*(LONG)cosval(Angle)/10000L)*2;
|
|
Height = (SHORT)(Radius*(LONG)sinval(Angle)/10000L)*2;
|
|
}
|
|
Width = OIMABS (Width);
|
|
Height = OIMABS(Height);
|
|
lpRect->left = Center.x - (SHORT)(Width/2)*lpVectorInfo->XDirection;
|
|
lpRect->top = Center.y - (SHORT)(Height/2)*lpVectorInfo->YDirection;
|
|
lpRect->right = Center.x + (SHORT)(Width/2)*lpVectorInfo->XDirection;
|
|
lpRect->bottom = Center.y + (SHORT)(Height/2)*lpVectorInfo->YDirection;
|
|
|
|
return(1);
|
|
}
|
|
|
|
SHORT SetupFrameTransform ( lpVectorInfo )
|
|
LPVECTORINFO lpVectorInfo;
|
|
{
|
|
PSOTRANSFORM lpXForm;
|
|
LPBYTE lpData;
|
|
LPWRAPITEM lpWrapItem;
|
|
lpData = UTGlobalLock(lpVectorInfo->GenTransform.hTransforms);
|
|
if ( lpData == NULL )
|
|
return(0);
|
|
lpData += lpVectorInfo->Frame.TransformOffset + sizeof(SHORT);
|
|
lpXForm = (PSOTRANSFORM) lpData;
|
|
lpWrapItem = (LPWRAPITEM)UTGlobalLock(lpVectorInfo->Frame.WrapInfo.hItems);
|
|
lpWrapItem += lpVectorInfo->Frame.WrapInfo.CurWrapItem;
|
|
lpXForm->xOffset = lpVectorInfo->Frame.FrameInfo.BoundingRect.left;
|
|
lpXForm->xOffset += lpWrapItem->PosX * lpVectorInfo->XDirection;
|
|
lpXForm->yOffset = lpVectorInfo->Frame.FrameInfo.BoundingRect.top;
|
|
lpXForm->yOffset += lpWrapItem->PosY * lpVectorInfo->YDirection;
|
|
lpVectorInfo->Frame.CurY = lpWrapItem->PosY;
|
|
UTGlobalUnlock(lpVectorInfo->Frame.WrapInfo.hItems);
|
|
UTGlobalUnlock(lpVectorInfo->GenTransform.hTransforms);
|
|
return(1);
|
|
}
|
|
|
|
SHORT OIMUpdateWrap ( lpVectorInfo, nStartLineItem, nLeft, nCur, nRight, nY, bHardWrap )
|
|
LPVECTORINFO lpVectorInfo;
|
|
SHORT nStartLineItem;
|
|
SHORT nLeft;
|
|
SHORT nCur;
|
|
SHORT nRight;
|
|
SHORT nY;
|
|
BOOL bHardWrap;
|
|
{
|
|
LPWRAPINFO lpWrapInfo;
|
|
LPWRAPITEM lpWrapItem;
|
|
SHORT nX, nA;
|
|
|
|
nX = nA = 0;
|
|
lpWrapInfo = &lpVectorInfo->Frame.WrapInfo;
|
|
if ( nStartLineItem < lpWrapInfo->nCount )
|
|
{
|
|
lpWrapItem = (LPWRAPITEM)UTGlobalLock(lpWrapInfo->hItems);
|
|
lpWrapItem += nStartLineItem;
|
|
switch (lpVectorInfo->Frame.ParaAlign)
|
|
{
|
|
case SO_ALIGNRIGHT:
|
|
nX = nRight - nCur;
|
|
break;
|
|
case SO_ALIGNCENTER:
|
|
nX = (nRight - nCur) / 2;
|
|
break;
|
|
case SO_ALIGNJUSTIFY:
|
|
if ( lpWrapInfo->nCount > nStartLineItem && !bHardWrap)
|
|
nA = (nRight - nCur)/(lpWrapInfo->nCount - nStartLineItem);
|
|
break;
|
|
}
|
|
for ( ; nStartLineItem < lpWrapInfo->nCount; nStartLineItem++ )
|
|
{
|
|
lpWrapItem->PosX += nX;
|
|
nX += nA;
|
|
lpWrapItem->PosY += nY;
|
|
lpWrapItem++;
|
|
}
|
|
UTGlobalUnlock(lpWrapInfo->hItems);
|
|
}
|
|
return(nStartLineItem);
|
|
}
|
|
|
|
SHORT OIMAddWrap ( lpWrapInfo, nX, nY, pStart, pEnd )
|
|
LPWRAPINFO lpWrapInfo;
|
|
SHORT nX;
|
|
SHORT nY;
|
|
LPBYTE pStart;
|
|
LPBYTE pEnd;
|
|
{
|
|
SHORT nCount;
|
|
LPWRAPITEM lpWrapItem;
|
|
if ( lpWrapInfo->nCount >= lpWrapInfo->nMax )
|
|
{
|
|
nCount = lpWrapInfo->nCount + NWRAPALLOCS;
|
|
if ( lpWrapInfo->hItems == NULL )
|
|
{
|
|
if ( ( lpWrapInfo->hItems = UTGlobalAlloc( sizeof(WRAPITEM)*nCount)) == NULL )
|
|
return(0);
|
|
}
|
|
else
|
|
{
|
|
HANDLE hMem;
|
|
if ( ( hMem = UTGlobalReAlloc( lpWrapInfo->hItems, sizeof(WRAPITEM)*nCount )) == NULL )
|
|
return(0);
|
|
lpWrapInfo->hItems = hMem;
|
|
}
|
|
lpWrapInfo->nMax = nCount;
|
|
}
|
|
lpWrapItem = (LPWRAPITEM)UTGlobalLock(lpWrapInfo->hItems);
|
|
lpWrapItem += lpWrapInfo->nCount;
|
|
lpWrapItem->PosX = nX;
|
|
lpWrapItem->PosY = nY;
|
|
lpWrapItem->pStart = pStart;
|
|
lpWrapItem->pEnd = pEnd;
|
|
UTGlobalUnlock(lpWrapInfo->hItems);
|
|
lpWrapInfo->nCount++;
|
|
return(lpWrapInfo->nCount);
|
|
}
|
|
|
|
SHORT OIMWrapPara ( lpDisplay, lpVectorInfo, lpChunkData )
|
|
POIM_DISPLAY lpDisplay;
|
|
LPVECTORINFO lpVectorInfo;
|
|
LPBYTE lpChunkData;
|
|
{
|
|
LPVRECORDHEADER lpVectorRecord;
|
|
SORECT SymbolBounds;
|
|
SHORT SymbolWidth, SymbolHeight;
|
|
SHORT LeftX, RightX, CurX, CurY, MaxLineHeight, MaxLineAscent;
|
|
DWORD dwTextExtent;
|
|
HDC hScreenIC;
|
|
HFONT hOldFont, hNewFont;
|
|
|
|
LPSTR lpString, lpStart, lpBreak, lpEnd;
|
|
SHORT nWidth, nHeight, nCount;
|
|
BOOL NotDone;
|
|
SHORT nStartLineItem;
|
|
SHORT nAlignOffset;
|
|
SHORT LineSpaceAdjust, ParaSpaceAdjust;
|
|
LPBYTE lpData;
|
|
LPSHORT lpInt;
|
|
LPWRAPINFO lpWrapInfo;
|
|
LPWRAPITEM lpWrapItem;
|
|
SOLOGFONT LogFont;
|
|
PSOLOGFONT pCurFont;
|
|
|
|
SHORT nOldMapMode;
|
|
OIMFONTSIZEINFO FontSizeInfo;
|
|
|
|
hScreenIC = VUGetScreenDC(lpDisplay);
|
|
nOldMapMode = VUSetMapMode( hScreenIC, VUMM_TEXT );
|
|
|
|
hOldFont = hNewFont = NULL;
|
|
|
|
if ( lpVectorInfo->FontTable.nObjectsSoFar )
|
|
{
|
|
hOldFont = lpVectorInfo->FontTable.hObject[0];
|
|
|
|
// Select the most recent font, but turn off any rotation.
|
|
pCurFont = (PSOLOGFONT)(lpVectorInfo->FontTable.lpObjects);
|
|
LogFont = *pCurFont;
|
|
LogFont.lfEscapement = 0; // Rotate this, pal.
|
|
hNewFont = CreateFontRtnNP( hScreenIC, (LPBYTE)&LogFont );
|
|
|
|
VUSelectObject ( hScreenIC, hNewFont );
|
|
}
|
|
|
|
VUGetFontSizeInfo( hScreenIC, &FontSizeInfo );
|
|
lpWrapInfo = &lpVectorInfo->Frame.WrapInfo;
|
|
if ( lpWrapInfo->CurWrapItem < lpWrapInfo->nCount )
|
|
{
|
|
lpWrapItem = (LPWRAPITEM)UTGlobalLock(lpWrapInfo->hItems);
|
|
lpWrapItem += lpWrapInfo->CurWrapItem;
|
|
LeftX = CurX = lpWrapItem->PosX;
|
|
CurY = lpVectorInfo->Frame.CurY - lpWrapItem->PosY;
|
|
MaxLineHeight = lpWrapItem->PosY;
|
|
MaxLineAscent = MaxLineHeight;
|
|
UTGlobalUnlock(lpWrapInfo->hItems);
|
|
}
|
|
else
|
|
{
|
|
LeftX = CurX = lpVectorInfo->Frame.ParaIndents.FirstLineIndent;
|
|
CurY = lpVectorInfo->Frame.CurY;
|
|
MaxLineHeight = 0;
|
|
MaxLineAscent = 0;
|
|
}
|
|
RightX = lpVectorInfo->Frame.RightWrap;
|
|
LineSpaceAdjust = lpVectorInfo->Frame.ParaSpacing.LineSpaceAdjust;
|
|
ParaSpaceAdjust = lpVectorInfo->Frame.ParaSpacing.ParaSpaceAdjust;
|
|
nStartLineItem = 0;
|
|
nAlignOffset = 0;
|
|
|
|
lpVectorRecord = (LPVRECORDHEADER)lpChunkData;
|
|
lpWrapInfo->nCount = 0;
|
|
|
|
NotDone = TRUE;
|
|
while ( NotDone )
|
|
{
|
|
lpData = (LPBYTE)(lpVectorRecord) + sizeof ( VRECORDHEADER );
|
|
lpInt = (LPSHORT)lpData;
|
|
|
|
switch ( lpVectorRecord->nItemId )
|
|
{
|
|
case SO_SELECTFONT:
|
|
if ( hNewFont )
|
|
{
|
|
VUSelectObject ( hScreenIC, hOldFont );
|
|
VUDeleteObject (lpDisplay, hNewFont );
|
|
}
|
|
|
|
hNewFont = CreateFontRtnNP( hScreenIC, lpData );
|
|
VUSelectObject ( hScreenIC, hNewFont );
|
|
|
|
VUGetFontSizeInfo( hScreenIC, &FontSizeInfo );
|
|
break;
|
|
|
|
case SO_BEGINSYMBOL:
|
|
SymbolBounds = *(PSORECT)lpData;
|
|
if( lpVectorInfo->bObjectTransform )
|
|
{
|
|
TransformPoints ( lpVectorInfo, &lpVectorInfo->ObjectTransform,(PSOPOINT)&SymbolBounds, (PSOPOINT)&SymbolBounds, 2 );
|
|
}
|
|
SymbolWidth = OIMABS ( SymbolBounds.right - SymbolBounds.left );
|
|
SymbolHeight = OIMABS ( SymbolBounds.bottom - SymbolBounds.top );
|
|
if ( CurX + SymbolWidth >= RightX )
|
|
{
|
|
nStartLineItem = OIMUpdateWrap ( lpVectorInfo, nStartLineItem, LeftX, CurX, RightX, MaxLineAscent, 0 );
|
|
CurX = lpVectorInfo->Frame.ParaIndents.LeftIndent;
|
|
if ( LineSpaceAdjust )
|
|
CurY += (SHORT)(((LONG)MaxLineHeight*(LONG)LineSpaceAdjust)/100L);
|
|
else
|
|
CurY += MaxLineHeight;
|
|
MaxLineHeight = 0;
|
|
MaxLineAscent = 0;
|
|
}
|
|
|
|
if ( SymbolHeight > MaxLineAscent )
|
|
{
|
|
MaxLineHeight = MaxLineHeight + (SymbolHeight - MaxLineAscent);
|
|
MaxLineAscent = SymbolHeight;
|
|
}
|
|
OIMAddWrap ( lpWrapInfo, CurX, CurY, lpChunkData, lpChunkData );
|
|
CurX += SymbolWidth;
|
|
break;
|
|
|
|
case SO_TEXTINPARA:
|
|
{
|
|
BOOL TabFound;
|
|
|
|
lpString = lpData + sizeof(SHORT);
|
|
nCount = *lpInt;
|
|
lpEnd = lpString + nCount;
|
|
lpStart = lpString;
|
|
lpBreak = lpStart;
|
|
while ( lpStart < lpEnd )
|
|
{
|
|
TabFound = FALSE;
|
|
|
|
for ( ; (*lpBreak != ' ') && (*lpBreak != 0x09) && (lpBreak != lpEnd); lpBreak++ )
|
|
;
|
|
for ( ; (*lpBreak == ' ') && (lpBreak != lpEnd); lpBreak++ )
|
|
;
|
|
|
|
// Add for tab to left indent - DJM
|
|
if (*lpBreak == 0x09)
|
|
{
|
|
// *lpBreak = 0x20;
|
|
// lpBreak++;
|
|
TabFound = TRUE;
|
|
// dwTextExtent = GetTextExtent ( hScreenIC, lpStart, lpBreak - lpStart );
|
|
dwTextExtent = (DWORD) VUGetTextWidth( hScreenIC, lpStart, (SHORT)(lpBreak - lpStart) );
|
|
if (CurX < lpVectorInfo->Frame.ParaIndents.LeftIndent)
|
|
nWidth = (SHORT)(lpVectorInfo->Frame.ParaIndents.LeftIndent - CurX);
|
|
else
|
|
nWidth = (SHORT)(dwTextExtent & 0x000ffff);
|
|
}
|
|
else
|
|
{
|
|
dwTextExtent = (DWORD) VUGetTextWidth( hScreenIC, lpStart, (SHORT)(lpBreak - lpStart) );
|
|
nWidth = (SHORT)(dwTextExtent & 0x000ffff);
|
|
}
|
|
nHeight = FontSizeInfo.height;
|
|
if ( CurX + nWidth >= RightX )
|
|
{
|
|
nStartLineItem = OIMUpdateWrap ( lpVectorInfo, nStartLineItem, LeftX, CurX, RightX, MaxLineAscent, 0 );
|
|
CurX = lpVectorInfo->Frame.ParaIndents.LeftIndent;
|
|
if ( LineSpaceAdjust )
|
|
CurY += (SHORT)(((LONG)MaxLineHeight*(LONG)LineSpaceAdjust)/100L);
|
|
else
|
|
CurY += MaxLineHeight;
|
|
MaxLineHeight = 0;
|
|
MaxLineAscent = 0;
|
|
}
|
|
|
|
if ( nHeight > MaxLineHeight )
|
|
MaxLineHeight = nHeight;
|
|
if ( FontSizeInfo.ascent > MaxLineAscent )
|
|
MaxLineAscent = FontSizeInfo.ascent;
|
|
|
|
OIMAddWrap ( lpWrapInfo, CurX, CurY, lpStart, lpBreak );
|
|
if (TabFound)
|
|
lpBreak++;
|
|
|
|
CurX += nWidth;
|
|
lpStart = lpBreak;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SO_VECTORENDOFCHUNK:
|
|
nStartLineItem = OIMUpdateWrap ( lpVectorInfo, nStartLineItem, LeftX, CurX, RightX, MaxLineAscent, 1 );
|
|
/* Save info for next wrap of text in wrap structure */
|
|
OIMAddWrap ( lpWrapInfo, CurX, MaxLineAscent, lpChunkData, lpChunkData );
|
|
NotDone = FALSE;
|
|
break;
|
|
|
|
case SO_PARAEND:
|
|
|
|
nStartLineItem = OIMUpdateWrap ( lpVectorInfo, nStartLineItem, LeftX, CurX, RightX, MaxLineAscent, 1 );
|
|
CurX = lpVectorInfo->Frame.ParaIndents.FirstLineIndent;
|
|
if ( MaxLineHeight == 0 )
|
|
MaxLineHeight = FontSizeInfo.height;
|
|
|
|
if ( ParaSpaceAdjust )
|
|
CurY += (SHORT)(((LONG)MaxLineHeight*(LONG)ParaSpaceAdjust)/100L);
|
|
else
|
|
CurY += MaxLineHeight;
|
|
OIMAddWrap ( lpWrapInfo, CurX, CurY, lpChunkData, lpChunkData );
|
|
NotDone = FALSE;
|
|
break;
|
|
}
|
|
if ( NotDone )
|
|
{
|
|
lpChunkData += sizeof(VRECORDHEADER)+lpVectorRecord->wDataSize;
|
|
lpVectorRecord = (LPVRECORDHEADER)lpChunkData;
|
|
}
|
|
}
|
|
|
|
VUSetMapMode( hScreenIC, nOldMapMode );
|
|
|
|
VUSelectObject ( hScreenIC, hOldFont );
|
|
if ( hNewFont )
|
|
VUDeleteObject (lpDisplay, hNewFont );
|
|
|
|
VUReleaseScreenDC(lpDisplay,hScreenIC);
|
|
|
|
lpWrapInfo->WrappedPara = TRUE;
|
|
lpWrapInfo->CurWrapItem = 0;
|
|
return(1);
|
|
}
|
|
|
|
|
|
SHORT OutputParaText ( hDC, lpVectorInfo, lpString, nCount )
|
|
HDC hDC;
|
|
LPVECTORINFO lpVectorInfo;
|
|
LPSTR lpString;
|
|
SHORT nCount;
|
|
{
|
|
LPSTR lpStart, lpEnd;
|
|
SOPOINT Pt;
|
|
LPWRAPITEM lpWrapItem;
|
|
SHORT CurY;
|
|
|
|
lpWrapItem = (LPWRAPITEM)UTGlobalLock(lpVectorInfo->Frame.WrapInfo.hItems);
|
|
lpWrapItem += lpVectorInfo->Frame.WrapInfo.CurWrapItem;
|
|
lpEnd = lpString + nCount;
|
|
|
|
while ( lpWrapItem->pStart >= lpString && lpWrapItem->pStart < lpEnd )
|
|
{
|
|
SetupFrameTransform ( lpVectorInfo );
|
|
lpStart = lpWrapItem->pStart;
|
|
CurY = lpWrapItem->PosY;
|
|
|
|
if (lpVectorInfo->Frame.ParaAlign != SO_ALIGNJUSTIFY)
|
|
{
|
|
while (((lpWrapItem+1)->PosY == CurY) && ((lpWrapItem+1)->pStart < lpEnd))
|
|
{
|
|
lpVectorInfo->Frame.WrapInfo.CurWrapItem++;
|
|
lpWrapItem++;
|
|
}
|
|
}
|
|
Pt.x = 0;
|
|
Pt.y = 0;
|
|
|
|
if( lpVectorInfo->bObjectTransform )
|
|
TransformPoints ( lpVectorInfo, &lpVectorInfo->ObjectTransform,(PSOPOINT)&Pt, (PSOPOINT)&Pt, 1 );
|
|
if( lpVectorInfo->bGenTransform )
|
|
TransformPoints ( lpVectorInfo, &lpVectorInfo->GenTransform, (PSOPOINT)&Pt, (PSOPOINT)&Pt, 1 );
|
|
|
|
VUSetTextAlign ( hDC, SOTA_BASELINE | SOTA_LEFT );
|
|
VUTextOut ( hDC, Pt.x, Pt.y, lpStart, (lpWrapItem->pEnd - lpStart ) );
|
|
lpVectorInfo->Frame.WrapInfo.CurWrapItem++;
|
|
lpWrapItem++;
|
|
}
|
|
|
|
UTGlobalUnlock(lpVectorInfo->Frame.WrapInfo.hItems);
|
|
return(1);
|
|
}
|
|
/* END HERE GEOFF */
|
|
|
|
|
|
SHORT VWPTR *ArcInfoToPoints ( lpVectorInfo, lpArcInfo, lpPoint )
|
|
LPVECTORINFO lpVectorInfo;
|
|
PSOARCINFO lpArcInfo;
|
|
PSOPOINT lpPoint;
|
|
{
|
|
SHORT xc, yc;
|
|
LONG xr, yr;
|
|
|
|
xc = MIDPOINT( lpArcInfo->Rect.left, lpArcInfo->Rect.right );
|
|
yc = MIDPOINT( lpArcInfo->Rect.top, lpArcInfo->Rect.bottom);
|
|
/*
|
|
| Note that the calculation of the x & y radius below will automatically
|
|
| resolve the XDirection and YDirection considerations when calculating
|
|
| the points.
|
|
*/
|
|
xr = (LONG)(lpArcInfo->Rect.right - xc);
|
|
yr = (LONG)(lpArcInfo->Rect.bottom - yc);
|
|
lpPoint[0].x = lpArcInfo->Rect.left;
|
|
lpPoint[0].y = lpArcInfo->Rect.top;
|
|
lpPoint[1].x = lpArcInfo->Rect.right;
|
|
lpPoint[1].y = lpArcInfo->Rect.bottom;
|
|
lpPoint[2].x = xc + (SHORT)(xr*((LONG)cosval(lpArcInfo->StartAngle))/10000L);
|
|
lpPoint[2].y = yc - (SHORT)(yr*((LONG)sinval(lpArcInfo->StartAngle))/10000L);
|
|
lpPoint[3].x = xc + (SHORT)(xr*((LONG)cosval(lpArcInfo->EndAngle))/10000L);
|
|
lpPoint[3].y = yc - (SHORT)(yr*((LONG)sinval(lpArcInfo->EndAngle))/10000L);
|
|
return ( (SHORT VWPTR *)(lpPoint) );
|
|
}
|
|
|
|
SHORT OIMCheckPointBuffer ( lpPBufInfo, nCount )
|
|
LPPOINTBUF lpPBufInfo;
|
|
SHORT nCount;
|
|
{
|
|
if ( nCount > lpPBufInfo->nMax )
|
|
{
|
|
nCount = nCount + SOMAXPOINTS - (nCount % SOMAXPOINTS);
|
|
if ( lpPBufInfo->hPoints == NULL )
|
|
{
|
|
if ( ( lpPBufInfo->hPoints = UTGlobalAlloc(sizeof(SOPOINT)*nCount)) == NULL )
|
|
UTBailOut( SCCCHERR_OUTOFMEMORY );
|
|
}
|
|
else
|
|
{
|
|
HANDLE hMem;
|
|
if ( ( hMem = UTGlobalReAlloc( lpPBufInfo->hPoints, sizeof(SOPOINT)*nCount)) == NULL )
|
|
UTBailOut( SCCCHERR_OUTOFMEMORY );
|
|
lpPBufInfo->hPoints = hMem;
|
|
}
|
|
lpPBufInfo->nMax = nCount;
|
|
}
|
|
return(lpPBufInfo->nMax);
|
|
}
|
|
|
|
VOID OIMPolyObject ( hDC, lpVectorInfo, lpPolyInfo, lpPolyPoints, bOutput )
|
|
HDC hDC;
|
|
LPVECTORINFO lpVectorInfo;
|
|
PSOPOLYINFO lpPolyInfo;
|
|
LPPOINTBUF lpPolyPoints;
|
|
BOOL bOutput;
|
|
{
|
|
PSOPOINT lpPoints, lpBezierPoints;
|
|
SHORT i, nCount, nBCount;
|
|
lpPoints = (PSOPOINT)UTGlobalLock ( lpPolyPoints->hPoints );
|
|
nCount = lpPolyPoints->nCount;
|
|
switch(lpPolyInfo->wFormat)
|
|
{
|
|
case SOPT_CPPOLYLINE:
|
|
case SOPT_POLYLINE:
|
|
if ( bOutput )
|
|
VUPolyline ( hDC, lpPoints, (SHORT)(lpPolyPoints->nCount) );
|
|
break;
|
|
|
|
case SOPT_CPPOLYGON:
|
|
case SOPT_POLYGON:
|
|
if ( bOutput )
|
|
VUPolygon ( hDC, lpPoints, lpPolyPoints->nCount );
|
|
break;
|
|
|
|
case SOPT_SPLINEOPEN:
|
|
/* Translate the spline points into an equivalent bezier */
|
|
UTGlobalUnlock ( lpPolyPoints->hPoints );
|
|
OIMSplineToBezier ( lpVectorInfo, lpPolyInfo, lpPolyPoints );
|
|
lpPoints = (PSOPOINT)UTGlobalLock ( lpPolyPoints->hPoints );
|
|
nCount = lpPolyPoints->nCount;
|
|
/* Display as an open bezier */
|
|
case SOPT_BEZIEROPEN:
|
|
|
|
lpVectorInfo->BezierPoints.nCount = 0;
|
|
for ( i=0; i < nCount - 3; i+=3 )
|
|
{
|
|
nBCount = MAXSMOOTHFACTOR;
|
|
if( !OIMCheckPointBuffer ( &(lpVectorInfo->BezierPoints),
|
|
(SHORT)(lpVectorInfo->BezierPoints.nCount+nBCount) ))
|
|
break;
|
|
lpBezierPoints = (PSOPOINT)UTGlobalLock ( lpVectorInfo->BezierPoints.hPoints );
|
|
lpBezierPoints += lpVectorInfo->BezierPoints.nCount;
|
|
nBCount = OIMBezierCurve ( hDC, lpPoints[i].x, lpPoints[i].y,
|
|
lpPoints[i+1].x, lpPoints[i+1].y,
|
|
lpPoints[i+2].x, lpPoints[i+2].y,
|
|
lpPoints[i+3].x, lpPoints[i+3].y,
|
|
lpBezierPoints,
|
|
nBCount );
|
|
if ( bOutput )
|
|
{
|
|
VUPolyline ( hDC, lpBezierPoints, nBCount );
|
|
lpVectorInfo->BezierPoints.nCount = 0;
|
|
}
|
|
else
|
|
lpVectorInfo->BezierPoints.nCount += nBCount;
|
|
UTGlobalUnlock ( lpVectorInfo->BezierPoints.hPoints );
|
|
}
|
|
|
|
break;
|
|
|
|
case SOPT_SPLINECLOSE:
|
|
/* Translate the spline points into an equivalent bezier */
|
|
UTGlobalUnlock ( lpPolyPoints->hPoints );
|
|
OIMSplineToBezier ( lpVectorInfo, lpPolyInfo, lpPolyPoints );
|
|
lpPoints = (PSOPOINT)UTGlobalLock ( lpPolyPoints->hPoints );
|
|
nCount = lpPolyPoints->nCount;
|
|
/* Display as a closed bezier */
|
|
case SOPT_BEZIERCLOSE:
|
|
lpVectorInfo->BezierPoints.nCount = 0;
|
|
for ( i=0; i < nCount - 3; i+=3 )
|
|
{
|
|
nBCount = MAXSMOOTHFACTOR;
|
|
if( !OIMCheckPointBuffer ( &(lpVectorInfo->BezierPoints),
|
|
(SHORT)(lpVectorInfo->BezierPoints.nCount+nBCount+1) ))
|
|
break;
|
|
lpBezierPoints = (PSOPOINT)UTGlobalLock ( lpVectorInfo->BezierPoints.hPoints );
|
|
lpBezierPoints += lpVectorInfo->BezierPoints.nCount;
|
|
lpVectorInfo->BezierPoints.nCount +=
|
|
OIMBezierCurve ( hDC, lpPoints[i].x, lpPoints[i].y,
|
|
lpPoints[i+1].x, lpPoints[i+1].y,
|
|
lpPoints[i+2].x, lpPoints[i+2].y,
|
|
lpPoints[i+3].x, lpPoints[i+3].y,
|
|
lpBezierPoints,
|
|
nBCount );
|
|
UTGlobalUnlock ( lpVectorInfo->BezierPoints.hPoints );
|
|
}
|
|
lpBezierPoints = (PSOPOINT)UTGlobalLock ( lpVectorInfo->BezierPoints.hPoints );
|
|
lpPoints = lpBezierPoints;
|
|
lpPoints += lpVectorInfo->BezierPoints.nCount-1;
|
|
/* straight line close bezier if not already closed */
|
|
if (lpPoints->x != lpBezierPoints->x || lpPoints->y != lpBezierPoints->y)
|
|
{
|
|
lpVectorInfo->BezierPoints.nCount++;
|
|
lpPoints++;
|
|
*lpPoints = *lpBezierPoints;
|
|
}
|
|
if ( bOutput )
|
|
VUPolygon ( hDC, (PSOPOINT)lpBezierPoints, lpVectorInfo->BezierPoints.nCount );
|
|
UTGlobalUnlock ( lpVectorInfo->BezierPoints.hPoints );
|
|
break;
|
|
|
|
|
|
}
|
|
UTGlobalUnlock ( lpPolyPoints->hPoints );
|
|
}
|
|
|
|
WORD OIMSplineToBezier ( lpVectorInfo, lpPolyInfo, lpPolyPoints )
|
|
LPVECTORINFO lpVectorInfo;
|
|
PSOPOLYINFO lpPolyInfo;
|
|
LPPOINTBUF lpPolyPoints;
|
|
{
|
|
SHORT i, x, y, nCount;
|
|
PSOPOINT lpPoints;
|
|
|
|
nCount = lpVectorInfo->PolyPoints.nCount;
|
|
if( OIMCheckPointBuffer ( &(lpVectorInfo->PolyPoints), (SHORT)(nCount*3+1)))
|
|
{
|
|
lpPoints = (PSOPOINT)UTGlobalLock ( lpVectorInfo->PolyPoints.hPoints );
|
|
/* Shift spline points to make room for bezier control points */
|
|
for ( i=nCount-1; i > 0; i-- )
|
|
{
|
|
lpPoints[i*3] = lpPoints[i];
|
|
}
|
|
/* Define control points */
|
|
if ( lpPolyInfo->wFormat == SOPT_SPLINEOPEN )
|
|
{
|
|
lpPolyInfo->wFormat == SOPT_BEZIEROPEN;
|
|
}
|
|
else
|
|
{
|
|
lpPolyInfo->wFormat == SOPT_BEZIERCLOSE;
|
|
}
|
|
i = (nCount-1)*3; /* end spline point */
|
|
x = SplineEnd ( lpPoints[0].x, lpPoints[3].x, lpPoints[6].x );
|
|
y = SplineEnd ( lpPoints[0].y, lpPoints[3].y, lpPoints[6].y );
|
|
lpPoints[1].x = lpPoints[0].x - x;
|
|
lpPoints[1].y = lpPoints[0].y - y;
|
|
x = SplineEnd ( lpPoints[i].x, lpPoints[i-3].x, lpPoints[i-6].x );
|
|
y = SplineEnd ( lpPoints[i].y, lpPoints[i-3].y, lpPoints[i-6].y );
|
|
lpPoints[i-1].x = lpPoints[i].x - x;
|
|
lpPoints[i-1].y = lpPoints[i].y - y;
|
|
|
|
/* Now handle the middle spline points */
|
|
nCount = i+1;
|
|
for ( i=3; i < nCount-1; i+= 3 )
|
|
{
|
|
x = SplineFuse ( lpPoints[i-3].x, lpPoints[i].x, lpPoints[i+3].x );
|
|
y = SplineFuse ( lpPoints[i-3].y, lpPoints[i].y, lpPoints[i+3].y );
|
|
lpPoints[i-1].x = lpPoints[i].x - x;
|
|
lpPoints[i-1].y = lpPoints[i].y - y;
|
|
lpPoints[i+1].x = lpPoints[i].x + x;
|
|
lpPoints[i+1].y = lpPoints[i].y + y;
|
|
}
|
|
lpVectorInfo->PolyPoints.nCount = nCount;
|
|
UTGlobalUnlock ( lpVectorInfo->PolyPoints.hPoints );
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|
|
SHORT SplineFuse ( i1, i2, i3 )
|
|
SHORT i1;
|
|
SHORT i2;
|
|
SHORT i3;
|
|
{
|
|
return ( (i3-i1)/6 );
|
|
}
|
|
|
|
SHORT SplineEnd ( i1, i2, i3 )
|
|
SHORT i1;
|
|
SHORT i2;
|
|
SHORT i3;
|
|
{
|
|
return ( ( ( (3*(i1-i2)) - (i2-i3) ) / 6) );
|
|
}
|
|
|
|
SHORT OIMBezierCurve ( hDC, X1, Y1, X2, Y2, X3, Y3, X4, Y4, lpBezier, nMaxPoints )
|
|
HDC hDC;
|
|
SHORT X1;
|
|
SHORT Y1;
|
|
SHORT X2;
|
|
SHORT Y2;
|
|
SHORT X3;
|
|
SHORT Y3;
|
|
SHORT X4;
|
|
SHORT Y4;
|
|
PSOPOINT lpBezier;
|
|
SHORT nMaxPoints;
|
|
{
|
|
LONG nIndex;
|
|
LONG nOptimumPoints;
|
|
LONG a, acubed, b, bcubed, c, ccubed, term2;
|
|
if ( X1 == X2 && Y1 == Y2 && X3 == X4 && Y3 == Y4 ) /* straight line */
|
|
{
|
|
lpBezier->x = X1;
|
|
lpBezier->y = Y1;
|
|
lpBezier++;
|
|
lpBezier->x = X4;
|
|
lpBezier->y = Y4;
|
|
return (2);
|
|
}
|
|
/*
|
|
| Calculate optimum points
|
|
*/
|
|
/*
|
|
#define abs(x) (((x)<0)?(-(x)):(x))
|
|
|
|
nOptimumPoints = (min(abs(X2-X1),abs(Y2-Y1))+min(abs(X3-X2),abs(Y3-Y2))
|
|
+min(abs(X4-X3),abs(Y4-Y3)));
|
|
if ( nOptimumPoints > nMaxPoints )
|
|
{
|
|
nOptimumPoints = nMaxPoints;
|
|
}
|
|
else
|
|
{
|
|
if ( nOptimumPoints < 5 )
|
|
nOptimumPoints = 5;
|
|
}
|
|
*/
|
|
nOptimumPoints = nMaxPoints;
|
|
|
|
c = nOptimumPoints-1;
|
|
ccubed = c * c * c;
|
|
for ( nIndex=0;nIndex < nOptimumPoints; nIndex++ )
|
|
{
|
|
a = nIndex;
|
|
acubed = a * a * a;
|
|
b = c - nIndex;
|
|
bcubed = b * b * b;
|
|
term2 = 3*a*b;
|
|
lpBezier->x = (SHORT)(((LONG)X1*bcubed + term2*((LONG)(X2*b)+(LONG)(X3*a)) + (LONG)X4*acubed)/ccubed);
|
|
lpBezier->y = (SHORT)(((LONG)Y1*bcubed + term2*((LONG)(Y2*b)+(LONG)(Y3*a)) + (LONG)Y4*acubed)/ccubed);
|
|
lpBezier++;
|
|
}
|
|
return ( (SHORT)nIndex );
|
|
}
|
|
|
|
|
|
VOID SelectObjectIndirect ( lpDisplay, hDC, lpTable, lpObject )
|
|
POIM_DISPLAY lpDisplay;
|
|
HDC hDC;
|
|
LPOBJECTTABLE lpTable;
|
|
VOID FAR *lpObject;
|
|
{
|
|
SHORT i;
|
|
HANDLE hObject;
|
|
LPBYTE lpTableObj;
|
|
|
|
lpTableObj = lpTable->lpObjects;
|
|
/* See if this object is already in the list */
|
|
for ( i=0; i < lpTable->nObjectsSoFar; i++ )
|
|
{
|
|
if ( UTmemcmp ( (LPBYTE)lpObject, lpTableObj, lpTable->wObjectSize) == 0)
|
|
break;
|
|
lpTableObj += lpTable->wObjectSize;
|
|
}
|
|
/* If object not found and list is full, clear out least recently used object */
|
|
if ( i == lpTable->nMaxObjects )
|
|
{
|
|
i--;
|
|
lpTableObj -= lpTable->wObjectSize;
|
|
lpTable->nObjectsSoFar = i;
|
|
VUDeleteObject (lpDisplay, lpTable->hObject[i] );
|
|
}
|
|
/* If not found, create a new object */
|
|
if ( i == lpTable->nObjectsSoFar )
|
|
{
|
|
hObject = (*lpTable->CreateRtn)(hDC,(LPBYTE)lpObject);
|
|
if ( hObject )
|
|
{
|
|
UTmemcpy ( lpTableObj, lpObject, lpTable->wObjectSize );
|
|
lpTable->hObject[i] = hObject;
|
|
lpTable->nObjectsSoFar++;
|
|
if ( i == 0 ) /* Select if first font created */
|
|
VUSelectObject ( hDC, lpTable->hObject[i] );
|
|
}
|
|
}
|
|
/* If not current object, select and move to top of list */
|
|
if ( i != 0 )
|
|
{
|
|
LPBYTE lpTop;
|
|
hObject = lpTable->hObject[i];
|
|
VUSelectObject ( hDC, hObject );
|
|
lpTop = lpTable->lpObjects;
|
|
UTmemmove ( lpTop+lpTable->wObjectSize, lpTop, i*(lpTable->wObjectSize) );
|
|
UTmemmove ( &lpTable->hObject[1], &lpTable->hObject[0], i*sizeof(HANDLE) );
|
|
UTmemcpy ( lpTop, lpObject, lpTable->wObjectSize );
|
|
lpTable->hObject[0] = hObject;
|
|
}
|
|
}
|
|
|
|
|
|
VOID OIMDisplayBkgdColor( hdc, BColor, lpDisplay )
|
|
HDC hdc;
|
|
COLORREF BColor;
|
|
POIM_DISPLAY lpDisplay;
|
|
{
|
|
LOGBRUSH LogBrush;
|
|
LOGPEN LogPen;
|
|
|
|
LogBrush.lbStyle = BS_SOLID;
|
|
LogPen.lopnStyle = PS_NULL;
|
|
LogPen.lopnWidth.x = LogPen.lopnWidth.y = 1;
|
|
/* For now background is white only, see what happens */
|
|
LogPen.lopnColor = BColor;
|
|
LogBrush.lbColor = BColor;
|
|
LogBrush.lbHatch = 0;
|
|
SelectObjectIndirect ( lpDisplay, hdc, &(lpDisplay->VectorInfo.PenTable), &LogPen );
|
|
SelectObjectIndirect ( lpDisplay, hdc, &(lpDisplay->VectorInfo.BrushTable), &LogBrush );
|
|
|
|
Rectangle ( hdc, lpDisplay->Image.bbox.left, lpDisplay->Image.bbox.top, lpDisplay->Image.bbox.right, lpDisplay->Image.bbox.bottom);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------
|
|
High End Drawing Functions
|
|
------------------------------------------------------------------*/
|
|
|
|
SHORT PushTransform ( lpVectorInfo, lpTransformInfo, nSrcCount, lpTransformData )
|
|
LPVECTORINFO lpVectorInfo;
|
|
LPTRANSFORMINFO lpTransformInfo;
|
|
SHORT nSrcCount;
|
|
LPBYTE lpTransformData;
|
|
{
|
|
LPBYTE lpDst;
|
|
SHORT i;
|
|
SHORT nSrcSize;
|
|
SHORT cosalpha, sinalpha;
|
|
PSOTRANSFORM lpTransform;
|
|
nSrcSize = sizeof(SHORT) + nSrcCount*sizeof(SOTRANSFORM);
|
|
if ( nSrcSize + lpTransformInfo->nAllocUsed > lpTransformInfo->nAllocSize )
|
|
{
|
|
lpTransformInfo->nAllocSize = nSrcSize + lpTransformInfo->nAllocUsed;
|
|
if ( lpTransformInfo->hTransforms == NULL )
|
|
{
|
|
if ( ( lpTransformInfo->hTransforms = UTGlobalAlloc(lpTransformInfo->nAllocSize)) == NULL )
|
|
return(0);
|
|
}
|
|
else
|
|
{
|
|
HANDLE hMem;
|
|
if ( ( hMem = UTGlobalReAlloc( lpTransformInfo->hTransforms, lpTransformInfo->nAllocSize)) == NULL )
|
|
return(0);
|
|
lpTransformInfo->hTransforms = hMem;
|
|
}
|
|
}
|
|
|
|
|
|
lpDst = UTGlobalLock ( lpTransformInfo->hTransforms );
|
|
lpDst += lpTransformInfo->nAllocUsed;
|
|
*(LPSHORT)lpDst = nSrcCount;
|
|
lpDst += sizeof(SHORT);
|
|
UTmemcpy ( lpDst, lpTransformData, nSrcSize-sizeof(SHORT) );
|
|
|
|
/* Turn rotation transforms into skew/scale combo's */
|
|
lpTransform = (PSOTRANSFORM)lpDst;
|
|
|
|
for ( i=0; i < nSrcCount; i++ )
|
|
{
|
|
if ( lpTransform->wTransformFlags & SOTF_ROTATE )
|
|
{
|
|
cosalpha = cosval(lpTransform->RotationAngle)*lpVectorInfo->XDirection;
|
|
sinalpha = sinval(lpTransform->RotationAngle)*lpVectorInfo->YDirection;
|
|
lpTransform->xScale = SOSETRATIO(cosalpha,10000);
|
|
lpTransform->yScale = SOSETRATIO(cosalpha,10000);
|
|
lpTransform->xSkew = SOSETRATIO(sinalpha,10000);
|
|
lpTransform->ySkew = SOSETRATIO(-sinalpha,10000);
|
|
lpTransform->wTransformFlags |= SOTF_XSCALE | SOTF_YSCALE | SOTF_XSKEW | SOTF_YSKEW;
|
|
}
|
|
if ( !( lpTransform->wTransformFlags & SOTF_XOFFSET ) )
|
|
lpTransform->xOffset = 0;
|
|
if ( !( lpTransform->wTransformFlags & SOTF_YOFFSET ) )
|
|
lpTransform->yOffset = 0;
|
|
if ( !( lpTransform->wTransformFlags & SOTF_XSCALE ) )
|
|
lpTransform->xScale = SOSETRATIO(1,1);
|
|
if ( !( lpTransform->wTransformFlags & SOTF_YSCALE ) )
|
|
lpTransform->yScale = SOSETRATIO(1,1);
|
|
if ( !( lpTransform->wTransformFlags & SOTF_XSKEW ) )
|
|
lpTransform->xSkew = SOSETRATIO(0,1);
|
|
if ( !( lpTransform->wTransformFlags & SOTF_YSKEW ) )
|
|
lpTransform->ySkew = SOSETRATIO(0,1);
|
|
lpTransform++;
|
|
}
|
|
UTGlobalUnlock ( lpTransformInfo->hTransforms );
|
|
lpTransformInfo->nTotalTransforms++;
|
|
lpTransformInfo->nAllocUsed += nSrcSize;
|
|
return(1);
|
|
}
|
|
|
|
SHORT PopTransform ( lpTransformInfo )
|
|
LPTRANSFORMINFO lpTransformInfo;
|
|
{
|
|
/* Traverse transform list and remove last set of transforms */
|
|
LPBYTE lpData;
|
|
SHORT nSize, nCount, nOffset;
|
|
nSize = nCount = 0;
|
|
lpData = UTGlobalLock ( lpTransformInfo->hTransforms );
|
|
for ( nOffset = 0; nOffset < lpTransformInfo->nAllocUsed; )
|
|
{
|
|
nCount = *(LPSHORT)(lpData);
|
|
nSize = sizeof(SHORT) + nCount*sizeof(SOTRANSFORM);
|
|
nOffset += nSize;
|
|
lpData += nSize;
|
|
}
|
|
lpTransformInfo->nAllocUsed -= nSize;
|
|
lpTransformInfo->nTotalTransforms--;
|
|
|
|
UTGlobalUnlock ( lpTransformInfo->hTransforms );
|
|
return(1);
|
|
}
|
|
|
|
SHORT FreeTransform ( lpTransformInfo )
|
|
LPTRANSFORMINFO lpTransformInfo;
|
|
{
|
|
if ( lpTransformInfo->hTransforms )
|
|
UTGlobalFree ( lpTransformInfo->hTransforms );
|
|
lpTransformInfo->hTransforms = NULL;
|
|
lpTransformInfo->nTotalTransforms = 0;
|
|
lpTransformInfo->nAllocUsed = 0;
|
|
lpTransformInfo->nAllocSize = 0;
|
|
return(1);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
ApplyTransform
|
|
|
|
This routine will apply the current transformation to the VectorRecord
|
|
and produce a new VectorRecord in the stored in the VectorInfo structure.
|
|
If the vector record is not a transformable type of record then this
|
|
routine returns 0 and the record should be played in it's original
|
|
format.
|
|
*/
|
|
|
|
SHORT ApplyTransform ( hDC, lpVectorInfo, lpVectorRecord )
|
|
HDC hDC;
|
|
LPVECTORINFO lpVectorInfo;
|
|
LPVRECORDHEADER lpVectorRecord;
|
|
{
|
|
LPBYTE lpData, lpNewData;
|
|
LPSHORT lpInt, lpNewInt;
|
|
SHORT nPoints;
|
|
SOPOINT TmpPoints[8];
|
|
LPVRECORDHEADER lpNewRecord;
|
|
SHORT ret;
|
|
|
|
ret = 1;
|
|
lpData = (LPBYTE)(lpVectorRecord) + sizeof ( VRECORDHEADER );
|
|
lpInt = (LPSHORT)lpData;
|
|
lpNewRecord = (LPVRECORDHEADER)&(lpVectorInfo->TmpRecord);
|
|
*lpNewRecord = *lpVectorRecord;
|
|
lpNewData = (LPBYTE)(lpNewRecord) + sizeof ( VRECORDHEADER );
|
|
lpNewInt = (LPSHORT)lpNewData;
|
|
nPoints = 0;
|
|
/*
|
|
| After the switch the lpNewRecord will be set up for with the points
|
|
| ready for transformation. If necessary for the type of transformation
|
|
| or if points are being collected into a path, the object will be
|
|
| turned into bezier object. If the resultant points are in the internal
|
|
| bezier structure they will be transformed in place. Otherwise,
|
|
| the tranformation will occur form lpInt to lpNewInt for a total of
|
|
| nPoints.
|
|
*/
|
|
switch ( lpVectorRecord->nItemId )
|
|
{
|
|
/* Ojbect information */
|
|
case SO_CPARCTRIPLE:
|
|
{
|
|
SOPOINT TriplePoints[3];
|
|
|
|
TriplePoints[0] = lpVectorInfo->ptCurrentPosition;
|
|
TriplePoints[1] = *(PSOPOINT)lpData;
|
|
TriplePoints[2] = *(PSOPOINT)(lpData + sizeof(SOPOINT));
|
|
RelatePoints ( lpVectorInfo, &TriplePoints[1], 1 );
|
|
lpVectorInfo->ptCurrentPosition = TriplePoints[0];
|
|
RelatePoints ( lpVectorInfo, &TriplePoints[2], 1 );
|
|
if ( ret = ArcTripleToPoints ( lpVectorInfo, (PSOPOINT)TriplePoints, (PSOPOINT)lpNewInt ) )
|
|
{
|
|
lpInt = lpNewInt;
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
if (ret == 1)
|
|
lpNewRecord->nItemId = SO_ARC;
|
|
else
|
|
lpNewRecord->nItemId = SO_ARCCLOCKWISE;
|
|
lpNewRecord->wDataSize = 4 * sizeof(SOPOINT);
|
|
nPoints = 4;
|
|
}
|
|
else
|
|
{
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
if (ret == 1)
|
|
ArcToPolyObject ( lpVectorInfo, (PSOPOINT)lpNewInt, SO_ARC, 0 );
|
|
else
|
|
ArcToPolyObject ( lpVectorInfo, (PSOPOINT)lpNewInt, SO_ARCCLOCKWISE, 0 );
|
|
}
|
|
}
|
|
else
|
|
lpNewRecord->nItemId = SO_ENDPOLY; /* empty poly */
|
|
|
|
}
|
|
break;
|
|
|
|
case SO_ARCTRIPLE:
|
|
|
|
if ( ret = ArcTripleToPoints ( lpVectorInfo, (PSOPOINT)lpData, TmpPoints ) )
|
|
{
|
|
lpInt = (LPSHORT)TmpPoints;
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
if (ret == 1)
|
|
lpNewRecord->nItemId = SO_ARC;
|
|
else
|
|
lpNewRecord->nItemId = SO_ARCCLOCKWISE;
|
|
lpNewRecord->wDataSize = 4 * sizeof(SOPOINT);
|
|
nPoints = 4;
|
|
}
|
|
else
|
|
{
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
if (ret == 1)
|
|
ArcToPolyObject ( lpVectorInfo, (PSOPOINT)TmpPoints, SO_ARC, 0 );
|
|
else
|
|
ArcToPolyObject ( lpVectorInfo, (PSOPOINT)TmpPoints, SO_ARCCLOCKWISE, 0 );
|
|
}
|
|
}
|
|
else
|
|
lpNewRecord->nItemId = SO_ENDPOLY; /* empty poly */
|
|
break;
|
|
|
|
case SO_PIETRIPLE:
|
|
|
|
if ( ret = ArcTripleToPoints ( lpVectorInfo, (PSOPOINT)lpData, TmpPoints ) )
|
|
{
|
|
lpInt = (LPSHORT)TmpPoints;
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
lpNewRecord->nItemId = SO_PIE;
|
|
lpNewRecord->wDataSize = 4 * sizeof(SOPOINT);
|
|
nPoints = 4;
|
|
}
|
|
else
|
|
{
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
ArcToPolyObject ( lpVectorInfo, (PSOPOINT)TmpPoints, SO_PIE, 0 );
|
|
}
|
|
}
|
|
else
|
|
lpNewRecord->nItemId = SO_ENDPOLY; /* empty poly */
|
|
break;
|
|
|
|
case SO_CHORDTRIPLE:
|
|
|
|
if ( ret = ArcTripleToPoints ( lpVectorInfo, (PSOPOINT)lpData, TmpPoints ) )
|
|
{
|
|
lpInt = (LPSHORT)TmpPoints;
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
lpNewRecord->nItemId = SO_CHORD;
|
|
lpNewRecord->wDataSize = 4 * sizeof(SOPOINT);
|
|
nPoints = 4;
|
|
}
|
|
else
|
|
{
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
ArcToPolyObject ( lpVectorInfo, (PSOPOINT)TmpPoints, SO_CHORD, 0 );
|
|
}
|
|
}
|
|
else
|
|
lpNewRecord->nItemId = SO_ENDPOLY; /* empty poly */
|
|
break;
|
|
|
|
case SO_CPARCANGLE:
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
lpNewRecord->nItemId = SO_ARC;
|
|
lpNewRecord->wDataSize = 4 * sizeof(SOPOINT);
|
|
CpArcToPoints ( lpVectorInfo, (PSOCPARCANGLE)lpData, (PSOPOINT)lpNewInt );
|
|
lpInt = lpNewInt;
|
|
nPoints = 4;
|
|
}
|
|
else
|
|
{
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
CpArcToPoints ( lpVectorInfo, (PSOCPARCANGLE)lpData, TmpPoints );
|
|
ArcToPolyObject ( lpVectorInfo, TmpPoints, SO_ARC, 0 );
|
|
}
|
|
break;
|
|
|
|
|
|
case SO_ARCANGLE:
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
lpNewRecord->nItemId = SO_ARC;
|
|
lpNewRecord->wDataSize = 4 * sizeof(SOPOINT);
|
|
ArcInfoToPoints ( lpVectorInfo, (PSOARCINFO)lpData, (PSOPOINT)lpNewInt );
|
|
lpInt = lpNewInt;
|
|
nPoints = 4;
|
|
}
|
|
else
|
|
{
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
ArcInfoToPoints ( lpVectorInfo, (PSOARCINFO)lpData, TmpPoints );
|
|
ArcToPolyObject ( lpVectorInfo, TmpPoints, SO_ARC, 0 );
|
|
}
|
|
break;
|
|
|
|
case SO_ARCANGLECLOCKWISE:
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
lpNewRecord->nItemId = SO_ARCCLOCKWISE;
|
|
lpNewRecord->wDataSize = 4 * sizeof(SOPOINT);
|
|
ArcInfoToPoints ( lpVectorInfo, (PSOARCINFO)lpData, (PSOPOINT)lpNewInt );
|
|
lpInt = lpNewInt;
|
|
nPoints = 4;
|
|
}
|
|
else
|
|
{
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
ArcInfoToPoints ( lpVectorInfo, (PSOARCINFO)lpData, TmpPoints );
|
|
/* Translate to a bezier */
|
|
ArcToPolyObject ( lpVectorInfo, TmpPoints, SO_ARCCLOCKWISE, 0 );
|
|
}
|
|
break;
|
|
|
|
case SO_ARCCLOCKWISE:
|
|
case SO_ARC:
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
nPoints = 4;
|
|
}
|
|
else
|
|
{
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
ArcToPolyObject ( lpVectorInfo , (PSOPOINT)lpData, lpVectorRecord->nItemId, 0 );
|
|
}
|
|
break;
|
|
|
|
|
|
case SO_CHORDANGLE:
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
lpNewRecord->nItemId = SO_CHORD;
|
|
lpNewRecord->wDataSize = 4 * sizeof(SOPOINT);
|
|
ArcInfoToPoints ( lpVectorInfo, (PSOARCINFO)lpData, (PSOPOINT)lpNewInt );
|
|
lpInt = lpNewInt;
|
|
nPoints = 4;
|
|
}
|
|
else
|
|
{
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
ArcInfoToPoints ( lpVectorInfo, (PSOARCINFO)lpData, TmpPoints );
|
|
/* Translate to a bezier */
|
|
ArcToPolyObject ( lpVectorInfo, TmpPoints, SO_CHORD, 0 );
|
|
}
|
|
break;
|
|
|
|
case SO_CHORD:
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
nPoints = 4;
|
|
}
|
|
else
|
|
{
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
ArcToPolyObject ( lpVectorInfo , (PSOPOINT)lpData, SO_CHORD, 0 );
|
|
}
|
|
break;
|
|
|
|
case SO_TEXTINRECT:
|
|
/*
|
|
| This requires a very tricky translation to a bezier.
|
|
| For now I will turn it into a rectangle so we can see
|
|
| where the text would end up.
|
|
*/
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
CopyRecord ( lpNewRecord, lpVectorRecord );
|
|
nPoints = 2;
|
|
}
|
|
else
|
|
{
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
lpVectorInfo->PolyInfo.wFormat = SOPT_POLYGON;
|
|
lpVectorInfo->PolyPoints.nCount = 0;
|
|
TmpPoints[0].x = TmpPoints[3].x = lpInt[0];
|
|
TmpPoints[0].y = TmpPoints[1].y = lpInt[1];
|
|
TmpPoints[1].x = TmpPoints[2].x = lpInt[2];
|
|
TmpPoints[2].y = TmpPoints[3].y = lpInt[3];
|
|
TmpPoints[4] = TmpPoints[0];
|
|
AddPointsToPolyObject ( lpVectorInfo, 5, TmpPoints );
|
|
}
|
|
break;
|
|
|
|
case SO_CPELLIPSE:
|
|
TmpPoints[2] = *(PSOPOINT)lpData;
|
|
TmpPoints[0].x = lpVectorInfo->ptCurrentPosition.x-TmpPoints[2].x;
|
|
TmpPoints[1].x = lpVectorInfo->ptCurrentPosition.x+TmpPoints[2].x;
|
|
TmpPoints[0].y = lpVectorInfo->ptCurrentPosition.y-TmpPoints[2].y;
|
|
TmpPoints[1].y = lpVectorInfo->ptCurrentPosition.y+TmpPoints[2].y;
|
|
lpInt = (LPSHORT)TmpPoints;
|
|
lpNewRecord->nItemId = SO_ELLIPSE;
|
|
lpNewRecord->wDataSize = 2 * sizeof(SOPOINT);
|
|
/* Fall Through */
|
|
|
|
case SO_ELLIPSE:
|
|
if ( lpVectorInfo->bOnlyOffsetOrScale )
|
|
{
|
|
nPoints = 2;
|
|
}
|
|
else
|
|
{
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
lpVectorInfo->PolyInfo.wFormat = SOPT_BEZIERCLOSE;
|
|
lpVectorInfo->PolyPoints.nCount = 0;
|
|
AddEllipseToBezier ( (PSOPOINT)lpInt, lpVectorInfo, 0 );
|
|
}
|
|
break;
|
|
|
|
case SO_ELLIPSERADII:
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
nPoints = 3;
|
|
}
|
|
else
|
|
{
|
|
ret = EllipseRadiiToPoints ( lpVectorInfo, (PSOPOINT)lpData, TmpPoints );
|
|
if (ret)
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
else
|
|
{
|
|
lpVectorInfo->PolyInfo.wFormat = SOPT_BEZIERCLOSE;
|
|
lpVectorInfo->PolyPoints.nCount = 0;
|
|
AddEllipseToBezier ( TmpPoints, lpVectorInfo, 0 );
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SO_ARCRADII:
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
nPoints = 5;
|
|
}
|
|
else
|
|
{
|
|
ret = ArcRadiiToPoints ( lpVectorInfo, (PSOPOINT)lpData, TmpPoints );
|
|
|
|
lpVectorInfo->PolyInfo.wFormat = SOPT_POLYGON;
|
|
lpVectorInfo->PolyPoints.nCount = 0;
|
|
ArcToPolyObject ( lpVectorInfo, TmpPoints, SO_ARC, ret ); // ret is the rotation angle
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
}
|
|
break;
|
|
|
|
case SO_PIERADII:
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
nPoints = 5;
|
|
}
|
|
else
|
|
{
|
|
ret = ArcRadiiToPoints ( lpVectorInfo, (PSOPOINT)lpData, TmpPoints );
|
|
|
|
lpVectorInfo->PolyInfo.wFormat = SOPT_POLYGON;
|
|
lpVectorInfo->PolyPoints.nCount = 0;
|
|
ArcToPolyObject ( lpVectorInfo, TmpPoints, SO_PIE, ret ); // ret is the rotation angle
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
}
|
|
break;
|
|
|
|
case SO_CHORDRADII:
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
nPoints = 5;
|
|
}
|
|
else
|
|
{
|
|
ret = ArcRadiiToPoints ( lpVectorInfo, (PSOPOINT)lpData, TmpPoints );
|
|
|
|
lpVectorInfo->PolyInfo.wFormat = SOPT_POLYGON;
|
|
lpVectorInfo->PolyPoints.nCount = 0;
|
|
ArcToPolyObject ( lpVectorInfo, TmpPoints, SO_CHORD, ret ); // ret is the rotation angle
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
}
|
|
break;
|
|
|
|
case SO_FLOODFILL:
|
|
CopyRecord ( lpNewRecord, lpVectorRecord );
|
|
nPoints = 1;
|
|
break;
|
|
|
|
case SO_CPLINE:
|
|
TmpPoints[0] = lpVectorInfo->ptCurrentPosition;
|
|
TmpPoints[1] = *(PSOPOINT)lpData;
|
|
RelatePoints ( lpVectorInfo, &TmpPoints[1], 1 );
|
|
lpInt = (LPSHORT)TmpPoints;
|
|
lpNewRecord->nItemId = SO_LINE;
|
|
lpNewRecord->wDataSize = 2 * sizeof(SOPOINT);
|
|
/* Fall through */
|
|
|
|
case SO_LINE:
|
|
if ( lpVectorInfo->wPathLevel )
|
|
{
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
lpVectorInfo->PolyInfo.wFormat = SOPT_POLYLINE;
|
|
lpVectorInfo->PolyPoints.nCount = 0;
|
|
AddPointsToPolyObject ( lpVectorInfo, 2, (PSOPOINT)lpInt );
|
|
}
|
|
else
|
|
nPoints = 2;
|
|
break;
|
|
|
|
case SO_CPPIEANGLE:
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
lpNewRecord->nItemId = SO_PIE;
|
|
lpNewRecord->wDataSize = 4 * sizeof(SOPOINT);
|
|
CpPieToPoints ( lpVectorInfo, (PSOCPPIEANGLE)lpData, (PSOPOINT)lpNewInt );
|
|
lpInt = lpNewInt;
|
|
nPoints = 4;
|
|
}
|
|
else
|
|
{
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
CpPieToPoints ( lpVectorInfo, (PSOCPPIEANGLE)lpData, TmpPoints );
|
|
/* Translate to a bezier */
|
|
ArcToPolyObject ( lpVectorInfo , TmpPoints, SO_PIE, 0 );
|
|
}
|
|
break;
|
|
|
|
case SO_PIEANGLE:
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
lpNewRecord->nItemId = SO_PIE;
|
|
lpNewRecord->wDataSize = 4 * sizeof(SOPOINT);
|
|
ArcInfoToPoints ( lpVectorInfo, (PSOARCINFO)lpData, (PSOPOINT)lpNewInt );
|
|
lpInt = lpNewInt;
|
|
nPoints = 4;
|
|
}
|
|
else
|
|
{
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
ArcInfoToPoints ( lpVectorInfo, (PSOARCINFO)lpData, TmpPoints );
|
|
/* Translate to a bezier */
|
|
ArcToPolyObject ( lpVectorInfo , TmpPoints, SO_PIE, 0 );
|
|
}
|
|
break;
|
|
|
|
case SO_PIE:
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
nPoints = 4;
|
|
}
|
|
else
|
|
{
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
ArcToPolyObject ( lpVectorInfo, (PSOPOINT)lpData, SO_PIE, 0 );
|
|
}
|
|
break;
|
|
|
|
case SO_ENDPOLY:
|
|
/* Is already set for transformation */
|
|
break;
|
|
|
|
case SO_CPRECTANGLE:
|
|
TmpPoints[0] = lpVectorInfo->ptCurrentPosition;
|
|
TmpPoints[1] = *(PSOPOINT)lpData;
|
|
RelatePoints ( lpVectorInfo, &TmpPoints[1], 1 );
|
|
/* reset cp */
|
|
lpVectorInfo->ptCurrentPosition = TmpPoints[0];
|
|
|
|
lpNewRecord->nItemId = SO_RECTANGLE;
|
|
lpNewRecord->wDataSize = 2 * sizeof(SOPOINT);
|
|
lpInt = (LPSHORT)TmpPoints;
|
|
/* Fall through */
|
|
|
|
case SO_RECTANGLE:
|
|
/*
|
|
if ( lpVectorInfo->bOnlyOffsetOrScale )
|
|
{
|
|
nPoints = 2;
|
|
}
|
|
else
|
|
*/
|
|
{
|
|
PSOPOINT lpPoint;
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
lpVectorInfo->PolyInfo.wFormat = SOPT_POLYGON;
|
|
lpVectorInfo->PolyPoints.nCount = 0;
|
|
lpPoint = (PSOPOINT)lpNewInt;
|
|
lpPoint[0].x = lpPoint[3].x = lpInt[0];
|
|
lpPoint[0].y = lpPoint[1].y = lpInt[1];
|
|
lpPoint[1].x = lpPoint[2].x = lpInt[2];
|
|
lpPoint[2].y = lpPoint[3].y = lpInt[3];
|
|
lpPoint[4] = lpPoint[0];
|
|
AddPointsToPolyObject ( lpVectorInfo, 5, lpPoint );
|
|
}
|
|
break;
|
|
|
|
case SO_ROUNDRECT:
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
CopyRecord ( lpNewRecord, lpVectorRecord );
|
|
nPoints = 2; /* don't transform the ellipse def */
|
|
}
|
|
else
|
|
{
|
|
lpNewRecord->nItemId = SO_ENDPOLY;
|
|
lpVectorInfo->PolyInfo.wFormat = SOPT_BEZIERCLOSE;
|
|
lpVectorInfo->PolyPoints.nCount = 0;
|
|
AddRoundRectToBezier ( (PSOPOINT)lpInt, lpVectorInfo );
|
|
}
|
|
break;
|
|
|
|
case SO_SETPIXEL:
|
|
CopyRecord ( lpNewRecord, lpVectorRecord );
|
|
nPoints = 1;
|
|
break;
|
|
|
|
case SO_CPTEXTATPOINT:
|
|
/* Turn into text at point record */
|
|
UTmemcpy ( (LPBYTE)lpNewData+sizeof(SOPOINT), (LPBYTE)lpData, lpVectorRecord->wDataSize-sizeof(SOPOINT) );
|
|
lpInt = (LPSHORT)(&lpVectorInfo->ptCurrentPosition);
|
|
lpNewRecord->wDataSize += sizeof(SOPOINT);
|
|
lpNewRecord->nItemId = SO_TEXTATPOINT;
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
nPoints = 1;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
| Need to turn text into multiple beziers, for now just
|
|
| transform point.
|
|
*/
|
|
nPoints = 1;
|
|
}
|
|
break;
|
|
|
|
|
|
case SO_TEXTATPOINT:
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
CopyRecord ( lpNewRecord, lpVectorRecord );
|
|
nPoints = 1;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
| Need to turn text into multiple beziers, for now just
|
|
| transform point.
|
|
*/
|
|
CopyRecord ( lpNewRecord, lpVectorRecord );
|
|
nPoints = 1;
|
|
}
|
|
break;
|
|
|
|
case SO_TEXTATARCANGLE:
|
|
/* Turn result into so_textatpoint with correct point transformed */
|
|
lpNewRecord->nItemId = SO_TEXTATPOINT;
|
|
lpNewRecord->wDataSize -= sizeof(SOARCINFO)-sizeof(SOPOINT);
|
|
UTmemcpy ( (LPBYTE)lpNewData+sizeof(SOARCINFO), (LPBYTE)lpData+sizeof(SOPOINT), lpVectorRecord->wDataSize-sizeof(SOARCINFO) );
|
|
lpInt = ArcInfoToPoints ( lpVectorInfo, (PSOARCINFO)lpData, TmpPoints );
|
|
lpInt += 4;
|
|
nPoints = 1;
|
|
break;
|
|
|
|
case SO_BEGINGROUP:
|
|
{
|
|
PSOGROUPINFO lpGroupInfo;
|
|
CopyRecord ( lpNewRecord, lpVectorRecord );
|
|
lpGroupInfo = (PSOGROUPINFO)lpData;
|
|
lpInt = (LPSHORT)&lpGroupInfo->BoundingRect;
|
|
lpGroupInfo = (PSOGROUPINFO)lpNewData;
|
|
lpNewInt = (LPSHORT)&lpGroupInfo->BoundingRect;
|
|
nPoints = 2;
|
|
}
|
|
break;
|
|
|
|
/* Attribute objects */
|
|
case SO_SELECTFONT:
|
|
if ( lpVectorInfo->TextRotationAngle )
|
|
{
|
|
PSOLOGFONT lpFont;
|
|
CopyRecord ( lpNewRecord, lpVectorRecord );
|
|
lpFont = (PSOLOGFONT)lpNewData;
|
|
lpFont->lfEscapement += lpVectorInfo->TextRotationAngle*lpVectorInfo->XDirection*lpVectorInfo->YDirection;
|
|
lpFont->lfEscapement = lpFont->lfEscapement % 3600;
|
|
lpFont->lfClipPrecision |= SOLF_CLIP_LH_ANGLES;
|
|
return(1);
|
|
}
|
|
else
|
|
return(0);
|
|
break;
|
|
|
|
default:
|
|
ret = 0; /* non transformable object */
|
|
break;
|
|
}
|
|
if ( ret )
|
|
{
|
|
if ( nPoints )
|
|
{
|
|
if( lpVectorInfo->bObjectTransform )
|
|
{
|
|
TransformPoints ( lpVectorInfo, &lpVectorInfo->ObjectTransform,(PSOPOINT)lpNewInt, (PSOPOINT)lpInt, nPoints );
|
|
lpInt = lpNewInt;
|
|
}
|
|
if( lpVectorInfo->bGenTransform )
|
|
TransformPoints ( lpVectorInfo, &lpVectorInfo->GenTransform, (PSOPOINT)lpNewInt, (PSOPOINT)lpInt, nPoints );
|
|
}
|
|
else
|
|
{
|
|
PSOPOINT lpPoints;
|
|
lpPoints = (PSOPOINT)UTGlobalLock ( lpVectorInfo->PolyPoints.hPoints );
|
|
lpVectorInfo->PolyInfo.nPoints = lpVectorInfo->PolyPoints.nCount;
|
|
if( lpVectorInfo->bObjectTransform )
|
|
TransformPoints ( lpVectorInfo, &lpVectorInfo->ObjectTransform, lpPoints, lpPoints, lpVectorInfo->PolyPoints.nCount );
|
|
if( lpVectorInfo->bGenTransform )
|
|
TransformPoints ( lpVectorInfo, &lpVectorInfo->GenTransform, lpPoints, lpPoints, lpVectorInfo->PolyPoints.nCount );
|
|
UTGlobalUnlock ( lpVectorInfo->PolyPoints.hPoints );
|
|
}
|
|
}
|
|
return(ret);
|
|
}
|
|
|
|
|
|
SHORT AddEllipseToBezier ( lpEllipseData, lpVectorInfo, RotAngle )
|
|
PSOPOINT lpEllipseData;
|
|
LPVECTORINFO lpVectorInfo;
|
|
SHORT RotAngle;
|
|
{
|
|
PSOPOINT lpP;
|
|
SOPOINT Center;
|
|
SHORT x1, x2, y1, y2, TotalRotAngle, Dist;
|
|
|
|
x1 = lpEllipseData[0].x;
|
|
y1 = lpEllipseData[0].y;
|
|
x2 = lpEllipseData[1].x;
|
|
y2 = lpEllipseData[1].y;
|
|
lpP = (PSOPOINT)UTGlobalLock ( lpVectorInfo->PolyPoints.hPoints );
|
|
lpP += lpVectorInfo->PolyPoints.nCount;
|
|
/* Set x values */
|
|
lpP[0].x = lpP[6].x = lpP[12].x = MIDPOINT(x1,x2);
|
|
lpP[1].x = lpP[5].x = MIDPOINT(x1,lpP[0].x);
|
|
lpP[2].x = lpP[3].x = lpP[4].x = x1;
|
|
lpP[7].x = lpP[11].x = MIDPOINT(lpP[0].x,x2);
|
|
lpP[8].x = lpP[9].x = lpP[10].x = x2;
|
|
/* Set y values */
|
|
lpP[0].y = lpP[1].y = lpP[11].y = lpP[12].y = y1;
|
|
lpP[3].y = lpP[9].y = MIDPOINT(y1,y2);
|
|
lpP[2].y = lpP[10].y = MIDPOINT(y1,lpP[3].y);
|
|
lpP[4].y = lpP[8].y = MIDPOINT(lpP[3].y,y2);
|
|
lpP[5].y = lpP[6].y = lpP[7].y = y2;
|
|
if (RotAngle)
|
|
{
|
|
Center.x = MIDPOINT(lpEllipseData[0].x, lpEllipseData[1].x);
|
|
Center.y = MIDPOINT(lpEllipseData[0].y, lpEllipseData[1].y);
|
|
for (x1=0; x1<13; x1++) // Rotate the points around the center
|
|
{
|
|
Dist = GetDistance( lpVectorInfo, &Center, &lpP[x1] );
|
|
TotalRotAngle = RotAngle + GetAngle ( lpVectorInfo, &Center, &lpP[x1] );
|
|
lpP[x1].x = Center.x + (SHORT)(((LONG)Dist * (LONG)(cosval(TotalRotAngle)))/10000)*lpVectorInfo->XDirection;
|
|
lpP[x1].y = Center.y - (SHORT)(((LONG)Dist * (LONG)(sinval(TotalRotAngle)))/10000)*lpVectorInfo->YDirection;
|
|
}
|
|
}
|
|
UTGlobalUnlock ( lpVectorInfo->PolyPoints.hPoints );
|
|
lpVectorInfo->PolyPoints.nCount += 13;
|
|
return(1);
|
|
}
|
|
|
|
|
|
SHORT AddRoundRectToBezier ( lpRoundRectData, lpVectorInfo )
|
|
PSOPOINT lpRoundRectData;
|
|
LPVECTORINFO lpVectorInfo;
|
|
{
|
|
PSOPOINT lpP;
|
|
SHORT x1, x2, y1, y2, x3, y3;
|
|
x1 = lpRoundRectData[0].x;
|
|
y1 = lpRoundRectData[0].y;
|
|
x2 = lpRoundRectData[1].x;
|
|
y2 = lpRoundRectData[1].y;
|
|
x3 = lpRoundRectData[2].x/2;
|
|
y3 = lpRoundRectData[2].y/2;
|
|
lpP = (PSOPOINT)UTGlobalLock ( lpVectorInfo->PolyPoints.hPoints );
|
|
lpP += lpVectorInfo->PolyPoints.nCount;
|
|
/* Set x values */
|
|
lpP[0].x = lpP[9].x = lpP[10].x = lpP[23].x = lpP[24].x = x1 + x3;
|
|
lpP[1].x = lpP[8].x = MIDPOINT(x1,lpP[0].x);
|
|
lpP[2].x = lpP[3].x = lpP[4].x = lpP[5].x = lpP[6].x = lpP[7].x = x1;
|
|
lpP[11].x = lpP[12].x = lpP[21].x = lpP[22].x = x2 - x3;
|
|
lpP[13].x = lpP[20].x = MIDPOINT(lpP[11].x,x2);
|
|
lpP[14].x = lpP[15].x = lpP[16].x = lpP[17].x = lpP[18].x = lpP[19].x = x2;
|
|
/* Set y values */
|
|
lpP[0].y = lpP[1].y = lpP[20].y = lpP[21].y = lpP[22].y = lpP[23].y = lpP[24].y = y1;
|
|
lpP[3].y = lpP[4].y = lpP[17].y = lpP[18].y = y1 + y3;
|
|
lpP[2].y = lpP[19].y = MIDPOINT(y1,lpP[3].y);
|
|
lpP[5].y = lpP[6].y = lpP[15].y = lpP[16].y = y2 - y3;
|
|
lpP[7].y = lpP[14].y = MIDPOINT ( lpP[5].y, y2 );
|
|
lpP[8].y = lpP[9].y = lpP[10].y = lpP[11].y = lpP[12].y = lpP[13].y = y2;
|
|
|
|
UTGlobalUnlock ( lpVectorInfo->PolyPoints.hPoints );
|
|
lpVectorInfo->PolyPoints.nCount += 25;
|
|
return(1);
|
|
}
|
|
|
|
/* This routine has never been tested
|
|
SHORT AddBezLinesToPolyObject ( lpVectorInfo, nLines, lpPoints )
|
|
LPVECTORINFO lpVectorInfo;
|
|
SHORT nLines;
|
|
PSOPOINT lpPoints;
|
|
{
|
|
SHORT i;
|
|
PSOPOINT lpP;
|
|
lpP = (PSOPOINT)UTGlobalLock ( lpVectorInfo->PolyPoints.hPoints );
|
|
lpP += lpVectorInfo->PolyPoints.nCount;
|
|
if ( lpVectorInfo->PolyPoints.nCount != 0 )
|
|
{
|
|
lpVectorInfo->PolyPoints.nCount--;
|
|
lpP--;
|
|
}
|
|
lpP[0] = lpP[1] = lpPoints[0];
|
|
for ( i=1; i < nLines; i++ )
|
|
lpP[(i*3)-1] = lpP[i*3] = lpP[(i*3)+1] = lpPoints[i];
|
|
lpP[(nLines*3)-1] = lpP[(nLines*3)] = lpPoints[nLines];
|
|
|
|
UTGlobalUnlock ( lpVectorInfo->PolyPoints.hPoints );
|
|
lpVectorInfo->PolyPoints.nCount += (nLines*3)+1;
|
|
return(1);
|
|
}
|
|
*/
|
|
|
|
SHORT AddPointsToPolyObject ( lpVectorInfo , nPoints, lpPoints )
|
|
LPVECTORINFO lpVectorInfo;
|
|
SHORT nPoints;
|
|
PSOPOINT lpPoints;
|
|
{
|
|
PSOPOINT lpP;
|
|
lpP = (PSOPOINT)UTGlobalLock ( lpVectorInfo->PolyPoints.hPoints );
|
|
lpP += lpVectorInfo->PolyPoints.nCount;
|
|
UTmemcpy ( (LPBYTE)lpP, (LPBYTE)lpPoints, nPoints * sizeof(SOPOINT) );
|
|
UTGlobalUnlock ( lpVectorInfo->PolyPoints.hPoints );
|
|
lpVectorInfo->PolyPoints.nCount += nPoints;
|
|
return(1);
|
|
}
|
|
|
|
VOID CopyRecord ( lpDst, lpSrc )
|
|
LPVRECORDHEADER lpDst;
|
|
LPVRECORDHEADER lpSrc;
|
|
{
|
|
WORD wCount;
|
|
wCount = lpSrc->wDataSize + sizeof(VRECORDHEADER);
|
|
if ( wCount > MAXTMPRECORD )
|
|
wCount = MAXTMPRECORD;
|
|
UTmemcpy ( (LPBYTE)lpDst, (LPBYTE)lpSrc, wCount);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
SetupTransfrom
|
|
|
|
This routine traverses all of the current transforms to setup boolean
|
|
flags about the overall transformation. These flags determine to what
|
|
level objects must be transformed.
|
|
*/
|
|
|
|
SHORT SetupTransform ( lpVectorInfo )
|
|
LPVECTORINFO lpVectorInfo;
|
|
{
|
|
lpVectorInfo->bTransforming = FALSE;
|
|
lpVectorInfo->TextRotationAngle = 0;
|
|
if ( lpVectorInfo->wPathLevel )
|
|
lpVectorInfo->bOnlyOffset = FALSE;
|
|
else
|
|
lpVectorInfo->bOnlyOffset = TRUE;
|
|
if ( lpVectorInfo->wPathLevel )
|
|
lpVectorInfo->bOnlyOffsetOrScale = FALSE;
|
|
else
|
|
lpVectorInfo->bOnlyOffsetOrScale = TRUE;
|
|
lpVectorInfo->bGenTransform = FALSE;
|
|
lpVectorInfo->bObjectTransform = FALSE;
|
|
if ( CheckTransform ( lpVectorInfo, &lpVectorInfo->GenTransform ) )
|
|
lpVectorInfo->bGenTransform = TRUE;
|
|
if( CheckTransform ( lpVectorInfo, &lpVectorInfo->ObjectTransform ) )
|
|
lpVectorInfo->bObjectTransform = TRUE;
|
|
return(1);
|
|
}
|
|
|
|
SHORT CheckTransform ( lpVectorInfo, lpTransformInfo )
|
|
LPVECTORINFO lpVectorInfo;
|
|
LPTRANSFORMINFO lpTransformInfo;
|
|
{
|
|
LPBYTE lpData;
|
|
SHORT nXGroups, nXForms;
|
|
SHORT i, j, ret;
|
|
PSOTRANSFORM lpXForm;
|
|
nXGroups = lpTransformInfo->nTotalTransforms;
|
|
if ( lpTransformInfo->hTransforms == NULL )
|
|
return(FALSE);
|
|
lpData = UTGlobalLock ( lpTransformInfo->hTransforms );
|
|
if ( lpData == NULL )
|
|
return(FALSE);
|
|
ret = FALSE;
|
|
for ( i=0; i < nXGroups; i++ )
|
|
{
|
|
nXForms = *(LPSHORT)lpData;
|
|
lpData += sizeof(SHORT);
|
|
lpXForm = (PSOTRANSFORM)lpData;
|
|
lpData += nXForms*sizeof(SOTRANSFORM);
|
|
for ( j=0; j< nXForms; j++ )
|
|
{
|
|
if ( !(lpXForm->wTransformFlags & SOTF_NOTRANSFORM) )
|
|
{
|
|
lpVectorInfo->bTransforming = TRUE;
|
|
ret = TRUE;
|
|
}
|
|
if ( lpXForm->wTransformFlags & (SOTF_XSCALE|SOTF_YSCALE|SOTF_XSKEW|SOTF_YSKEW))
|
|
lpVectorInfo->bOnlyOffset = FALSE;
|
|
if ( lpXForm->wTransformFlags & (SOTF_XSKEW|SOTF_YSKEW))
|
|
lpVectorInfo->bOnlyOffsetOrScale = FALSE;
|
|
if ( lpXForm->wTransformFlags & SOTF_ROTATE )
|
|
{
|
|
lpVectorInfo->TextRotationAngle += lpXForm->RotationAngle;
|
|
lpVectorInfo->TextRotationAngle = lpVectorInfo->TextRotationAngle % 3600;
|
|
}
|
|
|
|
lpXForm++;
|
|
}
|
|
|
|
}
|
|
UTGlobalUnlock ( lpTransformInfo->hTransforms );
|
|
return(ret);
|
|
}
|
|
|
|
SHORT TransformPoints ( lpVectorInfo, lpTransformInfo, lpDstPoints, lpSrcPoints, nPoints )
|
|
LPVECTORINFO lpVectorInfo;
|
|
LPTRANSFORMINFO lpTransformInfo;
|
|
PSOPOINT lpDstPoints;
|
|
PSOPOINT lpSrcPoints;
|
|
SHORT nPoints;
|
|
{
|
|
LPBYTE lpData, lpInitData;
|
|
SHORT nXGroups, nXForms;
|
|
SHORT i, j, ret;
|
|
SHORT k;
|
|
LONG eM11num, eM12num, eM21num, eM22num;
|
|
LONG eM11den, eM12den, eM21den, eM22den;
|
|
SHORT eDx, eDy, xOrg, yOrg, xRel, yRel;
|
|
PSOTRANSFORM lpXForm;
|
|
PSOPOINT lpDst;
|
|
PSOPOINT lpSrc;
|
|
|
|
nXGroups = lpTransformInfo->nTotalTransforms;
|
|
lpInitData = UTGlobalLock ( lpTransformInfo->hTransforms );
|
|
if ( lpInitData == NULL )
|
|
return(FALSE);
|
|
ret = FALSE;
|
|
/* Apply the group transforms in the reverse order */
|
|
lpSrc = lpSrcPoints;
|
|
lpDst = lpDstPoints;
|
|
|
|
for ( i=nXGroups-1; i >= 0; i-- )
|
|
{
|
|
lpData = lpInitData;
|
|
for (k=0; k <= i; k++ )
|
|
{
|
|
nXForms = *(LPSHORT)lpData;
|
|
lpData += sizeof(SHORT);
|
|
lpXForm = (PSOTRANSFORM)lpData;
|
|
lpData += nXForms*sizeof(SOTRANSFORM);
|
|
}
|
|
|
|
for ( j=0; j< nXForms; j++ )
|
|
{
|
|
if ( lpVectorInfo->bOnlyOffset )
|
|
{
|
|
for ( k=0; k < nPoints; k++ )
|
|
{
|
|
lpDst->x = lpSrc->x + lpXForm->xOffset;
|
|
lpDst->y = lpSrc->y + lpXForm->yOffset;
|
|
lpSrc++;
|
|
lpDst++;
|
|
}
|
|
lpSrc = lpDstPoints;
|
|
lpDst = lpDstPoints;
|
|
}
|
|
else
|
|
{
|
|
eM11num = (SHORT)((lpXForm->xScale)>>16);
|
|
eM12num = (SHORT)((lpXForm->ySkew)>>16);
|
|
eM21num = (SHORT)((lpXForm->xSkew)>>16);
|
|
eM22num = (SHORT)((lpXForm->yScale)>>16);
|
|
eM11den = (SHORT)((lpXForm->xScale)&0xffff);
|
|
eM12den = (SHORT)((lpXForm->ySkew)&0xffff);
|
|
eM21den = (SHORT)((lpXForm->xSkew)&0xffff);
|
|
eM22den = (SHORT)((lpXForm->yScale)&0xffff);
|
|
xOrg = lpXForm->Origin.x;
|
|
yOrg = lpXForm->Origin.y;
|
|
eDx = lpXForm->xOffset + xOrg;
|
|
eDy = lpXForm->yOffset + yOrg;
|
|
if ( eM11den && eM12den && eM21den && eM22den )
|
|
{
|
|
for ( k=0; k < nPoints; k++ )
|
|
{
|
|
xRel = lpSrc->x - xOrg;
|
|
yRel = lpSrc->y - yOrg;
|
|
lpDst->x =(SHORT)((eM11num*(LONG)(xRel))/eM11den) +
|
|
(SHORT)((eM21num*(LONG)(yRel))/eM21den) + eDx;
|
|
lpDst->y =(SHORT)((eM12num*(LONG)(xRel))/eM12den) +
|
|
(SHORT)((eM22num*(LONG)(yRel))/eM22den) + eDy;
|
|
lpSrc++;
|
|
lpDst++;
|
|
}
|
|
lpSrc = lpDstPoints;
|
|
lpDst = lpDstPoints;
|
|
}
|
|
}
|
|
lpXForm++;
|
|
}
|
|
|
|
}
|
|
UTGlobalUnlock ( lpTransformInfo->hTransforms );
|
|
return(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
SHORT ArcToPolyObject ( lpVectorInfo , lpArcData, wItemId, RotAngle )
|
|
LPVECTORINFO lpVectorInfo;
|
|
PSOPOINT lpArcData;
|
|
WORD wItemId;
|
|
SHORT RotAngle;
|
|
{
|
|
SOPOINT Center, Radius;
|
|
PSOPOINT lpTop, lpP;
|
|
SHORT i, j, k, StartAngle, EndAngle, Angle, TotalRotAngle;
|
|
SHORT StartQuad, EndQuad, PointQuad, TotalQuads;
|
|
LONG lStartx, lStarty, lEndx, lEndy, lPx, lPy, Dist;
|
|
BOOL bAddPoint;
|
|
|
|
lpVectorInfo->PolyInfo.wFormat = SOPT_BEZIEROPEN;
|
|
lpVectorInfo->PolyPoints.nCount = 0;
|
|
|
|
OIMCheckPointBuffer ( &(lpVectorInfo->PolyPoints), 365 );
|
|
lpTop = lpP = (PSOPOINT)UTGlobalLock ( lpVectorInfo->PolyPoints.hPoints );
|
|
lpP += lpVectorInfo->PolyPoints.nCount;
|
|
|
|
/* First get start and end angles of the arc from the arc data */
|
|
|
|
|
|
Center.x = MIDPOINT ( lpArcData[0].x, lpArcData[1].x );
|
|
Center.y = MIDPOINT ( lpArcData[0].y, lpArcData[1].y );
|
|
Radius.x = (Center.x - lpArcData[0].x)*lpVectorInfo->XDirection;
|
|
Radius.y = (Center.y - lpArcData[0].y)*lpVectorInfo->YDirection;
|
|
StartAngle = GetAngle ( lpVectorInfo, &Center, &lpArcData[2] );
|
|
EndAngle = GetAngle ( lpVectorInfo, &Center, &lpArcData[3] );
|
|
StartQuad = StartAngle / 900;
|
|
EndQuad = EndAngle / 900;
|
|
lStartx = (lpArcData[2].x - Center.x)*lpVectorInfo->XDirection;
|
|
lStarty = (lpArcData[2].y - Center.y)*lpVectorInfo->YDirection;
|
|
lEndx = (lpArcData[3].x - Center.x)*lpVectorInfo->XDirection;
|
|
lEndy = (lpArcData[3].y - Center.y)*lpVectorInfo->YDirection;
|
|
i=0;
|
|
|
|
bAddPoint = FALSE;
|
|
if ( wItemId == SO_ARCCLOCKWISE )
|
|
{
|
|
if ( EndAngle < StartAngle )
|
|
TotalQuads = StartQuad - EndQuad + 1;
|
|
else
|
|
TotalQuads = 5 - (EndQuad - StartQuad);
|
|
|
|
for ( j=0; j < TotalQuads; j++ )
|
|
{
|
|
PointQuad = (StartQuad+4-j) % 4;
|
|
for ( k=0; k < 900; k+=10 )
|
|
{
|
|
Angle = (PointQuad*900)+900-k;
|
|
lpP[i].x = Center.x + (SHORT)(((LONG)Radius.x * (LONG)(cosval(Angle)))/10000)*lpVectorInfo->XDirection;
|
|
lpP[i].y = Center.y - (SHORT)(((LONG)Radius.y * (LONG)(sinval(Angle)))/10000)*lpVectorInfo->YDirection;
|
|
lPx = (lpP[i].x - Center.x)*lpVectorInfo->XDirection;
|
|
lPy = (lpP[i].y - Center.y)*lpVectorInfo->YDirection;
|
|
if ( !bAddPoint )
|
|
{
|
|
if ( lPx * lStarty <= lPy * lStartx )
|
|
bAddPoint = TRUE;
|
|
}
|
|
if ( bAddPoint )
|
|
{
|
|
if (RotAngle) // Rotate the point
|
|
{
|
|
TotalRotAngle = RotAngle + GetAngle ( lpVectorInfo, &Center, &lpP[i] );
|
|
if (TotalRotAngle > 3600)
|
|
TotalRotAngle -= 3600;
|
|
|
|
Dist = GetDistance( lpVectorInfo, &Center, &lpP[i] );
|
|
lpP[i].x = Center.x + (SHORT)(((LONG)Dist * (LONG)(cosval(TotalRotAngle)))/10000)*lpVectorInfo->XDirection;
|
|
lpP[i].y = Center.y - (SHORT)(((LONG)Dist * (LONG)(sinval(TotalRotAngle)))/10000)*lpVectorInfo->YDirection;
|
|
}
|
|
i++;
|
|
/* Check for end point */
|
|
if ( j == TotalQuads-1 )
|
|
{
|
|
if ( lPx * lEndy <= lPy * lEndx )
|
|
{
|
|
k = 900; /* end the loops */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( StartAngle < EndAngle )
|
|
TotalQuads = EndQuad - StartQuad + 1;
|
|
else
|
|
TotalQuads = 5 - (StartQuad - EndQuad);
|
|
|
|
for ( j=0; j < TotalQuads; j++ )
|
|
{
|
|
PointQuad = (StartQuad+j) % 4;
|
|
for ( k=0; k < 900; k+=10 )
|
|
{
|
|
Angle = (PointQuad*900)+k;
|
|
lpP[i].x = Center.x + (SHORT)(((LONG)Radius.x * (LONG)(cosval(Angle)))/10000)*lpVectorInfo->XDirection;
|
|
lpP[i].y = Center.y - (SHORT)(((LONG)Radius.y * (LONG)(sinval(Angle)))/10000)*lpVectorInfo->YDirection;
|
|
lPx = (lpP[i].x - Center.x)*lpVectorInfo->XDirection;
|
|
lPy = (lpP[i].y - Center.y)*lpVectorInfo->YDirection;
|
|
if ( !bAddPoint )
|
|
{
|
|
if ( lPx * lStarty >= lPy * lStartx )
|
|
bAddPoint = TRUE;
|
|
}
|
|
if ( bAddPoint )
|
|
{
|
|
if (RotAngle) // Rotate the point
|
|
{
|
|
TotalRotAngle = RotAngle + GetAngle ( lpVectorInfo, &Center, &lpP[i] );
|
|
if (TotalRotAngle > 3600)
|
|
TotalRotAngle -= 3600;
|
|
Dist = GetDistance( lpVectorInfo, &Center, &lpP[i] );
|
|
lpP[i].x = Center.x + (SHORT)(((LONG)Dist * (LONG)(cosval(TotalRotAngle)))/10000)*lpVectorInfo->XDirection;
|
|
lpP[i].y = Center.y - (SHORT)(((LONG)Dist * (LONG)(sinval(TotalRotAngle)))/10000)*lpVectorInfo->YDirection;
|
|
}
|
|
i++;
|
|
/* Check for end point */
|
|
if ( j == TotalQuads-1 )
|
|
{
|
|
if ( lPx * lEndy >= lPy * lEndx )
|
|
{
|
|
k = 900; /* end the loops */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ( wItemId == SO_ARC || wItemId == SO_ARCCLOCKWISE )
|
|
{
|
|
lpVectorInfo->PolyInfo.wFormat = SOPT_POLYLINE;
|
|
}
|
|
else if ( wItemId == SO_CHORD )
|
|
{
|
|
lpVectorInfo->PolyInfo.wFormat = SOPT_POLYGON;
|
|
lpP[i++] = *lpTop;
|
|
}
|
|
else if ( wItemId == SO_PIE )
|
|
{
|
|
lpVectorInfo->PolyInfo.wFormat = SOPT_POLYGON;
|
|
lpP[i++] = Center;
|
|
lpP[i++] = *lpTop;
|
|
}
|
|
|
|
UTGlobalUnlock ( lpVectorInfo->PolyPoints.hPoints );
|
|
lpVectorInfo->PolyPoints.nCount += i;
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------
|
|
AddRecordToPath
|
|
|
|
By the time this routine is called the record has already been transformed
|
|
into a poly object. This routine buffers up the poly objects. Note, at
|
|
this stage the path is still allowed to contain beziers and splines. This
|
|
is acceptable for drawing the path but if the path is to be used as a
|
|
clipping region it must first be transformed into a series of polygons.
|
|
|
|
*/
|
|
#define POLYCOUNTALLOC 10
|
|
SHORT AddRecordToPath ( lpVectorInfo, lpVectorRecord )
|
|
LPVECTORINFO lpVectorInfo;
|
|
LPVRECORDHEADER lpVectorRecord;
|
|
{
|
|
SHORT nCount;
|
|
LPSHORT lpPolyCounts;
|
|
HPBYTE hpDst;
|
|
LPBYTE lpSrc;
|
|
DWORD dwSize;
|
|
LPPOINTBUF lpPointBuf;
|
|
LPPATHINFO lpCP;
|
|
|
|
if ( lpVectorRecord->nItemId != SO_ENDPOLY )
|
|
return(0);
|
|
|
|
/*
|
|
| First, if spline or bezier then translate to polyline or polygon.
|
|
*/
|
|
|
|
if ( lpVectorInfo->PolyInfo.wFormat == SOPT_SPLINEOPEN ||
|
|
lpVectorInfo->PolyInfo.wFormat == SOPT_SPLINECLOSE ||
|
|
lpVectorInfo->PolyInfo.wFormat == SOPT_BEZIEROPEN ||
|
|
lpVectorInfo->PolyInfo.wFormat == SOPT_BEZIERCLOSE )
|
|
{
|
|
OIMPolyObject ( NULL, lpVectorInfo, &lpVectorInfo->PolyInfo, &lpVectorInfo->PolyPoints, FALSE);
|
|
lpPointBuf = &lpVectorInfo->BezierPoints;
|
|
}
|
|
else
|
|
lpPointBuf = &lpVectorInfo->PolyPoints;
|
|
|
|
/* Now add the lpPointBuf to the current sub-path */
|
|
lpCP = &lpVectorInfo->CurrentPath;
|
|
/* Check space for polycounts */
|
|
nCount = lpPointBuf->nCount;
|
|
if ( nCount == 0 )
|
|
return(0);
|
|
if ( lpCP->hPolyCounts == NULL )
|
|
{
|
|
if((lpCP->hPolyCounts = UTGlobalAlloc(sizeof(SHORT)*POLYCOUNTALLOC)) == NULL )
|
|
return(0);
|
|
}
|
|
else
|
|
{
|
|
dwSize = UTGlobalSize(lpCP->hPolyCounts);
|
|
if ( dwSize < (DWORD)(sizeof(SHORT)*(lpCP->nPolys+1)) )
|
|
{
|
|
HANDLE hMem;
|
|
if ( ( hMem = UTGlobalReAlloc( lpCP->hPolyCounts, dwSize + (sizeof(SHORT)*POLYCOUNTALLOC))) == NULL )
|
|
return(0);
|
|
lpCP->hPolyCounts = hMem;
|
|
#ifdef MAC
|
|
hpDst = UTGlobalLock(hMem);
|
|
hpDst += dwSize;
|
|
memset(hpDst,0,UTGlobalSize(hMem)-dwSize);
|
|
UTGlobalUnlock(hMem);
|
|
#endif
|
|
}
|
|
}
|
|
/* Check space for polypoints */
|
|
if ( lpCP->hPolyPoints == NULL )
|
|
{
|
|
if((lpCP->hPolyPoints = UTGlobalAlloc(sizeof(SOPOINT)*(nCount+1))) == NULL )
|
|
return(0);
|
|
}
|
|
else
|
|
{
|
|
DWORD dwSize;
|
|
HANDLE hMem;
|
|
dwSize = UTGlobalSize(lpCP->hPolyPoints);
|
|
if ( ( hMem = UTGlobalReAlloc( lpCP->hPolyPoints, dwSize + (DWORD)(sizeof(SOPOINT)*(nCount+1)))) == NULL )
|
|
return(0);
|
|
lpCP->hPolyPoints = hMem;
|
|
}
|
|
|
|
/* Add points */
|
|
if((lpSrc = UTGlobalLock ( lpPointBuf->hPoints))==NULL)
|
|
return(0);
|
|
|
|
if((hpDst = (HPBYTE)UTGlobalLock ( lpCP->hPolyPoints ))==NULL)
|
|
{
|
|
UTGlobalUnlock(lpPointBuf->hPoints);
|
|
return(0);
|
|
}
|
|
hpDst += lpCP->dwTotalPoints*(DWORD)sizeof(SOPOINT);
|
|
UTmemcpy ( (LPBYTE)hpDst, lpSrc, sizeof(SOPOINT)*nCount);
|
|
UTGlobalUnlock(lpPointBuf->hPoints);
|
|
UTGlobalUnlock(lpCP->hPolyPoints);
|
|
|
|
if((lpPolyCounts = (LPSHORT)UTGlobalLock(lpCP->hPolyCounts))==NULL)
|
|
return(0);
|
|
lpPolyCounts += lpCP->nPolys;
|
|
*lpPolyCounts += nCount;
|
|
UTGlobalUnlock(lpCP->hPolyCounts);
|
|
lpCP->dwTotalPoints += nCount;
|
|
lpVectorInfo->wPathFlags = CP_LASTSUBOPEN | CP_BUFFERED;
|
|
|
|
}
|
|
|
|
VOID FreePath ( lpVectorInfo )
|
|
LPVECTORINFO lpVectorInfo;
|
|
{
|
|
if ( lpVectorInfo->CurrentPath.hPolyCounts )
|
|
{
|
|
UTGlobalFree ( lpVectorInfo->CurrentPath.hPolyCounts );
|
|
lpVectorInfo->CurrentPath.hPolyCounts = NULL;
|
|
}
|
|
if ( lpVectorInfo->CurrentPath.hPolyPoints )
|
|
{
|
|
UTGlobalFree ( lpVectorInfo->CurrentPath.hPolyPoints );
|
|
lpVectorInfo->CurrentPath.hPolyPoints = NULL;
|
|
}
|
|
lpVectorInfo->CurrentPath.nPolys = 0;
|
|
lpVectorInfo->CurrentPath.dwTotalPoints = 0;
|
|
lpVectorInfo->wPathFlags = 0;
|
|
}
|
|
|
|
VOID DrawPath ( hDC, lpVectorInfo, wDrawFlags )
|
|
HDC hDC;
|
|
LPVECTORINFO lpVectorInfo;
|
|
WORD wDrawFlags;
|
|
{
|
|
PSOPOINT lpPolyPoints;
|
|
LPSHORT lpPolyCounts;
|
|
LPPATHINFO lpCP;
|
|
lpCP = &lpVectorInfo->CurrentPath;
|
|
if ( lpCP->dwTotalPoints )
|
|
{
|
|
lpPolyCounts = (LPSHORT)UTGlobalLock ( lpCP->hPolyCounts );
|
|
if ( lpPolyCounts == NULL )
|
|
return;
|
|
lpPolyPoints = (PSOPOINT)UTGlobalLock ( lpCP->hPolyPoints );
|
|
if ( lpPolyPoints == NULL )
|
|
{
|
|
UTGlobalUnlock ( lpCP->hPolyCounts );
|
|
return;
|
|
}
|
|
if ( (wDrawFlags & (SODP_STROKE|SODP_FILL)) == (SODP_STROKE|SODP_FILL))
|
|
{
|
|
if ( lpCP->nPolys == 1 )
|
|
VUPolygon ( hDC, lpPolyPoints, *lpPolyCounts );
|
|
else
|
|
VUPolyPolygon ( hDC, lpPolyPoints, lpPolyCounts, lpCP->nPolys );
|
|
}
|
|
else if ( wDrawFlags & SODP_STROKE ) /* only draw polylines */
|
|
{
|
|
SHORT i;
|
|
for ( i=0; i < lpCP->nPolys; i++ )
|
|
{
|
|
VUPolyline ( hDC, lpPolyPoints, *lpPolyCounts );
|
|
lpPolyPoints += *lpPolyCounts;
|
|
lpPolyCounts++;
|
|
}
|
|
}
|
|
else if ( wDrawFlags & SODP_FILL ) /* no pen */
|
|
{
|
|
HANDLE hSavePen;
|
|
hSavePen = VUSelectStockObject ( hDC, VUNULL_PEN );
|
|
if ( lpCP->nPolys == 1 )
|
|
VUPolygon ( hDC, lpPolyPoints, *lpPolyCounts );
|
|
else
|
|
VUPolyPolygon ( hDC, lpPolyPoints, lpPolyCounts, lpCP->nPolys );
|
|
VUSelectObject ( hDC, hSavePen );
|
|
}
|
|
UTGlobalUnlock ( lpCP->hPolyCounts );
|
|
UTGlobalUnlock ( lpCP->hPolyPoints );
|
|
}
|
|
}
|
|
/*-------------------------------------------------------------------------
|
|
SetClipMode
|
|
|
|
This routine handles setting the clipping mode to either the current path
|
|
or to the dimensions of the bounding rectangle of the image. Since the
|
|
current path may include bezier or spline definitions they must first
|
|
be translated into polygons. The CreatePolyPolygonRgn is then used
|
|
to create the clipping region. Also, regions are device dependent so
|
|
all points must be translated to device coordinates when creating the
|
|
polypolygon.
|
|
*/
|
|
|
|
SHORT SetClipMode ( hDC, lpVectorInfo, lpDisplay )
|
|
HDC hDC;
|
|
LPVECTORINFO lpVectorInfo;
|
|
POIM_DISPLAY lpDisplay;
|
|
{
|
|
PSOPOINT lpPolyPoints, lpClipPolyPoints;
|
|
LPSHORT lpPolyCounts;
|
|
HANDLE hClipPolyPoints;
|
|
HRGN hRgn;
|
|
DWORD dwSize;
|
|
LPPATHINFO lpCP;
|
|
|
|
if ( lpDisplay->wPlayState == OIMF_PLAYTOMETA )
|
|
return(0);
|
|
|
|
if ( lpVectorInfo->wClipMode == SO_CLIPTOPATH )
|
|
{
|
|
lpCP = &lpVectorInfo->CurrentPath;
|
|
if ( lpCP->dwTotalPoints && lpCP->hPolyPoints && lpCP->hPolyCounts )
|
|
{
|
|
/* Make a copy of the points in order to translate to device units */
|
|
dwSize = UTGlobalSize ( lpCP->hPolyPoints );
|
|
hClipPolyPoints = UTGlobalAlloc(dwSize );
|
|
if ( hClipPolyPoints == NULL )
|
|
return(0);
|
|
lpClipPolyPoints = (PSOPOINT)UTGlobalLock ( hClipPolyPoints );
|
|
lpPolyPoints = (PSOPOINT)UTGlobalLock ( lpCP->hPolyPoints );
|
|
UTmemcpy ( (LPBYTE)lpClipPolyPoints, (LPBYTE)lpPolyPoints, (WORD)dwSize );
|
|
UTGlobalUnlock ( lpCP->hPolyPoints );
|
|
|
|
lpPolyCounts = (LPSHORT)UTGlobalLock ( lpCP->hPolyCounts );
|
|
if ( lpPolyCounts == NULL )
|
|
return(0);
|
|
|
|
VULPtoDP ( hDC, lpClipPolyPoints, (WORD)(lpCP->dwTotalPoints) );
|
|
/* And clip to this region */
|
|
if ( lpCP->nPolys == 1 )
|
|
hRgn = VUCreatePolygonRgn ( (PSOPOINT)lpClipPolyPoints, *lpPolyCounts, lpVectorInfo->nPolyFillMode );
|
|
else
|
|
hRgn = VUCreatePolyPolygonRgn ( (PSOPOINT)lpClipPolyPoints, lpPolyCounts, lpCP->nPolys, lpVectorInfo->nPolyFillMode );
|
|
UTGlobalUnlock ( lpCP->hPolyCounts );
|
|
UTGlobalUnlock ( hClipPolyPoints );
|
|
UTGlobalFree ( hClipPolyPoints );
|
|
if ( lpVectorInfo->hSelectRgn )
|
|
VUIntersectRgn ( hRgn, hRgn, lpVectorInfo->hSelectRgn );
|
|
if ( hRgn )
|
|
{
|
|
VUSelectClipRgn(hDC,hRgn);
|
|
}
|
|
VUDeleteRgn ( hRgn );
|
|
}
|
|
}
|
|
else /* clip to the bounding rect of the image */
|
|
{
|
|
if ( lpVectorInfo->hSelectRgn )
|
|
VUSelectClipRgn ( hDC, lpVectorInfo->hSelectRgn );
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
The following routines expect the parameter in angles in 10ths of a degree.
|
|
They return the cosine and sine values as integers in a ratio to 10000.
|
|
*/
|
|
CosTable[91] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9
|
|
10000,9998, 9993, 9986, 9975, 9961, 9945, 9925, 9902, 9876, //0-9
|
|
9848, 9816, 9781, 9743, 9702, 9659, 9612, 9563, 9510, 9455, //10-19
|
|
9396, 9335, 9271, 9205, 9135, 9063, 8987, 8910, 8829, 8746, //20-29
|
|
8660, 8571, 8480, 8386, 8290, 8191, 8090, 7986, 7880, 7771, //30-39
|
|
7660, 7547, 7431, 7313, 7193, 7071, 6946, 6819, 6691, 6560, //40-49
|
|
6427, 6293, 6156, 6018, 5877, 5735, 5591, 5446, 5299, 5150, //50-59
|
|
5000, 4848, 4694, 4539, 4383, 4226, 4067, 3907, 3746, 3583, //60-69
|
|
3420, 3255, 3090, 2923, 2756, 2588, 2419, 2249, 2079, 1908, //70-79
|
|
1736, 1564, 1391, 1218, 1045, 871, 697, 523, 348, 174, //80-89
|
|
0,
|
|
};
|
|
|
|
/* Angles are passed in in 10ths of a degree */
|
|
SHORT cosval ( angle )
|
|
SHORT angle;
|
|
{
|
|
angle = (angle/10) % 360;
|
|
if ( angle < 0 )
|
|
angle = 360 + angle;
|
|
if ( angle <= 90 )
|
|
return(CosTable[angle]);
|
|
if ( angle <= 180 )
|
|
return(-CosTable[180-angle]);
|
|
if ( angle <= 270 )
|
|
return(-CosTable[(angle-180)]);
|
|
if ( angle < 360 )
|
|
return(CosTable[360-angle]);
|
|
}
|
|
|
|
SHORT sinval ( angle )
|
|
SHORT angle;
|
|
{
|
|
angle = (angle/10) % 360;
|
|
if ( angle < 0 )
|
|
angle = 360 + angle;
|
|
if ( angle <= 90 )
|
|
return(CosTable[90-angle]);
|
|
if ( angle <= 180 )
|
|
return(CosTable[angle-90]);
|
|
if ( angle <= 270 )
|
|
return(-CosTable[270-angle]);
|
|
if ( angle < 360 )
|
|
return(-CosTable[(angle-270)]);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
This routine determines the angle (in 10ths of a degree) formed by drawing
|
|
a horizontal line to the right of p1 and a line from p1 to p2.
|
|
*/
|
|
|
|
SHORT GetAngle ( lpVectorInfo, p1, p2 )
|
|
LPVECTORINFO lpVectorInfo;
|
|
PSOPOINT p1;
|
|
PSOPOINT p2;
|
|
{
|
|
SHORT i, x, y;
|
|
SHORT ax, ay;
|
|
SHORT quad;
|
|
x = (p2->x - p1->x) * lpVectorInfo->XDirection;
|
|
/* Since the default direction is down in the y the subtraction is inverted */
|
|
y = (p1->y - p2->y) * lpVectorInfo->YDirection;
|
|
|
|
if ( x < 0 )
|
|
ax = -x;
|
|
else
|
|
ax = x;
|
|
if ( y >= 0 )
|
|
{
|
|
ay = y;
|
|
if ( x >= 0 )
|
|
quad = 0;
|
|
else
|
|
quad = 1;
|
|
}
|
|
else
|
|
{
|
|
ay = -y;
|
|
if ( x >= 0 )
|
|
quad = 3;
|
|
else
|
|
quad = 2;
|
|
}
|
|
for ( i=0; i < 900; i+=10 )
|
|
{
|
|
if ( ay <= (SHORT)(((LONG)ax*(LONG)sinval(i))/(LONG)cosval(i)))
|
|
break;
|
|
}
|
|
if ( quad == 0 )
|
|
return (i);
|
|
if ( quad == 1 )
|
|
return (1800-i);
|
|
if ( quad == 2 )
|
|
return(1800+i);
|
|
return(3600-i);
|
|
}
|
|
|
|
SHORT GetDistance ( lpVectorInfo, p1, p2 )
|
|
LPVECTORINFO lpVectorInfo;
|
|
PSOPOINT p1;
|
|
PSOPOINT p2;
|
|
{
|
|
SHORT trigfactor;
|
|
SHORT Distance;
|
|
SOANGLE Angle;
|
|
|
|
|
|
Angle = GetAngle ( lpVectorInfo, p1, p2 );
|
|
|
|
if (((Angle > 450) && (Angle < 1350)) || ((Angle > 2250) && (Angle < 3150)))
|
|
{
|
|
trigfactor = sinval ( Angle );
|
|
Distance = p2->y - p1->y;
|
|
}
|
|
else
|
|
{
|
|
trigfactor = cosval ( Angle );
|
|
Distance = p2->x - p1->x;
|
|
}
|
|
if (trigfactor != 0) // This should always be non zero
|
|
Distance = (SHORT)(((LONG)Distance*10000L)/(LONG)trigfactor);
|
|
|
|
if ( Distance < 0 )
|
|
Distance = -Distance;
|
|
|
|
return(Distance);
|
|
}
|
|
|
|
VOID CloseSubPath ( lpVectorInfo )
|
|
LPVECTORINFO lpVectorInfo;
|
|
{
|
|
LPPATHINFO lpCP;
|
|
HPSOPOINT hpFirstPoint;
|
|
HPSOPOINT hpEndPoint;
|
|
LPSHORT lpCounts;
|
|
lpCP = &lpVectorInfo->CurrentPath;
|
|
if ( (lpVectorInfo->wPathFlags & CP_BUFFERED ) &&
|
|
(lpCP->dwTotalPoints) )
|
|
{
|
|
/*
|
|
| Check current subpath - if last point is not first point then
|
|
| add a new point equal to the first point. Support paths beyond
|
|
| 64K of data.
|
|
*/
|
|
lpCounts = (LPSHORT)UTGlobalLock(lpCP->hPolyCounts);
|
|
lpCounts += lpCP->nPolys;
|
|
hpFirstPoint = (HPSOPOINT)UTGlobalLock(lpCP->hPolyPoints);
|
|
/* Set hpEnd to last point in path */
|
|
hpEndPoint = hpFirstPoint + (lpCP->dwTotalPoints-1L);
|
|
/* Move hpSrc to first point of this subpath */
|
|
hpFirstPoint = hpEndPoint - ((DWORD)*lpCounts-1L);
|
|
if ( hpFirstPoint->x != hpEndPoint->x ||
|
|
hpFirstPoint->y != hpEndPoint->y )
|
|
{
|
|
hpEndPoint++;
|
|
*hpEndPoint = *hpFirstPoint;
|
|
*lpCounts = (*lpCounts)+1;
|
|
lpCP->dwTotalPoints++;
|
|
}
|
|
UTGlobalUnlock(lpCP->hPolyCounts);
|
|
UTGlobalUnlock(lpCP->hPolyPoints);
|
|
lpVectorInfo->CurrentPath.nPolys++;
|
|
}
|
|
lpVectorInfo->wPathFlags = 0; /* not open, not buffered */
|
|
}
|
|
|
|
VOID RelatePoints ( lpVectorInfo, lpPoint, nCount )
|
|
LPVECTORINFO lpVectorInfo;
|
|
PSOPOINT lpPoint;
|
|
SHORT nCount;
|
|
{
|
|
SHORT i;
|
|
if ( lpVectorInfo->nPointRelation == SOPR_ABSOLUTE )
|
|
{
|
|
lpVectorInfo->ptCurrentPosition = lpPoint[nCount-1];
|
|
return;
|
|
}
|
|
for ( i=0; i < nCount; i++ )
|
|
{
|
|
lpPoint->x += lpVectorInfo->ptCurrentPosition.x;
|
|
lpPoint->y += lpVectorInfo->ptCurrentPosition.y;
|
|
lpVectorInfo->ptCurrentPosition = *(lpPoint);
|
|
lpPoint++;
|
|
}
|
|
}
|
|
|
|
VOID CpArcToPoints ( lpVectorInfo, lpCpArcAngle, lpPoint )
|
|
LPVECTORINFO lpVectorInfo;
|
|
PSOCPARCANGLE lpCpArcAngle;
|
|
PSOPOINT lpPoint;
|
|
{
|
|
SOPOINT Center, Cp;
|
|
SHORT StartAngle, EndAngle;
|
|
SHORT Radius;
|
|
SHORT cosangle;
|
|
Center = lpCpArcAngle->Center;
|
|
Cp = lpVectorInfo->ptCurrentPosition;
|
|
RelatePoints ( lpVectorInfo, &Center, 1 );
|
|
StartAngle = GetAngle ( lpVectorInfo, &Center, &Cp );
|
|
EndAngle = (StartAngle + lpCpArcAngle->SweepAngle) % 3600;
|
|
cosangle = cosval ( StartAngle );
|
|
Radius = Cp.x - Center.x;
|
|
if ( cosangle != 0 )
|
|
Radius = (SHORT)(((LONG)Radius*10000L)/(LONG)cosangle);
|
|
if ( Radius < 0 )
|
|
Radius = -Radius;
|
|
lpPoint[0].x = Center.x - Radius*(lpVectorInfo->XDirection);
|
|
lpPoint[0].y = Center.y - Radius*(lpVectorInfo->YDirection);
|
|
lpPoint[1].x = Center.x + Radius*(lpVectorInfo->XDirection);
|
|
lpPoint[1].y = Center.y + Radius*(lpVectorInfo->YDirection);
|
|
lpPoint[2] = Cp;
|
|
lpPoint[3].x = Center.x + (SHORT)(Radius*((LONG)cosval(EndAngle))/10000L)*lpVectorInfo->XDirection;
|
|
lpPoint[3].y = Center.y - (SHORT)(Radius*((LONG)sinval(EndAngle))/10000L)*lpVectorInfo->YDirection;
|
|
}
|
|
|
|
VOID CpPieToPoints ( lpVectorInfo, lpCpPieAngle, lpPoint )
|
|
LPVECTORINFO lpVectorInfo;
|
|
PSOCPPIEANGLE lpCpPieAngle;
|
|
PSOPOINT lpPoint;
|
|
{
|
|
SOPOINT Center;
|
|
SOANGLE StartAngle, EndAngle;
|
|
SOPOINT Radius;
|
|
|
|
Center = lpVectorInfo->ptCurrentPosition;
|
|
StartAngle = lpCpPieAngle->StartAngle;
|
|
EndAngle = (StartAngle + lpCpPieAngle->SweepAngle) % 3600;
|
|
Radius = lpCpPieAngle->Radius;
|
|
lpPoint[0].x = Center.x - Radius.x*(lpVectorInfo->XDirection);
|
|
lpPoint[0].y = Center.y - Radius.y*(lpVectorInfo->YDirection);
|
|
lpPoint[1].x = Center.x + Radius.x*(lpVectorInfo->XDirection);
|
|
lpPoint[1].y = Center.y + Radius.y*(lpVectorInfo->YDirection);
|
|
lpPoint[3].x = Center.x + (SHORT)(Radius.x*((LONG)cosval(StartAngle))/10000L)*lpVectorInfo->XDirection;
|
|
lpPoint[3].y = Center.y - (SHORT)(Radius.y*((LONG)sinval(StartAngle))/10000L)*lpVectorInfo->YDirection;
|
|
lpPoint[3].x = Center.x + (SHORT)(Radius.x*((LONG)cosval(EndAngle))/10000L)*lpVectorInfo->XDirection;
|
|
lpPoint[3].y = Center.y - (SHORT)(Radius.y*((LONG)sinval(EndAngle))/10000L)*lpVectorInfo->YDirection;
|
|
}
|
|
|
|
SHORT ArcTripleToPoints ( lpVectorInfo, lpThreePoints, lpPoint )
|
|
LPVECTORINFO lpVectorInfo;
|
|
PSOPOINT lpThreePoints;
|
|
PSOPOINT lpPoint;
|
|
{
|
|
SOPOINT StartPoint, MidPoint, EndPoint, Center;
|
|
LONG A, B, D;
|
|
LONG x1, x2, x3, y1, y2, y3, z1, z2, z3;
|
|
SOANGLE StartAngle, MidAngle, EndAngle;
|
|
SHORT Radius;
|
|
|
|
#define FACTORSIZE 10
|
|
|
|
StartPoint = lpThreePoints[0];
|
|
MidPoint = lpThreePoints[1];
|
|
EndPoint = lpThreePoints[2];
|
|
// StartPoint = lpVectorInfo->ptCurrentPosition;
|
|
// RelatePoints ( lpVectorInfo, &MidPoint, 1 );
|
|
// lpVectorInfo->ptCurrentPosition = StartPoint;
|
|
// RelatePoints ( lpVectorInfo, &EndPoint, 1 );
|
|
x1 = (LONG)StartPoint.x/FACTORSIZE;
|
|
y1 = (LONG)StartPoint.y/FACTORSIZE;
|
|
x2 = (LONG)MidPoint.x/FACTORSIZE;
|
|
y2 = (LONG)MidPoint.y/FACTORSIZE;
|
|
x3 = (LONG)EndPoint.x/FACTORSIZE;
|
|
y3 = (LONG)EndPoint.y/FACTORSIZE;
|
|
z1 = (-1L*x1*x1) - (y1*y1);
|
|
z2 = (-1L*x2*x2) - (y2*y2);
|
|
z3 = (-1L*x3*x3) - (y3*y3);
|
|
|
|
D = Matrix3x3 ( x1, y1, x2, y2, x3, y3 );
|
|
if ( D == 0 )
|
|
return(0);
|
|
|
|
A = Matrix3x3 ( z1, y1, z2, y2, z3, y3 );
|
|
B = Matrix3x3 ( x1, z1, x2, z2, x3, z3 );
|
|
|
|
Center.x = (SHORT)(-A/(2*D))*FACTORSIZE;
|
|
Center.y = (SHORT)(-B/(2*D))*FACTORSIZE;
|
|
|
|
/* Determine Radius */
|
|
Radius = GetDistance( lpVectorInfo, &Center, &StartPoint );
|
|
|
|
lpPoint[0].x = Center.x - Radius*(lpVectorInfo->XDirection);
|
|
lpPoint[0].y = Center.y - Radius*(lpVectorInfo->YDirection);
|
|
lpPoint[1].x = Center.x + Radius*(lpVectorInfo->XDirection);
|
|
lpPoint[1].y = Center.y + Radius*(lpVectorInfo->YDirection);
|
|
|
|
lpPoint[2] = StartPoint;
|
|
lpPoint[3] = EndPoint;
|
|
|
|
/* Determine if this is clockwise or counterclockwise */
|
|
StartAngle = GetAngle ( lpVectorInfo, &Center, &StartPoint );
|
|
MidAngle = GetAngle ( lpVectorInfo, &Center, &MidPoint ) - StartAngle;
|
|
if (MidAngle < 0)
|
|
MidAngle += 3600;
|
|
EndAngle = GetAngle ( lpVectorInfo, &Center, &EndPoint ) - StartAngle;
|
|
if (EndAngle < 0)
|
|
EndAngle += 3600;
|
|
|
|
if (MidAngle > EndAngle)
|
|
return(2); // Clockwise
|
|
else
|
|
return(1); // Counter Clockwise
|
|
}
|
|
|
|
SHORT EllipseRadiiToPoints ( lpVectorInfo, lpThreePoints, lpPoint )
|
|
LPVECTORINFO lpVectorInfo;
|
|
PSOPOINT lpThreePoints;
|
|
PSOPOINT lpPoint;
|
|
{
|
|
SHORT RotAngle, Dx, Dy;
|
|
SOPOINT Radii[2], Center;
|
|
|
|
Center = lpThreePoints[0];
|
|
Radii[0] = lpThreePoints[1];
|
|
Radii[1] = lpThreePoints[2];
|
|
Dx = GetDistance( lpVectorInfo, &Center, &Radii[0] );
|
|
Dy = GetDistance( lpVectorInfo, &Center, &Radii[1] );
|
|
|
|
lpPoint[0].x = Center.x - Dx; // Upper left
|
|
lpPoint[0].y = Center.y + Dy;
|
|
lpPoint[1].x = Center.x + Dx; // Lower Right
|
|
lpPoint[1].y = Center.y - Dy;
|
|
|
|
RotAngle = GetAngle ( lpVectorInfo, &Center, &Radii[0]);
|
|
if (RotAngle % 1800)
|
|
{
|
|
lpVectorInfo->PolyInfo.wFormat = SOPT_BEZIERCLOSE;
|
|
lpVectorInfo->PolyPoints.nCount = 0;
|
|
AddEllipseToBezier ( lpPoint, lpVectorInfo, RotAngle );
|
|
return (1);
|
|
}
|
|
else
|
|
return (0);
|
|
}
|
|
|
|
|
|
SHORT ArcRadiiToPoints ( lpVectorInfo, lpFivePoints, lpPoint )
|
|
LPVECTORINFO lpVectorInfo;
|
|
PSOPOINT lpFivePoints;
|
|
PSOPOINT lpPoint;
|
|
{
|
|
SHORT RotAngle, Dx, Dy, Angle, Dist;
|
|
SOPOINT Radii[2], Center;
|
|
|
|
Center = lpFivePoints[0];
|
|
Radii[0] = lpFivePoints[1];
|
|
Radii[1] = lpFivePoints[2];
|
|
|
|
lpPoint[2] = lpFivePoints[3]; // Arc points
|
|
lpPoint[3] = lpFivePoints[4];
|
|
|
|
Dx = GetDistance( lpVectorInfo, &Center, &Radii[0] );
|
|
Dy = GetDistance( lpVectorInfo, &Center, &Radii[1] );
|
|
|
|
lpPoint[0].x = Center.x - Dx; // Upper left
|
|
lpPoint[0].y = Center.y + Dy;
|
|
lpPoint[1].x = Center.x + Dx; // Lower Right
|
|
lpPoint[1].y = Center.y - Dy;
|
|
|
|
RotAngle = GetAngle ( lpVectorInfo, &Center, &Radii[0]);
|
|
if (RotAngle % 1800)
|
|
{
|
|
Dist = GetDistance( lpVectorInfo, &Center, &lpPoint[2]); // Rotate back the arc points
|
|
Angle = GetAngle ( lpVectorInfo, &Center, &lpPoint[2]);
|
|
Angle -= RotAngle;
|
|
if (Angle < 0)
|
|
Angle += 3600;
|
|
lpPoint[2].x = Center.x + (SHORT)(((LONG)Dist * (LONG)(cosval(Angle)))/10000)*lpVectorInfo->XDirection;
|
|
lpPoint[2].y = Center.y - (SHORT)(((LONG)Dist * (LONG)(sinval(Angle)))/10000)*lpVectorInfo->YDirection;
|
|
|
|
Dist = GetDistance( lpVectorInfo, &Center, &lpPoint[3]); // Rotate back the arc points
|
|
Angle = GetAngle ( lpVectorInfo, &Center, &lpPoint[3]);
|
|
Angle -= RotAngle;
|
|
if (Angle < 0)
|
|
Angle += 3600;
|
|
lpPoint[3].x = Center.x + (SHORT)(((LONG)Dist * (LONG)(cosval(Angle)))/10000)*lpVectorInfo->XDirection;
|
|
lpPoint[3].y = Center.y - (SHORT)(((LONG)Dist * (LONG)(sinval(Angle)))/10000)*lpVectorInfo->YDirection;
|
|
|
|
lpVectorInfo->PolyInfo.wFormat = SOPT_POLYGON;
|
|
lpVectorInfo->PolyPoints.nCount = 0;
|
|
return (RotAngle);
|
|
}
|
|
else
|
|
return (0);
|
|
}
|
|
|
|
|
|
LONG Matrix3x3 ( a1, b1, a2, b2, a3, b3 )
|
|
LONG a1, b1, a2, b2, a3, b3;
|
|
{
|
|
return((a1*b2)+(a2*b3)+(a3*b1)-(a3*b2)-(a2*b1)-(a1*b3));
|
|
}
|
|
|
|
VOID AddToPalette ( hDC, lpDisplay, lpColor )
|
|
HDC hDC;
|
|
POIM_DISPLAY lpDisplay;
|
|
SOCOLORREF FAR *lpColor;
|
|
{
|
|
SOCOLORREF Color;
|
|
SOCOLORREF VWPTR *pColorRef;
|
|
WORD i;
|
|
if ( lpDisplay->VectorInfo.wNewPaletteSize == 255 )
|
|
return;
|
|
if ( lpDisplay->VectorInfo.hNewPalette == NULL )
|
|
{
|
|
if ( (lpDisplay->VectorInfo.hNewPalette = UTGlobalAlloc(256*sizeof(SOCOLORREF))) == NULL )
|
|
{
|
|
return;
|
|
}
|
|
/*
|
|
Set palette size to 1 since 0th entry is reserved for black
|
|
note that 255th entry is reserved for white
|
|
*/
|
|
lpDisplay->VectorInfo.wNewPaletteSize = 1;
|
|
pColorRef = (SOCOLORREF VWPTR *) UTGlobalLock( lpDisplay->VectorInfo.hNewPalette );
|
|
*pColorRef = SORGB ( 0, 0, 0 );
|
|
UTGlobalUnlock( lpDisplay->VectorInfo.hNewPalette );
|
|
}
|
|
Color = *lpColor;
|
|
pColorRef = (SOCOLORREF VWPTR *) UTGlobalLock( lpDisplay->VectorInfo.hNewPalette );
|
|
for ( i=0; i < lpDisplay->VectorInfo.wNewPaletteSize; i++ )
|
|
{
|
|
if ( *pColorRef == Color )
|
|
break;
|
|
pColorRef++;
|
|
}
|
|
if ( i == lpDisplay->VectorInfo.wNewPaletteSize )
|
|
{
|
|
*pColorRef = Color;
|
|
lpDisplay->VectorInfo.wNewPaletteSize++;
|
|
VUAddColorToPalette(lpDisplay,hDC,lpDisplay->Image.hPalette,i,pColorRef);
|
|
}
|
|
if ( i==255 )
|
|
lpDisplay->VectorInfo.bFinalPalette = TRUE;
|
|
|
|
UTGlobalUnlock( lpDisplay->VectorInfo.hNewPalette );
|
|
}
|
|
|