|
|
//
// DRAWOBJ.CPP
// Drawing objects: point, openpolyline, closepolyline, ellipse
//
// Copyright Microsoft 1998-
//
#include "precomp.h"
#define DECIMAL_PRECISION 100
DrawObj::DrawObj(UINT drawingType, UINT toolType): m_drawingType(drawingType), m_isDrawingCompleted(FALSE) { SetMyWorkspace(NULL); SetOwnerID(g_MyMemberID);
m_ToolType = toolType;
//
// Created locally, not selected, not editing or deleting.
//
CreatedLocally(); ClearSelectionFlags(); ClearEditionFlags(); ClearDeletionFlags();
SetFillColor(0,FALSE);
//
// No attributes changed, they will be set as we change them
//
ResetAttrib();
DBG_SAVE_FILE_LINE m_points = new DCDWordArray(); SetWorkspaceHandle(g_pCurrentWorkspace == NULL ? 0 : g_pCurrentWorkspace->GetWorkspaceHandle()); SetType(drawingCreatePDU_chosen); SetPenNib(circular_chosen); SetROP(R2_NOTXORPEN); SetPlaneID(1); SetMyPosition(NULL); SetMyWorkspace(NULL);
RECT rect; ::SetRectEmpty(&rect); SetBoundsRect(&rect); SetRect(&rect);
}
DrawObj::DrawObj (DrawingCreatePDU * pdrawingCreatePDU) { SetType(drawingCreatePDU_chosen); SetMyWorkspace(NULL);
//
// Created remotely, not selected, not editing or deleting.
//
ClearCreationFlags(); ClearSelectionFlags(); ClearEditionFlags(); ClearDeletionFlags();
ResetAttrib();
//
// Get the drawing handle
//
SetThisObjectHandle(pdrawingCreatePDU->drawingHandle);
//
// Get the destination address
//
UINT workspaceHandle = 0; UINT planeID = 0; GetDrawingDestinationAddress(&pdrawingCreatePDU->destinationAddress, &workspaceHandle, &planeID); SetWorkspaceHandle(workspaceHandle); SetPlaneID(planeID); TRACE_DEBUG(("Destination address, Workspace Handle = %d", workspaceHandle)); TRACE_DEBUG(("Destination address, Plane ID = %d", planeID));
//
// Get the drawing type, line, circle, etc ...
//
SetDrawingType(pdrawingCreatePDU->drawingType.choice);
//
// Set defaults
//
// m_T126Drawing.m_sampleRate = INVALID_SAMPLE_RATE;
//
// Default attributes
//
// Pen color black
SetPenColor(0,TRUE); // No fill color
SetFillColor(0,FALSE); // 1 Pixels for pen thickness
SetPenThickness(1); // Pen Nib is circular
SetPenNib(circular_chosen); // Solid line
SetLineStyle(PS_SOLID); // No highlight
SetHighlight(FALSE); // Not selected
SetViewState(unselected_chosen); // Top object
SetZOrder(front);
// This is a complete drawing
SetIsCompleted(TRUE);
//
// Get attributes
//
if(pdrawingCreatePDU->bit_mask & DrawingCreatePDU_attributes_present) { GetDrawingAttrib((PVOID)pdrawingCreatePDU->attributes); }
DBG_SAVE_FILE_LINE m_points = new DCDWordArray();
//
// Get Anchor point
//
POINT Point;
//
// For open polylines the first point will be an offset of the anchor point
//
if(pdrawingCreatePDU->drawingType.choice == openPolyLine_chosen) { Point.x = 0; Point.y = 0; AddPoint(Point); } SetAnchorPoint(pdrawingCreatePDU->anchorPoint.xCoordinate, pdrawingCreatePDU->anchorPoint.yCoordinate); GetAnchorPoint(&Point); RECT rect; rect.left = pdrawingCreatePDU->anchorPoint.xCoordinate; rect.top = pdrawingCreatePDU->anchorPoint.yCoordinate; rect.right = pdrawingCreatePDU->anchorPoint.xCoordinate; rect.bottom = pdrawingCreatePDU->anchorPoint.yCoordinate; SetRect(&rect); SetBoundsRect(&rect); AddPointToBounds(pdrawingCreatePDU->anchorPoint.xCoordinate, pdrawingCreatePDU->anchorPoint.yCoordinate); //
// Since we don't know ahead of time how many points we have, set the type as a polyline
//
m_ToolType = TOOLTYPE_PEN;
//
// Get consecutive points
//
UINT nPoints; nPoints = GetSubsequentPoints(pdrawingCreatePDU->pointList.choice, &Point, &pdrawingCreatePDU->pointList);
//
// Find out what UI tool are we, and set the correct ROP
//
SetUIToolType();
if(nPoints == 1) { POINT *point; point = m_points->GetBuffer(); rect.right = point->x + pdrawingCreatePDU->anchorPoint.xCoordinate; rect.bottom = point->y + pdrawingCreatePDU->anchorPoint.yCoordinate; SetRect(&rect); ::InflateRect(&rect, GetPenThickness()/2, GetPenThickness()/2); SetBoundsRect(&rect); } //
// Get Non standard stuff
//
if(pdrawingCreatePDU->bit_mask & DrawingCreatePDU_nonStandardParameters_present) { ; // NYI
}
}
DrawObj::~DrawObj( void ) { RemoveObjectFromResendList(this); RemoveObjectFromRequestHandleList(this);
TRACE_DEBUG(("drawingHandle = %d", GetThisObjectHandle() ));
//
// Tell other nodes that we are gone
//
if(GetMyWorkspace() != NULL && WasDeletedLocally()) { OnObjectDelete(); }
//
// Clear the list of points
//
delete m_points;
}
void DrawObj::DrawEditObj ( DrawingEditPDU * pdrawingEditPDU ) {
RECT rect; POSITION pos; POINT anchorPoint; LONG deltaX = 0; LONG deltaY = 0;
TRACE_DEBUG(("DrawEditObj drawingHandle = %d", pdrawingEditPDU->drawingHandle ));
//
// Was edited remotely
//
ClearEditionFlags();
//
// Read attributes
//
if(pdrawingEditPDU->bit_mask & DrawingEditPDU_attributeEdits_present) { GetDrawingAttrib((PVOID)pdrawingEditPDU->attributeEdits); }
//
// Change the anchor point
//
GetAnchorPoint(&anchorPoint); if(pdrawingEditPDU->bit_mask & DrawingEditPDU_anchorPointEdit_present) {
TRACE_DEBUG(("Old anchor point (%d,%d)", anchorPoint.x, anchorPoint.y)); TRACE_DEBUG(("New anchor point (%d,%d)", pdrawingEditPDU->anchorPointEdit.xCoordinate, pdrawingEditPDU->anchorPointEdit.yCoordinate)); //
// Get the delta from previous anchor point
//
deltaX = pdrawingEditPDU->anchorPointEdit.xCoordinate - anchorPoint.x; deltaY = pdrawingEditPDU->anchorPointEdit.yCoordinate - anchorPoint.y; TRACE_DEBUG(("Delta (%d,%d)", deltaX , deltaY));
//
// Was edited remotely
//
ClearEditionFlags(); } //
// Get Rotation
//
// if(pdrawingEditPDU->bit_mask & rotationEdit_present)
// {
// m_T126Drawing.m_rotation.m_bIsPresent = TRUE;
// m_T126Drawing.m_rotation.m_rotation.rotationAngle = pdrawingEditPDU->rotation.rotationAngle;
// m_T126Drawing.m_rotation.m_rotation.rotationAxis.xCoordinate = pdrawingEditPDU->rotation.rotationAxis.xCoordinate;
// m_T126Drawing.m_rotation.m_rotation.rotationAxis.yCoordinate = pdrawingEditPDU->rotation.rotationAxis.yCoordinate;
// }
// else
// {
// m_T126Drawing.m_rotation.m_bIsPresent = FALSE;
// }
//
// Get the list of points
//
if(pdrawingEditPDU->bit_mask & pointListEdits_present) { UINT i, initialIndex, xInitial,yInitial,numberOfPoints; PointListEdits_Seq pointList; POINT initialPoint;
TRACE_DEBUG(("Number of point edit lists %d", pdrawingEditPDU->pointListEdits.count));
for (i = 0; i<pdrawingEditPDU->pointListEdits.count; i++) { pointList = pdrawingEditPDU->pointListEdits.value[i]; initialIndex = pointList.initialIndex; TRACE_DEBUG(("Points cached = %d", m_points->GetSize())); TRACE_DEBUG(("initialIndex = %d", initialIndex)); initialPoint.x = pointList.initialPointEdit.xCoordinate; initialPoint.y = pointList.initialPointEdit.yCoordinate;
POINT * pPoint = m_points->GetBuffer(); TRACE_DEBUG(("initialPoint=(%d, %d), previousPoint=(%d, %d), anchorPoint=(%d, %d)", initialPoint.x, initialPoint.y, pPoint[initialIndex-1].x, pPoint[initialIndex-1].y, anchorPoint.x , anchorPoint.y )); if(initialIndex > 1) { for(UINT k = 0; k< initialIndex; k++) { deltaX += pPoint[k].x; deltaY += pPoint[k].y; } initialPoint.x -= deltaX; initialPoint.y -= deltaY; } m_points->SetSize(initialIndex); AddPoint(initialPoint);
if(GetDrawingType() == rectangle_chosen || GetDrawingType() == ellipse_chosen) { GetRect(&rect); rect.right = initialPoint.x + anchorPoint.x; rect.bottom = initialPoint.y + anchorPoint.y; SetRect(&rect); ::InflateRect(&rect, GetPenThickness()/2, GetPenThickness()/2); SetBoundsRect(&rect); }
if(pointList.bit_mask & subsequentPointEdits_present) { GetSubsequentPoints(pointList.subsequentPointEdits.choice, &anchorPoint, &pointList.subsequentPointEdits);
} ChangedPointList(); } }
//
// Just changed the anchor point, the other points have to change as well
//
if(pdrawingEditPDU->bit_mask & DrawingEditPDU_anchorPointEdit_present) { //
// Set new anchor point
//
anchorPoint.x = pdrawingEditPDU->anchorPointEdit.xCoordinate; anchorPoint.y = pdrawingEditPDU->anchorPointEdit.yCoordinate; SetAnchorPoint(anchorPoint.x, anchorPoint.y);
GetRect(&rect); ::OffsetRect(&rect, deltaX, deltaY); SetRect(&rect); GetBoundsRect(&rect); ::OffsetRect(&rect, deltaX, deltaY); SetBoundsRect(&rect);
}
if(pdrawingEditPDU->bit_mask & DrawingEditPDU_nonStandardParameters_present) { ; // Do the non Standard Edit PDU NYI
} if(HasAnchorPointChanged() || HasPointListChanged() || HasFillColorChanged() || HasPenColorChanged()|| HasPenThicknessChanged()|| HasLineStyleChanged()) { g_pDraw->EraseInitialDrawFinal(0 - deltaX,0 - deltaY, FALSE, (T126Obj*)this); ::InvalidateRect(g_pDraw->m_hwnd, NULL, TRUE);
} else if(HasZOrderChanged()) { if(GetZOrder() == front) { g_pDraw->BringToTopSelection(FALSE, this); } else { g_pDraw->SendToBackSelection(FALSE, this); } } //
// If it just select/unselected it
//
else if(HasViewStateChanged()) { ; // do nothing
} //
// If we have a valid pen.
//
else if(GetPenThickness()) { Draw(); }
//
// Reset all the attributes
//
ResetAttrib(); }
void DrawObj::GetDrawingAttrib(PVOID pAttribPDU) { PDrawingEditPDU_attributeEdits attributes; attributes = (PDrawingEditPDU_attributeEdits)pAttribPDU; COLORREF rgb; while(attributes) { switch(attributes->value.choice) { case(penColor_chosen): { switch(attributes->value.u.penColor.choice) { // case(workspacePaletteIndex_chosen):
// {
// ASN1uint16_t workspacePaletteIndex = ((attributes->value.u.penColor).u).workspacePaletteIndex;
// break;
// }
case(rgbTrueColor_chosen): { rgb = RGB(attributes->value.u.penColor.u.rgbTrueColor.r, attributes->value.u.penColor.u.rgbTrueColor.g, attributes->value.u.penColor.u.rgbTrueColor.b); SetPenColor(rgb, TRUE); TRACE_DEBUG(("Attribute penColor (r,g,b)=(%d, %d,%d)", attributes->value.u.penColor.u.rgbTrueColor.r, attributes->value.u.penColor.u.rgbTrueColor.g, attributes->value.u.penColor.u.rgbTrueColor.b)); break; } case(transparent_chosen): { SetPenColor(0,FALSE); break; } default: ERROR_OUT(("Invalid penColor choice")); break; } break; }
case(fillColor_chosen): { TRACE_DEBUG(("Attribute fillColor")); switch(attributes->value.u.fillColor.choice) { // case(workspacePaletteIndex_chosen):
// {
// ASN1uint16_t workspacePaletteIndex = ((attributes->value.u.fillColor).u).workspacePaletteIndex;
// break;
// }
case(rgbTrueColor_chosen): { rgb = RGB(attributes->value.u.fillColor.u.rgbTrueColor.r, attributes->value.u.fillColor.u.rgbTrueColor.g, attributes->value.u.fillColor.u.rgbTrueColor.b); SetFillColor(rgb, TRUE); TRACE_DEBUG(("Attribute fillColor (r,g,b)=(%d, %d,%d)", attributes->value.u.fillColor.u.rgbTrueColor.r, attributes->value.u.fillColor.u.rgbTrueColor.g, attributes->value.u.fillColor.u.rgbTrueColor.b)); break; } case(transparent_chosen): { SetFillColor(0,FALSE); break; } default: ERROR_OUT(("Invalid fillColor choice")); break; } break; }
case(penThickness_chosen): { SetPenThickness(attributes->value.u.penThickness); TRACE_DEBUG(("Attribute penThickness %d", attributes->value.u.penThickness)); break; }
case(penNib_chosen): { if (attributes->value.u.penNib.choice != nonStandardNib_chosen) { SetPenNib(attributes->value.u.penNib.choice); TRACE_DEBUG(("Attribute penNib %d",attributes->value.u.penNib.choice)); } else { // Do the non Standard penNib NYI
; } break; }
case(lineStyle_chosen): { if((attributes->value.u.lineStyle).choice != nonStandardStyle_chosen) { SetLineStyle(attributes->value.u.lineStyle.choice - 1); TRACE_DEBUG(("Attribute lineStyle %d", attributes->value.u.lineStyle.choice)); } else { // Do the non Standard lineStyle NYI
; } break; } case(highlight_chosen): { SetHighlight(attributes->value.u.highlight); TRACE_DEBUG(("Attribute highlight %d", attributes->value.u.highlight)); break; }
case(DrawingAttribute_viewState_chosen): { if((attributes->value.u.viewState).choice != nonStandardViewState_chosen) { SetViewState(attributes->value.u.viewState.choice); //
// If the other node is selecting the drawing or unselecting
//
if(attributes->value.u.viewState.choice == selected_chosen) { SelectedRemotely(); } else if(attributes->value.u.viewState.choice == unselected_chosen) { ClearSelectionFlags(); }
TRACE_DEBUG(("Attribute viewState %d", attributes->value.u.viewState.choice)); } else { // Do the non Standard lineStyle NYI
; } break; }
case(DrawingAttribute_zOrder_chosen): { SetZOrder(attributes->value.u.zOrder); TRACE_DEBUG(("Attribute zOrder %d", attributes->value.u.zOrder)); break;
} case(DrawingAttribute_nonStandardAttribute_chosen): { break; // NYI
}
default: ERROR_OUT(("Invalid attributes choice")); break; }
attributes = attributes->next; } }
UINT DrawObj::GetSubsequentPoints(UINT choice, POINT * initialPoint, PointList * pointList) { UINT numberOfPoints = 0; INT deltaX, deltaY;
POINT point; if(choice == pointsDiff16_chosen) { PPointList_pointsDiff16 drawingPoint = pointList->u.pointsDiff16; deltaX = (SHORT)initialPoint->x; deltaY = (SHORT)initialPoint->y; TRACE_DEBUG(("initialpoint (%d,%d)", deltaX, deltaY));
while(drawingPoint) { numberOfPoints++; point.x = drawingPoint->value.xCoordinate; point.y = drawingPoint->value.yCoordinate; m_points->Add(point); deltaX += point.x; deltaY += point.y; drawingPoint = drawingPoint->next; } } else { TRACE_DEBUG(("GetSubsequentPoints got points != pointsDiff16_chosen")); }
TRACE_DEBUG(("Got %d points", numberOfPoints));
return numberOfPoints; }
void DrawObj::CreateDrawingCreatePDU(DrawingCreatePDU *pCreatePDU) { int nPoints = 1; pCreatePDU->bit_mask = 0;
//
// Pass the drawing Handle
//
pCreatePDU->bit_mask |=drawingHandle_present; pCreatePDU->drawingHandle = GetThisObjectHandle();
//
// Pass the destination adress
//
pCreatePDU->destinationAddress.choice = DrawingDestinationAddress_softCopyAnnotationPlane_chosen; pCreatePDU->destinationAddress.u.softCopyAnnotationPlane.workspaceHandle = GetWorkspaceHandle(); pCreatePDU->destinationAddress.u.softCopyAnnotationPlane.plane = (DataPlaneID)GetPlaneID();
//
// Pass the drawing type
//
pCreatePDU->drawingType.choice = (ASN1choice_t)GetDrawingType();
//
// Pass the attributes
//
SetDrawingAttrib(&pCreatePDU->attributes); if(pCreatePDU->attributes != NULL) { pCreatePDU->bit_mask |=DrawingCreatePDU_attributes_present; }
//
// Pass the anchor point
//
POINT point; GetAnchorPoint(&point); pCreatePDU->anchorPoint.xCoordinate = point.x; pCreatePDU->anchorPoint.yCoordinate = point.y;
RECT rect; GetRect(&rect);
pCreatePDU->pointList.choice = pointsDiff16_chosen; DBG_SAVE_FILE_LINE pCreatePDU->pointList.u.pointsDiff16 = (PPointList_pointsDiff16)new BYTE[sizeof(PointList_pointsDiff16)]; PPointList_pointsDiff16 drawingPoint = pCreatePDU->pointList.u.pointsDiff16; PPointList_pointsDiff16 drawingPointLast = NULL; drawingPoint->next = NULL;
switch(GetDrawingType()) {
case point_chosen: drawingPoint->value.xCoordinate = 0; drawingPoint->value.yCoordinate = 0; drawingPoint->next = NULL; break;
case openPolyLine_chosen: case closedPolyLine_chosen: case rectangle_chosen: case ellipse_chosen: { nPoints = m_points->GetSize(); UINT maxPoints = 1; POINT * pPoint = m_points->GetBuffer(); while(nPoints && maxPoints < (MAX_POINT_LIST_VALUES + 1)) { drawingPoint->value.xCoordinate = (SHORT)pPoint->x; drawingPoint->value.yCoordinate = (SHORT)pPoint->y; drawingPointLast = drawingPoint; DBG_SAVE_FILE_LINE drawingPoint->next = (PPointList_pointsDiff16)new BYTE[sizeof(PointList_pointsDiff16)]; drawingPoint = drawingPoint->next; nPoints--; pPoint++; maxPoints++; } if(drawingPointLast) { delete drawingPointLast->next; drawingPointLast->next = NULL; } } break; } } void DrawObj::CreateDrawingEditPDU(DrawingEditPDU *pEditPDU) { pEditPDU->bit_mask = (ASN1uint16_t) GetPresentAttribs();
//
// Pass the anchor point
//
POINT point; GetAnchorPoint(&point);
if(HasAnchorPointChanged()) { pEditPDU->anchorPointEdit.xCoordinate = point.x; pEditPDU->anchorPointEdit.yCoordinate = point.y; }
pEditPDU->pointListEdits.value[0].subsequentPointEdits.u.pointsDiff16 = NULL;
//
// Pass point list changes
//
if(HasPointListChanged()) {
UINT nPoints = m_points->GetSize(); POINT * pPoint = m_points->GetBuffer();
pPoint = &pPoint[1];
//
// Just send the last 255 points
//
if(nPoints > 256) { pEditPDU->pointListEdits.value[0].initialIndex = nPoints - 256; nPoints = 256; } else { pEditPDU->pointListEdits.value[0].initialIndex = 0; }
//
// Calculate the initial point
//
point.x = 0; point.y = 0; for(UINT i = 0; i < pEditPDU->pointListEdits.value[0].initialIndex; i++) { point.x += pPoint[i].x; point.y += pPoint[i].y; }
pEditPDU->pointListEdits.count = 1; pEditPDU->pointListEdits.value[0].bit_mask = subsequentPointEdits_present; pEditPDU->pointListEdits.value[0].subsequentPointEdits.choice = pointsDiff16_chosen; pEditPDU->pointListEdits.value[0].initialPointEdit.xCoordinate = (SHORT)point.x; pEditPDU->pointListEdits.value[0].initialPointEdit.yCoordinate = (SHORT)point.y;
TRACE_DEBUG(("Sending List of points starting at Index = %d point(%d,%d)", pEditPDU->pointListEdits.value[0].initialIndex, point.x, point.y));
pPoint = &pPoint[pEditPDU->pointListEdits.value[0].initialIndex];
DBG_SAVE_FILE_LINE pEditPDU->pointListEdits.value[0].subsequentPointEdits.u.pointsDiff16 = (PPointList_pointsDiff16)new BYTE[sizeof(PointList_pointsDiff16)]; PPointList_pointsDiff16 drawingPointLast = NULL; PPointList_pointsDiff16 drawingPoint = pEditPDU->pointListEdits.value[0].subsequentPointEdits.u.pointsDiff16; pEditPDU->pointListEdits.value[0].subsequentPointEdits.u.pointsDiff16->next = NULL; pEditPDU->pointListEdits.value[0].subsequentPointEdits.u.pointsDiff16->value.xCoordinate = 0; pEditPDU->pointListEdits.value[0].subsequentPointEdits.u.pointsDiff16->value.yCoordinate = 0;
nPoints--; while(nPoints) { drawingPoint->value.xCoordinate = (SHORT)pPoint->x; drawingPoint->value.yCoordinate = (SHORT)pPoint->y; drawingPointLast = drawingPoint; DBG_SAVE_FILE_LINE drawingPoint->next = (PPointList_pointsDiff16)new BYTE[sizeof(PointList_pointsDiff16)]; drawingPoint = drawingPoint->next; nPoints--; pPoint++; } if(drawingPointLast) { delete drawingPointLast->next; drawingPointLast->next = NULL; } }
//
// JOSEF Pass rotation if we ever do it (FEATURE)
//
//
// Pass all the changed attributes, if any.
//
if(pEditPDU->bit_mask & DrawingEditPDU_attributeEdits_present) { SetDrawingAttrib((PDrawingCreatePDU_attributes *)&pEditPDU->attributeEdits); }
pEditPDU->drawingHandle = GetThisObjectHandle(); } void DrawObj::CreateDrawingDeletePDU(DrawingDeletePDU *pDeletePDU) { pDeletePDU->bit_mask = 0; pDeletePDU->drawingHandle = GetThisObjectHandle(); }
void DrawObj::AllocateAttrib(PDrawingCreatePDU_attributes *pAttributes) { DBG_SAVE_FILE_LINE PDrawingCreatePDU_attributes pAttrib = (PDrawingCreatePDU_attributes)new BYTE[sizeof(DrawingCreatePDU_attributes)]; if(*pAttributes == NULL) { *pAttributes = pAttrib; pAttrib->next = NULL; } else { ((PDrawingCreatePDU_attributes)pAttrib)->next = *pAttributes; *pAttributes = pAttrib; } }
void DrawObj::SetDrawingAttrib(PDrawingCreatePDU_attributes *pattributes) {
PDrawingCreatePDU_attributes attributes = NULL; RGBTRIPLE color;
//
// Do the pen Color
//
if(HasPenColorChanged()) { if(GetPenColor(&color)) { AllocateAttrib(&attributes); attributes->value.choice = penColor_chosen; attributes->value.u.penColor.choice = rgbTrueColor_chosen; attributes->value.u.penColor.u.rgbTrueColor.r = color.rgbtRed; attributes->value.u.penColor.u.rgbTrueColor.g = color.rgbtGreen; attributes->value.u.penColor.u.rgbTrueColor.b = color.rgbtBlue; } }
//
// Do the fillColor
//
if(HasFillColorChanged()) { if(GetFillColor(&color)) { AllocateAttrib(&attributes); attributes->value.choice = fillColor_chosen; attributes->value.u.fillColor.choice = rgbTrueColor_chosen; attributes->value.u.fillColor.u.rgbTrueColor.r = color.rgbtRed; attributes->value.u.fillColor.u.rgbTrueColor.g = color.rgbtGreen; attributes->value.u.fillColor.u.rgbTrueColor.b = color.rgbtBlue; } } //
// Do the penThickness
//
if(HasPenThicknessChanged()) { AllocateAttrib(&attributes); attributes->value.choice = penThickness_chosen; attributes->value.u.penThickness = (PenThickness)GetPenThickness(); }
//
// Do the penNib
//
if(HasPenNibChanged()) { AllocateAttrib(&attributes); attributes->value.choice = penNib_chosen; attributes->value.u.penNib.choice = (ASN1choice_t)GetPenNib(); }
//
// Do the lineStyle
//
if(HasLineStyleChanged()) { AllocateAttrib(&attributes); attributes->value.choice = lineStyle_chosen; attributes->value.u.lineStyle.choice = GetLineStyle()+1; } //
// Do the Highlight
//
if(HasHighlightChanged()) { AllocateAttrib(&attributes); attributes->value.choice = highlight_chosen; attributes->value.u.highlight = (ASN1bool_t)GetHighlight(); } //
// Do the viewState
//
if(HasViewStateChanged()) { AllocateAttrib(&attributes); attributes->value.choice = DrawingAttribute_viewState_chosen; attributes->value.u.viewState.choice = (ASN1choice_t)GetViewState(); } //
// Do the zOrder
//
if(HasZOrderChanged()) { AllocateAttrib(&attributes); attributes->value.choice = DrawingAttribute_zOrder_chosen; attributes->value.u.zOrder = GetZOrder(); }
*pattributes = attributes;
}
//
// CircleHit()
//
// Checks for overlap between circle at PcxPcy with uRadius and
// lpHitRect. If overlap TRUE is returned, otherwise FALSE.
//
BOOL CircleHit( LONG Pcx, LONG Pcy, UINT uRadius, LPCRECT lpHitRect, BOOL bCheckPt ) { RECT hr = *lpHitRect; RECT ellipse; ellipse.left = Pcx - uRadius; ellipse.right= Pcx + uRadius; ellipse.bottom = Pcy + uRadius; ellipse.top = Pcy - uRadius;
// check the easy thing first (don't use PtInRect)
if( bCheckPt &&(lpHitRect->left >= ellipse.left)&&(ellipse.right >= lpHitRect->right)&& (lpHitRect->top >= ellipse.top)&&(ellipse.bottom >= lpHitRect->bottom)) { return( TRUE ); }
//
// The circle is just a boring ellipse
//
return EllipseHit(&ellipse, bCheckPt, uRadius, lpHitRect ); }
//
// EllipseHit()
//
// Checks for overlap between ellipse defined by lpEllipseRect and
// lpHitRect. If overlap TRUE is returned, otherwise FALSE.
//
BOOL EllipseHit(LPCRECT lpEllipseRect, BOOL bBorderHit, UINT uPenWidth, LPCRECT lpHitRect ) { RECT hr = *lpHitRect; RECT er = *lpEllipseRect;
// Some code below assumes l<r and t<b
NormalizeRect(&er); lpEllipseRect = &er;
// Check easy thing first. If lpEllipseRect is inside lpHitRect
// then we have a hit (no duh...)
if( (hr.left <= lpEllipseRect->left)&&(hr.right >= lpEllipseRect->right)&& (hr.top <= lpEllipseRect->top)&&(hr.bottom >= lpEllipseRect->bottom) ) return( TRUE );
// Check easy thing first. If lpEllipseRect is disjoint from lpHitRect
// then we have a miss (no duh...)
if( (hr.left > lpEllipseRect->right)||(hr.right < lpEllipseRect->left)|| (hr.top > lpEllipseRect->bottom)||(hr.bottom < lpEllipseRect->top) ) return( FALSE );
// If this is an ellipse....
//
// * * ^
// * | b | Y
// * | a +-------> X
// *-------+--------
// |
//
//
// Look for the ellipse hit. (x/a)^2 + (y/b)^2 = 1
// If it is > 1 than the point is outside the ellipse
// If it is < 1 it is inside
//
LONG a,b,aOuter, bOuter, x, y, xCenter, yCenter; BOOL bInsideOuter = FALSE; BOOL bOutsideInner = FALSE;
//
// Calculate a and b
//
a = (lpEllipseRect->right - lpEllipseRect->left)/2; b = (lpEllipseRect->bottom - lpEllipseRect->top)/2;
//
// Get the center of the ellipse
//
xCenter = lpEllipseRect->left + a; yCenter = lpEllipseRect->top + b;
//
// a and b generates a inner ellipse
// aOuter and bOuter generates a outer ellipse
//
aOuter = a + uPenWidth/2; bOuter = b + uPenWidth/2; a = a - uPenWidth/2; b = b - uPenWidth/2;
//
// Make our coordinates relative to the center of the ellipse
//
y = abs(hr.bottom - yCenter); x = abs(hr.right - xCenter);
//
// Be carefull not to divide by 0
//
if((a && b && aOuter && bOuter) == 0) { return FALSE; }
//
// We are using LONG instead of double and we need to have some precision
// that is why we multiply the equation of the ellipse
// ((x/a)^2 + (y/b)^2 = 1) by DECIMAL_PRECISION
// Note that the multiplication has to be done before the division, if we didn't do that
// we will always get 0 or 1 for x/a
//
if(x*x*DECIMAL_PRECISION/(aOuter*aOuter) + y*y*DECIMAL_PRECISION/(bOuter*bOuter) <= DECIMAL_PRECISION) { bInsideOuter = TRUE; }
if(x*x*DECIMAL_PRECISION/(a*a)+ y*y*DECIMAL_PRECISION/(b*b) >= DECIMAL_PRECISION) { bOutsideInner = TRUE; } //
// If we are checking for border hit,
// we need to be inside the outer ellipse and inside the inner
//
if( bBorderHit ) { return( bInsideOuter & bOutsideInner ); } // just need to be inside the outer ellipse
else { return( bInsideOuter ); }
}
//
// LineHit()
//
// Checks for overlap (a "hit") between lpHitRect and the line
// P1P2 accounting for line width. If bCheckP1End or bCheckP2End is
// TRUE then a circle of radius 0.5 * uPenWidth is also checked for
// a hit to account for the rounded ends of wide lines.
//
// If a hit is found TRUE is returned, otherwise FALSE.
//
BOOL LineHit( LONG P1x, LONG P1y, LONG P2x, LONG P2y, UINT uPenWidth, BOOL bCheckP1End, BOOL bCheckP2End, LPCRECT lpHitRect ) {
LONG uHalfPenWidth = uPenWidth/2;
//
// It is really hard to hit if the width is only 2
//
if(uHalfPenWidth == 1) { uHalfPenWidth = 2; }
LONG a,b,x,y;
x = lpHitRect->left + (lpHitRect->right - lpHitRect->left)/2; y = lpHitRect->bottom + (lpHitRect->top - lpHitRect->bottom)/2;
//
// This code assume the rectangle is normalized
//
RECT rect; rect.top = P1y; rect.left = P1x; rect.bottom = P2y; rect.right = P2x;
NormalizeRect(&rect);
if( (P1x == P2x)&&(P1y == P2y) ) { // just check one end point's circle
return( CircleHit( P1x, P1y, uHalfPenWidth, lpHitRect, TRUE ) ); }
// check rounded end at P1
if( bCheckP1End && CircleHit( P1x, P1y, uHalfPenWidth, lpHitRect, FALSE ) ) return( TRUE );
// check rounded end at P2
if( bCheckP2End && CircleHit( P2x, P2y, uHalfPenWidth, lpHitRect, FALSE ) ) return( TRUE ); //
// The function of a line is Y = a.X + b
//
// a = (Y1-Y2)/(X1 -X2)
// if we found a we get b = y1 -a.X1
//
if(P1x == P2x) { a=0; b = DECIMAL_PRECISION*P1x;
} else { a = (P1y - P2y)*DECIMAL_PRECISION/(P1x - P2x); b = DECIMAL_PRECISION*P1y - a*P1x; }
//
// Paralel to Y
//
if(P1x == P2x && ((x >= P1x - uHalfPenWidth) && x <= P1x + uHalfPenWidth)) { return (P1y <= y && P2y >= y); }
//
// Paralel to X
//
if(P1y == P2y && ((y >= P1y - uHalfPenWidth) && y <= P1y + uHalfPenWidth)) { return (P1x <= x && P2x >= x); }
//
// General line
//
return(( y*DECIMAL_PRECISION <= a*x + b + DECIMAL_PRECISION*uHalfPenWidth) && ( y*DECIMAL_PRECISION >= a*x + b - DECIMAL_PRECISION*uHalfPenWidth)&& ((rect.top <= y && rect.bottom >= y) && (rect.left <= x && rect.right >= x))); }
//
// Checks object for an actual overlap with pRectHit. This
// function assumes that the boundingRect has already been
// compared with pRectHit.
//
BOOL DrawObj::PolyLineHit(LPCRECT pRectHit) { POINT *lpPoints; int iCount; int i; POINT ptLast; UINT uRadius; RECT rectHit;
iCount = m_points->GetSize(); lpPoints = (POINT *)m_points->GetBuffer();
if( iCount == 0 ) return( FALSE );
// addjust hit rect to lpPoints coord space.
rectHit = *pRectHit; POINT anchorPoint; GetAnchorPoint(&anchorPoint);
if( (iCount > 0)&&(iCount < 2) ) { // only one point, just hit check it
uRadius = GetPenThickness() >> 1; // m_uiPenWidth/2
return(CircleHit( anchorPoint.x + lpPoints->x, anchorPoint.y - lpPoints->y, uRadius, &rectHit, TRUE )); }
// look for a hit on each line segment body
ptLast = anchorPoint; for( i=1; i<iCount; i++ ) { RECT rect; rect.top = ptLast.y; rect.left = ptLast.x; rect.bottom = ptLast.y + lpPoints->y; rect.right = ptLast.x + lpPoints->x; NormalizeRect(&rect);
if( LineHit(rect.left, rect.top, rect.right, rect.bottom, GetPenThickness(), TRUE, TRUE, &rectHit)) { return( TRUE ); // got a hit
}
lpPoints++; ptLast.x +=lpPoints->x; ptLast.y +=lpPoints->y; }
// now, look for a hit on the line endpoints if m_uiPenWidth > 1
if( GetPenThickness() > 1 ) { uRadius = GetPenThickness() >> 1; // m_uiPenWidth/2
lpPoints = (POINT *)m_points->GetBuffer(); for( i=0; i<iCount; i++, lpPoints++ ) { if( CircleHit( anchorPoint.x + lpPoints->x, anchorPoint.y + lpPoints->y, uRadius, &rectHit, FALSE )) { return( TRUE ); // got a hit
} } }
return( FALSE ); // no hits
}
DrawObj::CheckReallyHit(LPCRECT pRectHit) { RECT rect; switch(GetDrawingType()) { case point_chosen: case openPolyLine_chosen: { UINT nPoints = m_points->GetSize(); if(nPoints > 2 ) { return PolyLineHit(pRectHit); } else { GetRect(&rect); return(LineHit(rect.left, rect.top, rect.right, rect.bottom, GetPenThickness(), TRUE, TRUE, pRectHit)); } } break;
case rectangle_chosen: { // Draw the rectangle
return(RectangleHit(!HasFillColor(), pRectHit)); } break; case ellipse_chosen: { GetRect(&rect); return( EllipseHit( &rect, !HasFillColor(), GetPenThickness(), pRectHit ));
} break; }
return FALSE; }
void DrawObj::UnDraw(void) { RECT rect; UINT penThickness; GetBoundsRect(&rect); penThickness = GetPenThickness(); ::InflateRect(&rect, penThickness, penThickness); g_pDraw->InvalidateSurfaceRect(&rect,TRUE);
BitmapObj* remotePointer = NULL; WBPOSITION pos = NULL; remotePointer = g_pCurrentWorkspace->RectHitRemotePointer(&rect, penThickness, NULL); while(remotePointer) { remotePointer->DeleteSavedBitmap(); remotePointer = g_pCurrentWorkspace->RectHitRemotePointer(&rect, penThickness, remotePointer->GetMyPosition()); } }
void DrawObj::Draw(HDC hDC, BOOL bForcedDraw, BOOL bPrinting) {
if(!bPrinting) { //
// Don't draw anything if we don't belong in this workspace
//
if(!(GraphicTool() == TOOLTYPE_SELECT || GraphicTool() == TOOLTYPE_ERASER) && GetWorkspaceHandle() != g_pCurrentWorkspace->GetThisObjectHandle()) { return; } }
HPEN hPen = NULL; HPEN hOldPen = NULL; HBRUSH hBrush = NULL; HBRUSH hOldBrush = NULL; BOOL bHasPenColor; BOOL bHasFillColor; BitmapObj* remotePointer = NULL; COLORREF color; COLORREF fillColor; RECT boundsRect; RECT rect; UINT penThickness = GetPenThickness();
if(hDC == NULL) { hDC = g_pDraw->m_hDCCached; }
MLZ_EntryOut(ZONE_FUNCTION, "DrawObj::Draw");
// Select the required pen and fill color
bHasPenColor = GetPenColor(&color); bHasFillColor = GetFillColor(&fillColor);
if(bHasFillColor) { hBrush = ::CreateSolidBrush(SET_PALETTERGB(fillColor)); hOldBrush = SelectBrush(hDC, hBrush); } else { hOldBrush = SelectBrush(hDC, ::GetStockObject(NULL_BRUSH)); }
//
// Get rect
//
GetBoundsRect(&boundsRect); GetRect(&rect);
hPen = ::CreatePen(GetLineStyle(), penThickness, SET_PALETTERGB(color)); hOldPen = SelectPen(hDC, hPen);
if (hOldPen != NULL) {
// Select the raster operation
int iOldROP = ::SetROP2(hDC, GetROP());
switch(GetDrawingType()) { case point_chosen: case openPolyLine_chosen: { UINT nPoints = m_points->GetSize(); //
// This is a redraw of a pen or highlight
// We have to draw all the segments
//
if( (bForcedDraw || GetIsCompleted()) && nPoints > 1) { POINT anchorPoint; GetAnchorPoint(&anchorPoint);
AddPointToBounds(anchorPoint.x, anchorPoint.y);
//
// Go to the beggining
//
::MoveToEx(hDC, anchorPoint.x, anchorPoint.y, NULL);
//
// Get the list of points
//
POINT *point = m_points->GetBuffer(); while(nPoints) { anchorPoint.x += point->x; anchorPoint.y += point->y; ::LineTo(hDC, anchorPoint.x, anchorPoint.y); ::MoveToEx(hDC, anchorPoint.x, anchorPoint.y, NULL); point++; nPoints--;
RECT rect1; MAKE_HIT_RECT(rect1, anchorPoint); if(remotePointer) { remotePointer->Draw(); remotePointer = NULL; }
AddPointToBounds(anchorPoint.x, anchorPoint.y);
::InflateRect(&rect1, GetPenThickness()/2, GetPenThickness()/2); remotePointer = g_pCurrentWorkspace->RectHitRemotePointer(&rect1, GetPenThickness()/2, NULL);
} } else { // Draw the line
::MoveToEx(hDC, rect.left, rect.top, NULL); ::LineTo(hDC, rect.right, rect.bottom); } } break;
case rectangle_chosen: {
TRACE_DEBUG(("RECTANGLE %d, %d, %d , %d", rect.left, rect.top, rect.right, rect.bottom ));
// Draw the rectangle
::Rectangle(hDC, rect.left, rect.top, rect.right, rect.bottom); } break; case ellipse_chosen: { ::Ellipse(hDC, rect.left, rect.top, rect.right, rect.bottom); } break; case closedPolyLine_chosen: default: TRACE_DEBUG(("Unsupported DrawingType", GetDrawingType())); break; }
//
// De-select the brush
//
SelectBrush(hDC, hOldBrush);
// De-select the pen and ROP
::SetROP2(hDC, iOldROP); SelectPen(hDC, hOldPen); }
//
// Do NOT draw focus if clipboard or printing
//
if (WasSelectedLocally() && (hDC == g_pDraw->m_hDCCached)) { DrawRect(); }
if (hPen != NULL) { ::DeletePen(hPen); }
if (hBrush != NULL) { ::DeleteBrush(hBrush); }
if(remotePointer) { remotePointer->Draw(); }
//
// Now for rectangles ellipses and lines, check if we are on top of any remote pointer
//
remotePointer = NULL; WBPOSITION pos = NULL; ::InflateRect(&rect, GetPenThickness()/2, GetPenThickness()/2); remotePointer = g_pCurrentWorkspace->RectHitRemotePointer(&rect, GetPenThickness()/2, NULL); while(remotePointer) { remotePointer->DeleteSavedBitmap(); remotePointer->Draw(); remotePointer = g_pCurrentWorkspace->RectHitRemotePointer(&rect, GetPenThickness()/2, remotePointer->GetMyPosition()); } }
void DrawObj::SetPenColor(COLORREF rgb, BOOL isPresent) { ChangedPenColor(); m_bIsPenColorPresent = isPresent; if(!isPresent) { return; } m_penColor.rgbtRed = GetRValue(rgb); m_penColor.rgbtGreen = GetGValue(rgb); m_penColor.rgbtBlue = GetBValue(rgb);
}
BOOL DrawObj::GetPenColor(COLORREF * rgb) { if(m_bIsPenColorPresent) { *rgb = RGB(m_penColor.rgbtRed, m_penColor.rgbtGreen, m_penColor.rgbtBlue); } return m_bIsPenColorPresent; }
BOOL DrawObj::GetPenColor(RGBTRIPLE* rgb) { if(m_bIsPenColorPresent) { *rgb = m_penColor; } return m_bIsPenColorPresent; }
void DrawObj::SetFillColor(COLORREF rgb, BOOL isPresent) { ChangedFillColor(); m_bIsFillColorPresent = isPresent; if(!isPresent) { return; } m_fillColor.rgbtRed = GetRValue(rgb); m_fillColor.rgbtGreen = GetGValue(rgb); m_fillColor.rgbtBlue = GetBValue(rgb);
}
BOOL DrawObj::GetFillColor(COLORREF* rgb) { if(m_bIsFillColorPresent && rgb !=NULL) { *rgb = RGB(m_fillColor.rgbtRed, m_fillColor.rgbtGreen, m_fillColor.rgbtBlue); } return m_bIsFillColorPresent; }
BOOL DrawObj::GetFillColor(RGBTRIPLE* rgb) { if(m_bIsFillColorPresent && rgb!= NULL) { *rgb = m_fillColor; } return m_bIsFillColorPresent; }
BOOL DrawObj::AddPoint(POINT point) { BOOL bSuccess = TRUE;
MLZ_EntryOut(ZONE_FUNCTION, "DrawObj::::AddPoint");
int nPoints = m_points->GetSize();
// if we've reached the maximum number of points then quit with failure
if (nPoints >= MAX_FREEHAND_POINTS) { bSuccess = FALSE; TRACE_DEBUG(("Maximum number of points for freehand object reached.")); return(bSuccess); }
m_points->Add(point); nPoints++;
ChangedPointList();
//
// If we hit the 256 limit fake a timer notification and resend the polyline
//
if((nPoints & 0xff) == 0) { g_pDraw->OnTimer(0); } return(bSuccess); }
void DrawObj::AddPointToBounds(int x, int y) { // Create a rectangle containing the point just added (expanded
// by the width of the pen being used).
RECT rect; RECT boundsRect; rect.left = x - 1; rect.top = y - 1; rect.right = x + 1; rect.bottom = y + 1;
GetBoundsRect(&boundsRect); ::UnionRect(&boundsRect, &boundsRect, &rect); SetBoundsRect(&boundsRect); }
void GetDrawingDestinationAddress(DrawingDestinationAddress *destinationAddress, PUINT workspaceHandle, PUINT planeID) {
//
// Get the destination address
//
switch(destinationAddress->choice) {
case(DrawingDestinationAddress_softCopyAnnotationPlane_chosen): { *workspaceHandle = (destinationAddress->u.softCopyAnnotationPlane.workspaceHandle); *planeID = (destinationAddress->u.softCopyAnnotationPlane.plane); break; } // case(DrawingDestinationAddress_nonStandardDestination_chosen):
// {
// break;
// }
default: ERROR_OUT(("Invalid destinationAddress")); break; } }
void DrawObj::SetUIToolType(void) { UINT drawingType = GetDrawingType(); BOOL filled = HasFillColor();
UINT rop = R2_COPYPEN;
switch (drawingType) { case openPolyLine_chosen: { if(m_points->GetSize() > 1) { if(GetHighlight()) { m_ToolType = TOOLTYPE_HIGHLIGHT; rop = R2_MASKPEN;
} else { m_ToolType = TOOLTYPE_PEN; }
} else { m_ToolType = TOOLTYPE_LINE; } } break; case rectangle_chosen: { if(filled) { m_ToolType = TOOLTYPE_FILLEDBOX; } else { m_ToolType = TOOLTYPE_BOX; } } break;
case ellipse_chosen: { if(filled) { m_ToolType = TOOLTYPE_FILLEDELLIPSE; } else { m_ToolType = TOOLTYPE_ELLIPSE; } } break; }
SetROP(rop); }
//
// UI Edited the Drawing Object
//
void DrawObj::OnObjectEdit(void) { g_bContentsChanged = TRUE;
SIPDU *sipdu = NULL; DBG_SAVE_FILE_LINE sipdu = (SIPDU *) new BYTE[sizeof(SIPDU)]; if(sipdu) { sipdu->choice = drawingEditPDU_chosen;
CreateDrawingEditPDU(&sipdu->u.drawingEditPDU);
TRACE_DEBUG(("Sending Drawing Edit >> Drawing handle = %d", sipdu->u.drawingEditPDU.drawingHandle ));
T120Error rc = SendT126PDU(sipdu); if(rc == T120_NO_ERROR) { SIPDUCleanUp(sipdu); ResetAttrib(); } } else { TRACE_MSG(("Failed to create sipdu")); ::PostMessage(g_pMain->m_hwnd, WM_USER_DISPLAY_ERROR, WBFE_RC_WINDOWS, 0); } }
//
// UI Deleted the Drawing Object
//
void DrawObj::OnObjectDelete(void) { SIPDU *sipdu = NULL; DBG_SAVE_FILE_LINE sipdu = (SIPDU *) new BYTE[sizeof(SIPDU)]; if(sipdu) { sipdu->choice = drawingDeletePDU_chosen; CreateDrawingDeletePDU(&sipdu->u.drawingDeletePDU); T120Error rc = SendT126PDU(sipdu); if(rc == T120_NO_ERROR) { SIPDUCleanUp(sipdu); } } else { TRACE_MSG(("Failed to create sipdu")); ::PostMessage(g_pMain->m_hwnd, WM_USER_DISPLAY_ERROR, WBFE_RC_WINDOWS, 0); }
}
//
// Get the encoded buffer for Drawing Create PDU
//
void DrawObj::GetEncodedCreatePDU(ASN1_BUF *pBuf) { SIPDU *sipdu = NULL; DBG_SAVE_FILE_LINE sipdu = (SIPDU *) new BYTE[sizeof(SIPDU)]; if(sipdu) { sipdu->choice = drawingCreatePDU_chosen; CreateDrawingCreatePDU(&sipdu->u.drawingCreatePDU);
ASN1_BUF encodedPDU; g_pCoder->Encode(sipdu, pBuf);
SIPDUCleanUp(sipdu); } else { TRACE_MSG(("Failed to create penMenu")); ::PostMessage(g_pMain->m_hwnd, WM_USER_DISPLAY_ERROR, WBFE_RC_WINDOWS, 0);
} }
//
// UI Created a new Drawing Object
//
void DrawObj::SendNewObjectToT126Apps(void) {
SIPDU *sipdu = NULL; DBG_SAVE_FILE_LINE sipdu = (SIPDU *) new BYTE[sizeof(SIPDU)]; if(sipdu) { sipdu->choice = drawingCreatePDU_chosen; CreateDrawingCreatePDU(&sipdu->u.drawingCreatePDU);
TRACE_DEBUG(("Sending Drawing >> Drawing handle = %d", sipdu->u.drawingCreatePDU.drawingHandle )); T120Error rc = SendT126PDU(sipdu); if(rc == T120_NO_ERROR) { SIPDUCleanUp(sipdu); } } else { TRACE_MSG(("Failed to create sipdu")); ::PostMessage(g_pMain->m_hwnd, WM_USER_DISPLAY_ERROR, WBFE_RC_WINDOWS, 0); } }
|