/******************************************************************************************** > OpState OpBaseConvertPathSegment::BaseGetState(INT32 PathType) Author: Peter_Arnold (Xara Group Ltd) <*****@*****.**> Created: 16/8/95 Inputs: Type of the path that ends a segment Returns: The tick/grey state of OpBaseConvertPathSegment and derived classes Purpose: For finding the state of this op SeeAlso: OpState ********************************************************************************************/ OpState OpBaseConvertPathSegment::BaseGetState(INT32 PathType) { OpState OpSt; #ifndef STANDALONE SelRange* Selected = GetApplication()->FindSelection(); if ((Document::GetSelected() == NULL) || (Selected == NULL) ) { // There is no selected document or selrange is invalid OpSt.Greyed = TRUE; return OpSt; } Node* pNode = Selected->FindFirst(); BOOL FoundSegment = FALSE; BOOL AllConverted = TRUE; BOOL PrevSelected = FALSE; while ((pNode != NULL) && AllConverted) { if (pNode->IsNodePath() && ((NodePath*)pNode)->IsPathAllowable()) { Path* ThisPath = &(((NodePath*)pNode)->InkPath); PathFlags* Flags = ThisPath->GetFlagArray(); PathVerb* Verbs = ThisPath->GetVerbArray(); INT32 UsedSlots = ThisPath->GetNumCoords(); PrevSelected = FALSE; for (INT32 i=0; i<UsedSlots; i++) { if (Flags[i].IsEndPoint) { if (Flags[i].IsSelected) { if (PrevSelected && ((Verbs[i] & ~PT_CLOSEFIGURE) != PT_MOVETO) ) { FoundSegment = TRUE; if ((Verbs[i] & ~PT_CLOSEFIGURE) != PathType) AllConverted = FALSE; } PrevSelected = TRUE; } else { PrevSelected = FALSE; } } } } pNode = Selected->FindNext(pNode); } OpSt.Greyed = !FoundSegment; OpSt.Ticked = AllConverted && FoundSegment; #endif // #ifdef STANDALONE return OpSt; }
DocRect ArrowRec::FindBoundsAt(const DocCoord& ArrowCentre, const DocCoord& Direction, INT32 ParentLineWidth) { DocRect Bounds(0,0,0,0); // Find a matrix to transform the ArrowHead to this Position. Trans2DMatrix Trans; GetArrowMatrix(ArrowCentre, Direction, ParentLineWidth, &Trans); // Note: // We should really be able to ask Gavin to Calculate the Bounds, // and pass him this Transform Matrix, but he can't do this at the // moment, so we'll have to actually transform the path into // a tempory path, and then ask him to calc the bounds of that. // Make a tempory path to transform Path* TransPath = new Path(); if (TransPath == NULL) return Bounds; // Copy the path data from the ArrorHead into our tempory path. BOOL ok = TransPath->Initialise(ArrowShape->GetNumCoords()); if (ok) ok = TransPath->CopyPathDataFrom(ArrowShape); if (!ok) { // Tidy up if we failed delete TransPath; return Bounds; } // Go transform the Tempory path Trans.Transform(TransPath->GetCoordArray(), TransPath->GetNumCoords() ); BOOL GDrawResult = FALSE; // Find out what the paths bounding rect is, taking into account // any bezier curve thingies. GDrawContext *GD = GRenderRegion::GetStaticDrawContext(); if (GD != NULL) GDrawResult = GD->CalcStrokeBBox((POINT*)TransPath->GetCoordArray(), TransPath->GetVerbArray(), TransPath->GetNumCoords(), (RECT *)(&Bounds), TRUE, 0, CAPS_ROUND, JOIN_ROUND, NULL) == 0; // If Gavin failed, then use backup technique of getting coord array bounds if (!GDrawResult) Bounds = TransPath->GetBoundingRect(); // Delete the temporary transformed path delete TransPath; return Bounds; }
/******************************************************************************************** > BOOL BlendHelpers::BlendPaths(BlendNodeParam * pParam, Path * pPath) Author: David_McClarnon (Xara Group Ltd) <*****@*****.**> Created: 21/2/2000 Inputs: The blend node parameter Outputs: The blended path is stored in three arrays: the coords, the verbs, and the flags. The arrays are: pTempCoords pTempVerbs pTempFlags ArrayLength = the length of all three arrays This allows the caller to decide what to do with the blended path in a very flexible way. Returns: TRUE if successful, FALSE otherwise Purpose: Blends two BlendPath objects by the amount specified in BlendRatio SeeAlso: - ********************************************************************************************/ BOOL BlendHelpers::BlendPaths(BlendNodeParam * pParam, Path * pPath) { // Check entry params BlendPath * pBlendPathStart = pParam->GetStartBlendPath(); BlendPath * pBlendPathEnd = pParam->GetEndBlendPath(); ERROR2IF(!pBlendPathStart->GetBlendNode()->IsNodePath(), FALSE, "Start blend path's node isn't a node path"); ERROR2IF(!pBlendPathEnd->GetBlendNode()->IsNodePath(), FALSE, "End blend path's node isn't a node path"); BOOL ok = (pBlendPathStart != NULL && pBlendPathEnd != NULL); if (ok) ok = (pBlendPathStart->GetBlendNode() != NULL && pBlendPathEnd->GetBlendNode() != NULL); ERROR3IF(!ok,"One or more NULL entry params"); if (!ok) return FALSE; // Get the types of the two paths PathTypeEnum PathTypeStart = pBlendPathStart->GetPathType(); PathTypeEnum PathTypeEnd = pBlendPathEnd ->GetPathType(); // The blended path will be closed if either of the paths is a shape BOOL Closed = (PathTypeStart == PATHTYPE_SHAPE) || (PathTypeEnd == PATHTYPE_SHAPE); Path * pPathStart = NULL; // Find the paths associated with the start and end blend paths if (pBlendPathStart->GetBlendNode()->IsNodePath()) { pPathStart = &(((NodePath *)pBlendPathStart->GetBlendNode())->InkPath); } Path * pPathEnd = NULL; if (pBlendPathEnd->GetBlendNode()->IsNodePath()) { pPathEnd = &(((NodePath *)pBlendPathEnd->GetBlendNode())->InkPath); } // Calculate how large the arrays have to be to store the blended path definition INT32 DestPathSize = ((pPathStart->GetNumCoords()+pPathEnd->GetNumCoords())*3)+500; // Get some arrays used to hold the blended path data, and error if any are NULL DocCoord* pDestCoords = GetCoordArray(DestPathSize); PathVerb* pDestVerbs = GetVerbArray(DestPathSize); PathFlags* pDestFlags = GetFlagArray(DestPathSize); UINT32* pBuff = GetGBlendBuff(DestPathSize); if (pDestCoords == NULL || pDestVerbs == NULL || pDestFlags == NULL || pBuff == NULL) return FALSE; // This section copes with the case when blending a line with a shape. // In this case we need to get a temp path the is actually a shape version of the line. // The line is simply reversed back onto itself to form a shape that would look identical to the // line if rendered. This allows the line to appear to open up to the shape when blended. Path Shape; if (PathTypeStart != PathTypeEnd) { BOOL ok = FALSE; if (!Shape.Initialise()) return FALSE; // if going from a line to a shape, convert the start path to a shape if (PathTypeStart == PATHTYPE_LINE && PathTypeEnd == PATHTYPE_SHAPE) { ok = NodeBlender::ConvertLineToShape(pPathStart,&Shape); pPathStart = &Shape; } // if going from a shape to a line, convert the end path to a shape if (PathTypeStart == PATHTYPE_SHAPE && PathTypeEnd == PATHTYPE_LINE) { ok = NodeBlender::ConvertLineToShape(pPathEnd,&Shape); pPathEnd = &Shape; } if (!ok) return FALSE; } // The blend should do a one-to-one mapping when the OneToOne flag is set AND both paths // have the same number of elements BOOL OneToOne = FALSE; if (pParam->GetOneToOne()) OneToOne = (pBlendPathStart->GetNumElements() == pBlendPathEnd->GetNumElements()); // Now actually blend the two paths GBlend GBlendObj; // Define the blend GBlendObj.Define( (PPOINT)pPathStart->GetCoordArray(), // Specify the start path pPathStart->GetVerbArray(), pPathStart->GetNumCoords(), (PPOINT)pPathEnd ->GetCoordArray(), // Specify the end path pPathEnd ->GetVerbArray(), pPathEnd ->GetNumCoords(), OneToOne, // The one-to-one flag 1024, // Flatness pBuff, // Buffer for GBlend to use DestPathSize*sizeof(UINT32)); // The buffer size // Blend the paths m_ArrayLength = GBlendObj.Blend(pParam->GetBlendRatio(), // The blend ratio, 0.0 < BlendRatio < 1.0 (PPOINT)pDestCoords, // Array to store blended coords pDestVerbs, // Array to store blended verbs DestPathSize); // The num elements in the two arrays // If we're blending a line to another line, we need to make sure that the blended line // is going in a direction that corresponds to the source lines. This ensures attributes // that depend on this direction (e.g. start and end arrows) look correct. // // When creating blend paths of lines, we can detect if the blend path has been reversed, // in relation to the original path, by the original mapping value. // If it's 0 it has NOT been reversed, otherwise it's been reversed. // // If the blend ratio is <=0.5, the blended path is closest to the start blend path, // so we look at the start blend path's original mapping. // // If blend ration > 0.5, look at the end blend path's original mapping. // // The (BlendRation <= 0.5) cut-off point is the same as the cut-off point used in the blending // of attributes. if (pBlendPathStart->IsLine() && pBlendPathEnd->IsLine()) { BlendPath* pBlendPath; if (pParam->GetBlendRatio() <= 0.5) pBlendPath = pBlendPathStart; else pBlendPath = pBlendPathEnd; if (pBlendPath->GetOrigMapping() != 0) NodeBlender::ReversePath(pDestCoords,pDestVerbs,m_ArrayLength); } // We need to do some work on the blended path if (!NodeBlender::ProcessBlendedPath(pDestCoords,pDestVerbs,pDestFlags,m_ArrayLength,Closed)) return FALSE; Path RetnPath; RetnPath.Initialise(m_ArrayLength); BOOL Filled = pPathStart->IsFilled || pPathEnd->IsFilled; BOOL Stroked = pPathStart->IsStroked || pPathEnd->IsStroked; RetnPath.MergeTwoPaths(pDestCoords,pDestVerbs,pDestFlags,m_ArrayLength,Filled); pPath->ClearPath(); pPath->CloneFrom(RetnPath); pPath->IsFilled = Filled; pPath->IsStroked = Stroked; return TRUE; }