void XARGenerator::DetermineLinearGradientPoints(const Gradient* pGradient, const Transformation& trans, const RectD& boundings, DocCoord& p1, DocCoord& p2) { if (pGradient->units == Gradient::ObjectBoundingBox) { PointD pLower = boundings.LowerCoord(); PointD pHigher = boundings.HigherCoord(); p1 = DocCoord((INT32)pLower.x, m_docSize.y - (INT32)pLower.y); p2 = DocCoord((INT32)pHigher.x, m_docSize.y - (INT32)pHigher.y); #ifdef SVGDEBUG svgtrace(DBGTRACE_GRADIENTS, "using ObjectBoundingBox %d,%d %d,%d\n", p1.x, p1.y, p2.x, p2.y); #endif } else { // Gradient->units == Gradient::UserSpaceOnUse double fX1 = pGradient->x1; double fY1 = pGradient->y1; double fX2 = pGradient->x2; double fY2 = pGradient->y2; trans.ApplyToCoordinate(fX1, fY1, &fX1, &fY1); trans.ApplyToCoordinate(fX2, fY2, &fX2, &fY2); p1 = DocCoord((INT32)fX1, m_docSize.y - (INT32)fY1); p2 = DocCoord((INT32)fX2, m_docSize.y - (INT32)fY2); #if SVGDEBUG svgtrace(DBGTRACE_GRADIENTS, "using UserSpaceOnUse %d,%d %d,%d\n", p1.x, p1.y, p2.x, p2.y); #endif } }
void NodeEllipse::CreateShape(DocRect NewRect) { // Copy the rectangle into the parallelogram Parallel[0] = DocCoord(NewRect.lo.x, NewRect.hi.y); Parallel[1] = DocCoord(NewRect.hi.x, NewRect.hi.y); Parallel[2] = DocCoord(NewRect.hi.x, NewRect.lo.y); Parallel[3] = DocCoord(NewRect.lo.x, NewRect.lo.y); // Get an array to put the 12 different coords needed to specify an ellipse DocCoord NewCoords[12]; // Calculate the 3 coordinates along each side of the parallelogram CalcEllipseEdge(Parallel[0], Parallel[1], &NewCoords[11], &NewCoords[0], &NewCoords[1]); CalcEllipseEdge(Parallel[1], Parallel[2], &NewCoords[2], &NewCoords[3], &NewCoords[4]); CalcEllipseEdge(Parallel[2], Parallel[3], &NewCoords[5], &NewCoords[6], &NewCoords[7]); CalcEllipseEdge(Parallel[3], Parallel[0], &NewCoords[8], &NewCoords[9], &NewCoords[10]); // build a path InkPath.ClearPath(); InkPath.FindStartOfPath(); // Start at bottom left corner PathFlags NewFlags; NewFlags.IsRotate = TRUE; InkPath.InsertMoveTo(NewCoords[0], &NewFlags); InkPath.InsertCurveTo(NewCoords[1], NewCoords[2], NewCoords[3], &NewFlags); InkPath.InsertCurveTo(NewCoords[4], NewCoords[5], NewCoords[6], &NewFlags); InkPath.InsertCurveTo(NewCoords[7], NewCoords[8], NewCoords[9], &NewFlags); InkPath.InsertCurveTo(NewCoords[10], NewCoords[11], NewCoords[0], &NewFlags); // Close the path properly InkPath.CloseSubPath(); }
void NodeBrush::RenderObjectBlobs(RenderRegion* pRegion) { #if !defined(EXCLUDE_FROM_RALPH) // Find out about the groups bounding rect DocRect BoundingRect = GetBoundingRect(); // Inflate the bounds by the width of a blob DocRect TempRect; GetApplication()->GetBlobManager()->GetBlobRect(BoundingRect.lo,&TempRect); INT32 Delta = ((TempRect.hi.x - TempRect.lo.x)*3)/4; BoundingRect.Inflate(Delta); // Find out where to draw the blobs DocCoord Low = BoundingRect.LowCorner(); DocCoord High = BoundingRect.HighCorner(); // Set the colours of the blobs pRegion->SetFillColour(COLOUR_UNSELECTEDBLOB); pRegion->SetLineColour(COLOUR_NONE); // Draw all the blobs pRegion->DrawBlob(Low, BT_UNSELECTED); pRegion->DrawBlob(High, BT_UNSELECTED); pRegion->DrawBlob(DocCoord(Low.x, High.y), BT_UNSELECTED); pRegion->DrawBlob(DocCoord(High.x, Low.y), BT_UNSELECTED); // for some reason the NBP is never called, there is probably a // proper fix for this but I don't have time right now, so render // the nodeblend path here m_pNodeBrushPath->RenderObjectBlobs(pRegion); #endif }
// sets the height and width of the shape. if this function gets called, we assume that the shape has // no rotation or skew, so the MajorAxis = (0, Height), MinorAxis = (Width, 0) BOOL RegularShapeRecordHandler::SetHeightAndWidth(NodeRegularShape *pShape, const INT32 & Height, const INT32 & Width) { ERROR2IF(pShape==NULL, FALSE, "parameter pShape == NULL"); SetMajorAxis(pShape, DocCoord(0, Height/2)); SetMinorAxis(pShape, DocCoord(Width/2, 0)); return TRUE; }
bool XARGenerator::OutputHeader() { bool ok = true; // Create a CXaraFileRecord object for the document header record CXaraFileRecord Rec(TAG_FILEHEADER); ok = Rec.Init(); if (ok) ok = Rec.WriteBuffer((BYTE*)"CXN", 3); if (ok) ok = Rec.WriteUINT32(123); // File size if (ok) ok = Rec.WriteUINT32(0); // Native/Web link ID if (ok) ok = Rec.WriteUINT32(0); // Precompression flags if (ok) ok = Rec.WriteASCII(_T("SVGFilter")); // Producer if (ok) ok = Rec.WriteASCII(VERSION_TSTRING); // Producer version if (ok) ok = Rec.WriteASCII(_T("")); // Producer build if (ok) ok = m_pExporter->WriteRecord(&Rec); // If any part of the header writing fails then return our own specific error if (!ok) { // XXX Set an appropriate error here return false; } // XXX From this point on the error handling becomes a bit thin ok = m_pExporter->WriteZeroSizedRecord(TAG_SPREAD); /***/ ok = m_pExporter->WriteZeroSizedRecord(TAG_DOWN); if (m_docSize != DocCoord(0, 0)) { ok = Rec.Reinit(TAG_SPREADINFORMATION, TAG_SPREADINFORMATION_SIZE); ok = Rec.WriteUINT32(m_docSize.x); // width ok = Rec.WriteUINT32(m_docSize.y); // height ok = Rec.WriteUINT32(10000); // margin ok = Rec.WriteUINT32(0); // bleed ok = Rec.WriteBYTE(2); // flags (1:shadow) ok = m_pExporter->WriteRecord(&Rec); } ok = Rec.Reinit(TAG_VIEWPORT, TAG_VIEWPORT_SIZE); ok = Rec.WriteCoord(DocCoord(0, 0)); // bottom-left ok = Rec.WriteCoord(DocCoord(m_docSize.x, m_docSize.y));// top-right ok = m_pExporter->WriteRecord(&Rec); // Write a layer ok = m_pExporter->WriteZeroSizedRecord(TAG_LAYER); /***/ ok = m_pExporter->WriteZeroSizedRecord(TAG_DOWN); ok = Rec.Reinit(TAG_LAYERDETAILS, TAG_LAYERDETAILS_SIZE); ok = Rec.WriteBYTE(1|4|8); // flags (0:visible, 2:printable, 3:active) ok = Rec.WriteUnicode(_T("Layer 1")); ok = m_pExporter->WriteRecord(&Rec); return ok; }
bool XARGenerator::OutputPathEntity(const Style& style, const Transformation& trans, PathDataVector& pathVector) { bool ok = true; CXaraFileRecord Rec(0); if (style.IsFillColourDefined() || style.IsFillGradientDefined()) { if (style.IsStrokeColourDefined()) Rec.Reinit(TAG_PATH_FILLED_STROKED, TAG_PATH_SIZE); else Rec.Reinit(TAG_PATH_FILLED, TAG_PATH_SIZE); } else // if (style.IsStrokeColourDefined()) Rec.Reinit(TAG_PATH_STROKED, TAG_PATH_SIZE); Rec.WriteUINT32(pathVector.GetCount()); for (unsigned int i = 0; i < pathVector.GetCount(); ++i) Rec.WriteBYTE(pathVector[i].m_verb); for (unsigned int i = 0; i < pathVector.GetCount(); ++i) { PointD p = pathVector[i].m_coord; Rec.WriteCoord(DocCoord((INT32)p.x, m_docSize.y - (INT32)p.y)); } ok = m_pExporter->WriteRecord(&Rec); RectD boundings = GetMaximumBoundings(pathVector); /***/ ok = m_pExporter->WriteZeroSizedRecord(TAG_DOWN); OutputStyles(style, trans, boundings, STYLE_FILL_ALL|STYLE_STROKE_ALL|STYLE_OPACITY); /***/ ok = m_pExporter->WriteZeroSizedRecord(TAG_UP); return ok; }
bool XARGenerator::OutputPolygonEntity(const Style& style, const Transformation& trans, const PointDVector& coordVector) { bool ok = true; CXaraFileRecord Rec(0); if (style.IsFillColourDefined() || style.IsFillGradientDefined()) { if (style.IsStrokeColourDefined()) Rec.Reinit(TAG_PATH_FILLED_STROKED, TAG_PATH_SIZE); else Rec.Reinit(TAG_PATH_FILLED, TAG_PATH_SIZE); } else // if (style.IsStrokeColourDefined()) Rec.Reinit(TAG_PATH_STROKED, TAG_PATH_SIZE); Rec.WriteUINT32(coordVector.GetCount()); Rec.WriteBYTE(0x06); // moveto for (unsigned int i = 1; i < coordVector.GetCount() - 1; ++i) Rec.WriteBYTE(0x02); // lineto Rec.WriteBYTE(0x03); // lineto + closepath for (unsigned int i = 0; i < coordVector.GetCount(); ++i) { PointD p = coordVector[i]; Rec.WriteCoord(DocCoord((INT32)p.x, m_docSize.y - (INT32)p.y)); } ok = m_pExporter->WriteRecord(&Rec); RectD boundings = GetMaximumBoundings(coordVector); /***/ ok = m_pExporter->WriteZeroSizedRecord(TAG_DOWN); OutputStyles(style, trans, boundings, STYLE_FILL_ALL|STYLE_STROKE_ALL|STYLE_OPACITY); /***/ ok = m_pExporter->WriteZeroSizedRecord(TAG_UP); return ok; }
void Trans2DMatrix::InitDecomposedTransforms() { Scale = 0; // 0 indicates cached values invalid Aspect = 1; Rotation = 0; Skew = 0; Translation = DocCoord(0,0); }
BOOL RegularShapeRecordHandler::SetupShape(NodeRegularShape *pShape) { DocCoord Origin = DocCoord(0,0); pShape->SetCentrePoint(Origin); pShape->SetMinorAxes(Origin); pShape->SetMajorAxes(Origin); Matrix m = Matrix(); // Identity transform pShape->SetTransformMatrix(&m); return pShape->SetUpShape(); }
BOOL ProcessPathToTrapezoids::Process(const ProcessFlags &PFlags, TrapTravelType TravelType, JointType JoinStyle) { ERROR2IF(pTraps == NULL, FALSE, "Call Init to initialise the ProcessPathToTrapezoids object first!"); JoinType = JoinStyle; PointFollowsJoin = FALSE; LastPoint = DocCoord(0,0); BOOL ok = ProcessPath::Process(PFlags); if (ok) ok = pTraps->PostProcessLists(this, TravelType); return(ok); }
ArrowRec::ArrowRec() { ArrowShape = NULL; Centre = DocCoord(0,0); LineWidth = DEFAULT_ARROW_LINEWIDTH; ArrowWidth = 3; ArrowHeight = 3; StartArrow = FALSE; ScaleWithLineWidth = TRUE; ArrowID = 0; m_bExtendPath = TRUE; IsNull = TRUE; }
BOOL ProcessPathDistance::NewPointA(PathVerb Verb, DocCoord* pCoord, UINT32* pPressure) { ERROR2IF(pCoord==NULL,FALSE,"ProcessPathDistance::NewPoint() - pCoord==NULL"); ERROR2IF(Verb!=PT_LINETO && Verb!=PT_MOVETO,FALSE,"ProcessPathDistance::NewPoint() - unknown path verb"); if (!Found && !ProcFirstPoint && Verb==PT_LINETO) { double dx=pCoord->x-PrevCoord.x; double dy=pCoord->y-PrevCoord.y; double LineLength=sqrt(dx*dx+dy*dy); double NextDist=CurrentDist+LineLength; m_LastFoundDistance = CurrentDist; //TRACEUSER( "Diccon", _T("m_LastFound = %f\n"), m_LastFoundDistance); if (NextDist>=DesiredDist) { if (LineLength>0) { double FractOfLine = (DesiredDist-CurrentDist)/LineLength; double x = PrevCoord.x+dx*FractOfLine; double y = PrevCoord.y+dy*FractOfLine; CoordAtDist = DocCoord((MILLIPOINT)x,(MILLIPOINT)y); TangentAtDist = atan2(dy,dx); if (pPressure != NULL) PressureAtDist = (UINT32)((*pPressure * (1-FractOfLine)) + (m_PrevPressure * FractOfLine)); } else { CoordAtDist = PrevCoord; TangentAtDist = 0; if (pPressure != NULL) PressureAtDist = m_PrevPressure; } Found=TRUE; } CurrentDist=NextDist; } PrevCoord=*pCoord; m_PrevPressure = *pPressure; return TRUE; }
void XARGenerator::DetermineRadialGradientPoints(const Gradient* pGradient, const Transformation& trans, const RectD& boundings, DocCoord& pC, DocCoord& pMaj, DocCoord& pMin) { if (pGradient->units == Gradient::ObjectBoundingBox) { PointD p1m = (boundings.p11+boundings.p12)*0.5; PointD p2m = (boundings.p21+boundings.p22)*0.5; PointD p1M = (boundings.p11+boundings.p21)*0.5; PointD p2M = (boundings.p12+boundings.p22)*0.5; double fCX = p1M.x + (p2M.x-p1M.x)*pGradient->cx; double fCY = p2m.y + (p1m.y-p2m.y)*pGradient->cy; double fXM = fCX + (p2M.x-p1M.x)*pGradient->r; double fYM = fCY; double fXm = fCX; double fYm = fCY + (p1m.y-p2m.y)*pGradient->r; pC = DocCoord((INT32)fCX, (INT32)fCY); pMaj = DocCoord((INT32)fXM, m_docSize.y - (INT32)fYM); pMin = DocCoord((INT32)fXm, m_docSize.y - (INT32)fYm); #ifdef SVGDEBUG svgtrace(DBGTRACE_GRADIENTS, "using ObjectBoundingBox %d,%d %d,%d (%d,%d)\n", pMaj.x, pMaj.y, pMin.x, pMin.y, pC.x, pC.y); #endif } else { // Gradient->units == Gradient::UserSpaceOnUse double fX = pGradient->cx; double fY = pGradient->cy; double fR = pGradient->r; double fX1 = fX + fR; double fY1 = fY; double fX2 = fX; double fY2 = fY + fR; trans.ApplyToCoordinate(fX, fY, &fX, &fY); trans.ApplyToCoordinate(fX1, fY1, &fX1, &fY1); trans.ApplyToCoordinate(fX2, fY2, &fX2, &fY2); pC = DocCoord((INT32)fX, m_docSize.y - (INT32)fY); pMaj = DocCoord((INT32)fX1, m_docSize.y - (INT32)fY1); pMin = DocCoord((INT32)fX2, m_docSize.y - (INT32)fY2); #if SVGDEBUG svgtrace(DBGTRACE_GRADIENTS, "using UserSpaceOnUse %d,%d %d,%d (%d,%d)\n", pMaj.x, pMaj.y, pMin.x, pMin.y, pC.x, pC.y); #endif } }
BOOL ArrowRec::CreateStockArrow(StockArrow ArrowType) { if (ArrowShape != NULL) { delete ArrowShape; ArrowShape = NULL; } BOOL ok; Path* pPath; const INT32 Size = 3; const INT32 Width = (72000/2)*3; if (ArrowType >= NUM_STOCK_ARROWS) ArrowType = SA_STRAIGHTARROW; // Set the ArrowID ArrowID = ArrowType; switch (ArrowType) { case SA_STRAIGHTARROW: /* STRAIGHT -9 54 m -9 0 l -9 -54 l 117 0 l -9 54 l -9 54 l */ pPath = new Path(); if (pPath == NULL) return FALSE; ok = pPath->Initialise(4); if (ok) pPath->FindStartOfPath(); if (ok) ok = pPath->InsertMoveTo(DocCoord( -9000, 54000)); if (ok) ok = pPath->InsertLineTo(DocCoord( -9000, -54000)); if (ok) ok = pPath->InsertLineTo(DocCoord(117000, 0)); if (ok) ok = pPath->CloseSubPath(); if (!ok) { delete pPath; return FALSE; } pPath->IsFilled = TRUE; pPath->IsStroked = FALSE; ArrowShape = pPath; Centre = DocCoord(0,0); LineWidth = Width; ArrowWidth = INT32(Size); ArrowHeight = INT32(Size); IsNull = FALSE; StartArrow = FALSE; break; case SA_ANGLEDARROW: /* ANGLED -26.999 53.999 m -9 0 l -26.999 -54.001 l 135 0 l -26.999 53.999 l */ pPath = new Path(); if (pPath == NULL) return FALSE; ok = pPath->Initialise(5); if (ok) pPath->FindStartOfPath(); if (ok) ok = pPath->InsertMoveTo(DocCoord(-27000, 54000)); if (ok) ok = pPath->InsertLineTo(DocCoord( -9000, 0)); if (ok) ok = pPath->InsertLineTo(DocCoord(-27000, -54000)); if (ok) ok = pPath->InsertLineTo(DocCoord(135000, 0)); if (ok) ok = pPath->CloseSubPath(); if (!ok) { delete pPath; return FALSE; } pPath->IsFilled = TRUE; pPath->IsStroked = FALSE; ArrowShape = pPath; Centre = DocCoord(0,0); LineWidth = Width; ArrowWidth = INT32(Size); ArrowHeight = INT32(Size); IsNull = FALSE; StartArrow = FALSE; break; case SA_ROUNDEDARROW: /* ROUND -9 0 m -9 -45 l -9 -51.708 2.808 -56.580 9 -54 c 117 -9 l 120.916 -7.369 126 -4.242 126 0 c 126 4.242 120.916 7.369 117 9 c 9 54 l 2.808 56.580 -9 51.708 -9 45 c -9 0 l */ pPath = new Path(); if (pPath == NULL) return FALSE; ok = pPath->Initialise(17); if (ok) pPath->FindStartOfPath(); if (ok) ok = pPath->InsertMoveTo( DocCoord( -9000, 0)); if (ok) ok = pPath->InsertLineTo( DocCoord( -9000, -45000)); if (ok) ok = pPath->InsertCurveTo(DocCoord( -9000, -51708), DocCoord( 2808, -56580), DocCoord( 9000, -54000)); if (ok) ok = pPath->InsertLineTo( DocCoord( 117000, -9000)); if (ok) ok = pPath->InsertCurveTo(DocCoord( 120916, -7369), DocCoord( 126000, -4242), DocCoord( 126000, 0)); if (ok) ok = pPath->InsertCurveTo(DocCoord( 126000, 4242), DocCoord( 120916, 7369), DocCoord( 117000, 9000)); if (ok) ok = pPath->InsertLineTo( DocCoord( 9000, 54000)); if (ok) ok = pPath->InsertCurveTo(DocCoord( 2808, 56580), DocCoord( -9000, 51708), DocCoord( -9000, 45000)); if (ok) ok = pPath->CloseSubPath(); if (!ok) { delete pPath; return FALSE; } pPath->IsFilled = TRUE; pPath->IsStroked = FALSE; ArrowShape = pPath; Centre = DocCoord(0,0); LineWidth = Width; ArrowWidth = INT32(Size); ArrowHeight = INT32(Size); IsNull = FALSE; StartArrow = FALSE; break; case SA_SPOT: /* BLOB -54 0 m -54 29.807 -29.807 54 0 54 c 29.807 54 54 29.807 54 0 c 54 -29.807 29.807 -54 0 -54 c -29.807 -54 -54 -29.807 -54 0 c */ pPath = new Path(); if (pPath == NULL) return FALSE; ok = pPath->Initialise(14); if (ok) pPath->FindStartOfPath(); if (ok) ok = pPath->InsertMoveTo( DocCoord( -54000, 0)); if (ok) ok = pPath->InsertCurveTo(DocCoord( -54000, 29807), DocCoord( -29807, 54000), DocCoord( 0, 54000)); if (ok) ok = pPath->InsertCurveTo(DocCoord( 29807, 54000), DocCoord( 54000, 29807), DocCoord( 54000, 0)); if (ok) ok = pPath->InsertCurveTo(DocCoord( 54000, -29807), DocCoord( 29807, -54000), DocCoord( 0, -54000)); if (ok) ok = pPath->InsertCurveTo(DocCoord( -29807, -54000), DocCoord( -54000, -29807), DocCoord( -54000, 0)); if (ok) ok = pPath->CloseSubPath(); if (!ok) { delete pPath; return FALSE; } pPath->IsFilled = TRUE; pPath->IsStroked = FALSE; ArrowShape = pPath; Centre = DocCoord(0,0); LineWidth = Width; ArrowWidth = INT32(Size); ArrowHeight = INT32(Size); IsNull = FALSE; StartArrow = TRUE; break; case SA_DIAMOND: /* DIAMOND -63 0 m 0 63 l 63 0 l 0 -63 l -63 0 l */ pPath = new Path(); if (pPath == NULL) return FALSE; ok = pPath->Initialise(5); if (ok) pPath->FindStartOfPath(); if (ok) ok = pPath->InsertMoveTo(DocCoord(-63000, 0)); if (ok) ok = pPath->InsertLineTo(DocCoord( 0, 63000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 63000, 0)); if (ok) ok = pPath->InsertLineTo(DocCoord( 0, -63000)); if (ok) ok = pPath->CloseSubPath(); if (!ok) { delete pPath; return FALSE; } pPath->IsFilled = TRUE; pPath->IsStroked = FALSE; ArrowShape = pPath; Centre = DocCoord(0,0); LineWidth = Width; ArrowWidth = INT32(Size); ArrowHeight = INT32(Size); IsNull = FALSE; StartArrow = TRUE; break; case SA_ARROWFEATHER: /* FEATHER 18 -54 m 108 -54 l 63 0 l 108 54 l 18 54 l -36 0 l 18 -54 l */ pPath = new Path(); if (pPath == NULL) return FALSE; ok = pPath->Initialise(7); if (ok) pPath->FindStartOfPath(); if (ok) ok = pPath->InsertMoveTo(DocCoord( 18000, -54000)); if (ok) ok = pPath->InsertLineTo(DocCoord(108000, -54000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 63000, 0)); if (ok) ok = pPath->InsertLineTo(DocCoord(108000, 54000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 18000, 54000)); if (ok) ok = pPath->InsertLineTo(DocCoord(-36000, 0)); if (ok) ok = pPath->CloseSubPath(); if (!ok) { delete pPath; return FALSE; } pPath->IsFilled = TRUE; pPath->IsStroked = FALSE; ArrowShape = pPath; Centre = DocCoord(0,0); LineWidth = Width; ArrowWidth = INT32(Size); ArrowHeight = INT32(Size); IsNull = FALSE; StartArrow = TRUE; break; case SA_ARROWFEATHER2: /* FEATHER3 -35.998 0 m 18 -54 l 54 -54 l 18 -18 l 27 -18 l 63 -54 l 99 -54 l 63 -18 l 72 -18 l 108 -54 l 144 -54 l 90 0 l 144 54 l 108 54 l 72 18 l 63 18 l 99 54 l 63 54 l 27 18 l 18 18 l 54 54 l 18 54 l -35.998 0 l */ pPath = new Path(); if (pPath == NULL) return FALSE; ok = pPath->Initialise(23); if (ok) pPath->FindStartOfPath(); if (ok) ok = pPath->InsertMoveTo(DocCoord( -36000, 0)); if (ok) ok = pPath->InsertLineTo(DocCoord( 18000, -54000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 54000, -54000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 18000, -18000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 27000, -18000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 63000, -54000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 99000, -54000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 63000, -18000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 72000, -18000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 108000, -54000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 144000, -54000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 90000, 0)); if (ok) ok = pPath->InsertLineTo(DocCoord( 144000, 54000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 108000, 54000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 72000, 18000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 63000, 18000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 99000, 54000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 63000, 54000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 27000, 18000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 18000, 18000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 54000, 54000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 18000, 54000)); if (ok) ok = pPath->CloseSubPath(); if (!ok) { delete pPath; return FALSE; } pPath->IsFilled = TRUE; pPath->IsStroked = FALSE; ArrowShape = pPath; Centre = DocCoord(0,0); LineWidth = Width; ArrowWidth = INT32(Size); ArrowHeight = INT32(Size); IsNull = FALSE; StartArrow = TRUE; break; case SA_HOLLOWDIAMOND: /* HOLLOW 0 45 m -45 0 l 0 -45 l 45 0 l 0 45 l 0 63 m -63 0 l 0 -63 l 63 0 l 0 63 l */ pPath = new Path(); if (pPath == NULL) return FALSE; ok = pPath->Initialise(10); if (ok) pPath->FindStartOfPath(); if (ok) ok = pPath->InsertMoveTo(DocCoord( 0, 45000)); if (ok) ok = pPath->InsertLineTo(DocCoord(-45000, 0)); if (ok) ok = pPath->InsertLineTo(DocCoord( 0, -45000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 45000, 0)); if (ok) ok = pPath->CloseSubPath(); if (ok) ok = pPath->InsertMoveTo(DocCoord( 0, 63000)); if (ok) ok = pPath->InsertLineTo(DocCoord(-63000, 0)); if (ok) ok = pPath->InsertLineTo(DocCoord( 0, -63000)); if (ok) ok = pPath->InsertLineTo(DocCoord( 63000, 0)); if (ok) ok = pPath->CloseSubPath(); if (!ok) { delete pPath; return FALSE; } pPath->IsFilled = TRUE; pPath->IsStroked = FALSE; ArrowShape = pPath; Centre = DocCoord(-45000,0); LineWidth = Width; ArrowWidth = INT32(Size); ArrowHeight = INT32(Size); IsNull = FALSE; StartArrow = TRUE; break; default: ArrowShape = NULL; Centre = DocCoord(0,0); LineWidth = DEFAULT_ARROW_LINEWIDTH; ArrowWidth = 3; ArrowHeight = 3; StartArrow = FALSE; ScaleWithLineWidth = TRUE; ArrowID = SA_NULLARROW; IsNull = TRUE; break; } return TRUE; }
INT32 ProcessPathDistance::GetCoordAndTangentWithCache(DocCoord* pCoord, double* pTangent, BOOL* pFound, double Dist, Path* pPath, UINT32* pPressure) { ERROR2IF(pCoord==NULL && pTangent==NULL,FALSE,"ProcessPathDistance::GetCoordAndTangent() - no output pointers specified!"); ERROR2IF(pFound==NULL,FALSE,"ProcessPathDistance::GetCoordAndTangent() - pFound==NULL"); ERROR2IF( pPath==NULL,FALSE,"ProcessPathDistance::GetCoordAndTangent() - pPath==NULL"); // we wish to continue processing from the last point that we found INT32 PrevCoordIndex = m_LastFoundIndex; INT32 NumProcessed = m_LastFoundIndex; DesiredDist = Dist; CurrentDist = m_LastFoundDistance; Found = FALSE; CoordAtDist = DocCoord(0,0); TangentAtDist = 0; PressureAtDist = 0; m_bDrawingBrush = TRUE; // set up the processpath process. ProcessFlags PFlags; BOOL bPressure = (pPressure != NULL && pPath->HasWidth()); // if we are already partway along the path then we need to get the // previous point as it is needed in NewPoint if (NumProcessed > 0) { DocCoord* pCoords = pPath->GetCoordArray(); PrevCoord = pCoords[PrevCoordIndex]; if (bPressure) { UINT32* pPressureArray = pPath->GetWidthArray(); if (pPressureArray != NULL) m_PrevPressure = pPressureArray[PrevCoordIndex]; else { ERROR3("Wheres the pressure array?"); m_PrevPressure = (UINT32)(MAXPRESSURE / 2); } } } BOOL ok=ProcessPath::Init(pPath); //TRACEUSER( "Diccon", _T("Desired = %f\n"), Dist); //TRACEUSER( "Diccon", _T("Starting = %f\n"), CurrentDist); if (ok) NumProcessed = Process(PFlags, NumProcessed); if (NumProcessed != -1) { if (Found==FALSE) // this can happen if we are on the first couple of points { // get last 2 points on line DocCoord* pPathCoords=pPath->GetCoordArray(); ERROR2IF(pPathCoords==NULL,FALSE,"ProcessPathDistance::GetCoordAndTangent() - pPathCoords==NULL"); INT32 NumPathCoords=pPath->GetNumCoords(); //ERROR2IF(NumPathCoords<2,FALSE,"ProcessPathDistance::GetCoordAndTangent() - NumPathCoords < 2"); if (NumPathCoords >= 2) { DocCoord LastCoord=pPathCoords[NumPathCoords-1]; DocCoord PrevCoord=pPathCoords[NumPathCoords-2]; double dx=LastCoord.x-PrevCoord.x; double dy=LastCoord.y-PrevCoord.y; double LineLength=sqrt(dx*dx+dy*dy); if (LineLength>0) { double FractOfLine = (DesiredDist-CurrentDist)/LineLength; double x = LastCoord.x+dx*FractOfLine; double y = LastCoord.y+dy*FractOfLine; CoordAtDist = DocCoord((MILLIPOINT)x,(MILLIPOINT)y); TangentAtDist = atan2(dy,dx); Found = TRUE; } else { CoordAtDist = LastCoord; TangentAtDist = 0; Found = TRUE; } } else //if we only have one coordinate so far { CoordAtDist=pPathCoords[0]; TangentAtDist = 0; Found = TRUE; } } else { if (Dist<0) Found=FALSE; // if not actually on path, flag not found on path } *pFound = Found; if (pCoord) *pCoord = CoordAtDist; if (pTangent) *pTangent = TangentAtDist; if (pPressure != NULL) *pPressure = PressureAtDist; } //m_LastFoundDistance = CurrentDist; //TRACEUSER( "Diccon", _T("Last Index = %d\n"), m_LastFoundIndex); //TRACEUSER( "Diccon", _T("Last Dist = %f\n"), m_LastFoundDistance); //TRACEUSER( "Diccon", _T("FOUND = %d\n"), Found); return NumProcessed; }
void RenderDemoDlg::RenderControl(ReDrawInfoType* ExtraInfo) { // Go get a render region DocRect VirtualSize(-ExtraInfo->dx/2, -ExtraInfo->dy/2, ExtraInfo->dx/2, ExtraInfo->dy/2); RenderRegion* pRender = CreateGRenderRegion(&VirtualSize, ExtraInfo); if (pRender!=NULL) { DialogColourInfo RedrawColours; // Get a supplier for default dlg colours // Render stuff in here // Build a Linear fill attribute LinearFillAttribute MyGradFill; MyGradFill.Colour = DocColour(255, 255, 0); MyGradFill.EndColour = DocColour(0, 255, 255); MyGradFill.StartPoint = DocCoord(0, ExtraInfo->dy); MyGradFill.EndPoint = DocCoord(ExtraInfo->dx, 0); // Build a path Path InkPath; InkPath.Initialise(12,12); InkPath.FindStartOfPath(); // Get the coords used to build a shape INT32 dx = ExtraInfo->dx / 2; INT32 dy = ExtraInfo->dy / 2; INT32 Midx = ExtraInfo->dx / 4; INT32 Midy = ExtraInfo->dy / 4; // build a circle in the middle of the control InkPath.InsertMoveTo(DocCoord(Midx, dy)); InkPath.InsertCurveTo(DocCoord(Midx+Midx/2, dy), DocCoord(dx, Midy+Midy/2), DocCoord(dx, Midy)); InkPath.InsertCurveTo(DocCoord(dx, Midy-Midy/2), DocCoord(Midx+Midx/2, 0), DocCoord(Midx, 0)); InkPath.InsertCurveTo(DocCoord(Midx-Midx/2, 0), DocCoord(0, Midy-Midy/2), DocCoord(0, Midy)); InkPath.InsertCurveTo(DocCoord(0, Midy+Midy/2), DocCoord(Midx-Midx/2, dy), DocCoord(Midx, dy)); InkPath.IsFilled = TRUE; // A Grey colour [...hmmm, it's not a very grey grey any more... oragnge more like] DocColour Grey(255,200,0); // Render the attributes and the a rectangle pRender->SaveContext(); pRender->SetLineColour(Grey); // Draw a rectangle to fill in the background - Fill with Dialogue Background colour DocRect DrawMe(0, 0, ExtraInfo->dx, ExtraInfo->dy); pRender->SetFillColour(RedrawColours.DialogBack()); pRender->DrawRect(&VirtualSize); // Draw some shapes and stuff pRender->SetFillGeometry(&MyGradFill, FALSE); pRender->DrawPath(&InkPath); // Build a path Path TriPath; TriPath.Initialise(12,12); TriPath.FindStartOfPath(); // build a circle in the middle of the control TriPath.InsertMoveTo(VirtualSize.lo); TriPath.InsertLineTo(DocCoord(VirtualSize.hi.x, VirtualSize.lo.y)); TriPath.InsertLineTo(DocCoord(0, VirtualSize.hi.y)); TriPath.InsertLineTo(VirtualSize.lo); TriPath.IsFilled = TRUE; LinearFillAttribute MyTriFill; MyTriFill.Colour = ShowFirst ? First : Second; MyTriFill.EndColour = DocColour(0,0,0); MyTriFill.StartPoint = DocCoord(ExtraInfo->dx, 0); MyTriFill.EndPoint = DocCoord(0, ExtraInfo->dy); pRender->SetFillGeometry(&MyTriFill, FALSE); pRender->DrawPath(&TriPath); pRender->RestoreContext(); // Get rid of the render region DestroyGRenderRegion(pRender); } // and animate it! if (ShowFirst) { INT32 Red, Green, Blue; First.GetRGBValue(&Red, &Green, &Blue); if (Blue>0) { // Set the colour back again Blue -= 10; First.SetRGBValue(Red, Green, Blue); // redraw it InvalidateGadget(_R(IDC_REDRAW_ME)); } } else { // Set the colour back to how it was First.SetRGBValue(255, 0, 250); } }
//#include "trans2d.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "will.h" //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED] class Spread; DECLARE_SOURCE("$Revision$"); CC_IMPLEMENT_DYNCREATE(OpFillNudge,Operation) CC_IMPLEMENT_DYNCREATE(FillGeometryNudger, AttrValueChange) BOOL OpFillNudge::NudgeCols; // Shall we nudge colour or transparency fills ? static CCRuntimeClass* LastNudgeType = NULL; static DocCoord LastNudgeStart = DocCoord(0,0); static DocCoord LastNudgeEnd = DocCoord(0,0); static DocCoord LastNudgeEnd2 = DocCoord(0,0); /******************************************************************************************** > static void OpFillNudge::NudgeColours(BOOL cols) Author: Will_Cowling (Xara Group Ltd) <*****@*****.**> Created: 28/3/94 Purpose: Sets whether a nudge will nudge colour or transparency fills. ********************************************************************************************/ void OpFillNudge::NudgeColours(BOOL cols) {
void OpFillNudge::Do(OpDescriptor* pOpDesc) { // Get scaled pixel size FIXED16 ScaledPixelWidth, ScaledPixelHeight; GetWorkingView()->GetScaledPixelSize(&ScaledPixelWidth, &ScaledPixelHeight) ; PixelNudge=ScaledPixelWidth.MakeDouble() ; // Determine the nudge factors based on the OpDescriptor used to invoke the nudge operation String OpToken = pOpDesc->Token; if (OpToken == String(OPTOKEN_NUDGEUPPIXEL1)) { IsPixelNudgeClass = TRUE; } else if (OpToken == String(OPTOKEN_NUDGEUPPIXEL10)) { IsPixelNudgeClass = TRUE; } else if (OpToken == String(OPTOKEN_NUDGEDOWNPIXEL1)) { IsPixelNudgeClass = TRUE; } else if (OpToken == String(OPTOKEN_NUDGEDOWNPIXEL10)) { IsPixelNudgeClass = TRUE; } else if (OpToken == String(OPTOKEN_NUDGELEFTPIXEL1)) { IsPixelNudgeClass = TRUE; } else if (OpToken == String(OPTOKEN_NUDGELEFTPIXEL10)) { IsPixelNudgeClass = TRUE; } else if (OpToken == String(OPTOKEN_NUDGERIGHTPIXEL1)) { IsPixelNudgeClass = TRUE; } else if (OpToken == String(OPTOKEN_NUDGERIGHTPIXEL10)) { IsPixelNudgeClass = TRUE; } else if (OpToken == String(OPTOKEN_NUDGEUP1)) { IsPixelNudgeClass = FALSE; } else if (OpToken == String(OPTOKEN_NUDGEUP5)) { IsPixelNudgeClass = FALSE; } else if (OpToken == String(OPTOKEN_NUDGEUP10)) { IsPixelNudgeClass = FALSE; } else if (OpToken == String(OPTOKEN_NUDGEUPFIFTH)) { IsPixelNudgeClass = FALSE; } else if (OpToken == String(OPTOKEN_NUDGEDOWN1)) { IsPixelNudgeClass = FALSE; } else if (OpToken == String(OPTOKEN_NUDGEDOWN5)) { IsPixelNudgeClass = FALSE; } else if (OpToken == String(OPTOKEN_NUDGEDOWN10)) { IsPixelNudgeClass = FALSE; } else if (OpToken == String(OPTOKEN_NUDGEDOWNFIFTH)) { IsPixelNudgeClass = FALSE; } else if (OpToken == String(OPTOKEN_NUDGELEFT1)) { IsPixelNudgeClass = FALSE; } else if (OpToken == String(OPTOKEN_NUDGELEFT5)) { IsPixelNudgeClass = FALSE; } else if (OpToken == String(OPTOKEN_NUDGELEFT10)) { IsPixelNudgeClass = FALSE; } else if (OpToken == String(OPTOKEN_NUDGELEFTFIFTH)) { IsPixelNudgeClass = FALSE; } else if (OpToken == String(OPTOKEN_NUDGERIGHT1)) { IsPixelNudgeClass = FALSE; } else if (OpToken == String(OPTOKEN_NUDGERIGHT5)) { IsPixelNudgeClass = FALSE; } else if (OpToken == String(OPTOKEN_NUDGERIGHT10)) { IsPixelNudgeClass = FALSE; } else if (OpToken == String(OPTOKEN_NUDGERIGHTFIFTH)) { IsPixelNudgeClass = FALSE; } // Setup the Offset DocCoord to contain the X and Y translation values DocCoord Offset; if (IsPixelNudgeClass) { Offset.x=(INT32)GetXPixelDisplacement(); Offset.y=(INT32)GetYPixelDisplacement(); } else if (!IsPixelNudgeClass) { //TypeCast from double to INT32 Offset.x=(INT32) GetXNudgeDisplacement(); Offset.y=(INT32) GetYNudgeDisplacement(); } if (AttrFillGeometry::SelectionCount == 0) { // Nothing to Nudge !! FailAndExecute(); End(); return; } FillGeometryNudger* FillNudger = new FillGeometryNudger(); if (FillNudger == NULL) { FailAndExecute(); End(); return; } FillNudger->MutateColourFills(NudgeCols); FillNudger->SetNudgeDistance(Offset.x, Offset.y); AttributeManager::AttributeSelected(NULL, FillNudger); LastNudgeType = NULL; LastNudgeStart = DocCoord(0,0); LastNudgeEnd = DocCoord(0,0); LastNudgeEnd2 = DocCoord(0,0); End(); }
BOOL ProcessPathToTrapezoids::NewPoint(PathVerb Verb, DocCoord *pCoord) { // Process any join we've just gone past. We have to delay processing of joins // until we know which way the curve headed off after the join, which is why // we are processing it now. If the new point is a MOVETO, then there is no join if (PointFollowsJoin && Verb == PT_LINETO) { // Find the last edge in the current edge list. If we can't find one, there is // nothing to "join to" TrapEdgeList *pEdgeList = pTraps->GetLastTrapEdgeList(); TrapEdge *pEdge = NULL; if (pEdgeList != NULL) pEdge = pEdgeList->GetLastTrapEdge(); if (pEdge != NULL) { switch(JoinType) { case MitreJoin: // A mitred join involves extending the previous and next segments of the outline // to their intersection. If there is no intersection, or if the intersection // is beyond the "MitreLimit", then we revert to a simple Bevelled join. // Otherwise, we need to add 2 line segments (3 trapezoid edges) joining the // end of the last segment to the intersection, and then from the intersection // to the start of this new segment. // These new segments are marked as being part of a join so that they will be // stroked as straight line segments rather than interpolating normals to make // a smoothed/curved join. { ERROR3IF(pEdgeList->GetNumEdges() < 2, "Not enough traps for mitred join"); TrapEdge *pPrevEdge = pEdgeList->GetTrapEdge(pEdgeList->GetNumEdges() - 2); BOOL Mitred; if (pCoord != NULL) { Mitred = CalculateMitreIntersection(&pPrevEdge->Centre, &pEdge->Centre, pCoord); } else { // No pCoord passed in, so this is the join at the end. Use the 1st point // in the subpath as the "next point". (Well, the 2nd in the array, because point // 1 is coincident! We use point 2 which is the end of the 1st line) DocCoord NextCoord = pEdgeList->GetTrapEdge(1)->Centre; Mitred = CalculateMitreIntersection(&pPrevEdge->Centre, &pEdge->Centre, &NextCoord); } //BLOCK { // Nasty bodge - Because AddEdge can re-alloc the array, we CANNOT keep pointers // to array entries around over calls to AddEdge. We thus copy the edge point // into a temporary variable which we can safely use over the 2 calls the AddEdge DocCoord Temp = pEdge->Centre; // Add a single point for this join - by default this gives a Bevelled join pEdgeList->AddEdge(&Temp, TrapJoin_MitredOrBevelled); // And if it's Mitred, then add another point for this join if (Mitred) pEdgeList->AddEdge(&Temp, TrapJoin_MitredOrBevelled); } } break; case RoundJoin: // To make a rounded join, you might think we need to output a number of trapezoids, // but in fact the recursive flattened-mapping algorithm employed by the path // stroker will "smooth" a single trapezoid into a proper round join! // Thus, we simply insert another trapezoid on the join point (but do NOT mark // it as "part of a join") so that it will be mapped as a round join. pEdgeList->AddEdge(&pEdge->Centre, TrapJoin_Round); break; case BevelledJoin: // To make a bevelled join, we simply add another TrapEdge on the join point for // the start of the next segment, which will be joined with a straight line. // However, the stroking mechanism will actually output that "line" as a round // join (due to its recursive flattened-mapping algorithm), so we have to // mark this point as "part of a join" so that it simply plonks down the // straight segment we want! (Hence the TRUE) pEdgeList->AddEdge(&pEdge->Centre, TrapJoin_MitredOrBevelled); break; default: ERROR3("Unsupported join type in ProcessPathToTrapezoids"); break; } } } // Clear the join flag, as any pending join has been processed PointFollowsJoin = FALSE; // If the provided coordinate was NULL, then they only wanted to add the join // information, so we exit now if (pCoord == NULL) return(TRUE); // Add the new point to the current trapezoid list switch(Verb) { case PT_MOVETO: { // A MoveTo signifies the start of a new (sub)path, so we start a new TrapList TrapEdgeList *pEdgeList = pTraps->AddEdgeList(); if (pEdgeList == NULL) return(FALSE); pEdgeList->AddEdge(pCoord); LastPoint = *pCoord; } break; case PT_LINETO: { // Append each new point as a new trapezoid edge in the current TrapList // Find the last TrapEdgeList TrapEdgeList *pEdgeList = pTraps->GetLastTrapEdgeList(); if (pEdgeList == NULL) { // We have started a path with a LineTo! // Create a new Trapezoid List (imply that this point is really a MOVETO) ERROR3("LINETO added to traplist with no preceding MOVETO"); LastPoint = DocCoord(0,0); pEdgeList = pTraps->AddEdgeList(); if (pEdgeList == NULL) return(FALSE); } // Append the new point to the current trap list. Check first to eliminate // coincident points (places where the source path has coincident points), // as we only want coincident points to occur in the special case of joins. if (pEdgeList->GetNumEdges() < 1 || LastPoint != *pCoord) { pEdgeList->AddEdge(pCoord); LastPoint = *pCoord; } } break; default: ERROR3("ProcessPathToTrapezoids only handles MOVETO and LINETO!"); break; } return(TRUE); }
void ArrangeAlignment::RedrawDiagram(ReDrawInfoType* ExtraInfo) { // objects drawn in the render region must be relatively large in the given coord space // else Gavin's curve flattening results in visible straight lines // so every dimension is scaled by scale INT32 scale=1000; // make a render region DocRect VirtRendRect; VirtRendRect.lo.x=-1*scale; VirtRendRect.lo.y=-2*scale; VirtRendRect.hi.x=(DiagWidth +1)*scale; VirtRendRect.hi.y=(DiagHeight+2)*scale; RenderRegion* pRender=CreateGRenderRegion(&VirtRendRect,ExtraInfo); if (pRender!=NULL) { pRender->SaveContext(); // currently this must be set here before any colour tables calculated Quality AntiAliasQuality(Quality::QualityMax); QualityAttribute AntiAliasQualityAttr(AntiAliasQuality); pRender->SetQuality(&AntiAliasQualityAttr,FALSE); // Render the background rectangle DialogColourInfo RedrawColours; pRender->SetLineColour(RedrawColours.DialogBack()); pRender->SetFillColour(RedrawColours.DialogBack()); pRender->DrawRect(&VirtRendRect); // declared at this scope else RestoreContext() dies! RadialFillAttribute Fill; // set up some defaults used by all objects Fill.MakeElliptical(); Fill.Colour=DocColour(255,255,255); pRender->SetLineColour(BLACK); pRender->SetLineWidth(0); for (INT32 i=0; i<DiagRects; i++) { // reverse order in which objets are rendered (now filled!) INT32 j=DiagRects-1-i; // set fill colour of each object switch (j) { case 0: Fill.EndColour=DocColour(255,255,0); break; case 1: Fill.EndColour=DocColour(0,0,255); break; case 2: Fill.EndColour=DocColour(255,0,0); break; case 3: Fill.EndColour=DocColour(0,160,0); break; default: Fill.EndColour=DocColour(0,0,0); break; } // get bound rect of object to be drawn INT32 x=DiagRectX[Align.h][j].lo*scale; INT32 w=DiagRectX[Align.h][j].hi*scale-x; INT32 y=DiagRectY[Align.v][j].lo*scale; INT32 h=DiagRectY[Align.v][j].hi*scale-y; // create shape and fill geometries Path shape; shape.Initialise(16,8); shape.IsFilled=TRUE; shape.FindStartOfPath(); switch (j) { case 0: { // create a rectangle shape.InsertMoveTo(DocCoord(x,y)); shape.InsertLineTo(DocCoord(x,y+h)); shape.InsertLineTo(DocCoord(x+w,y+h)); shape.InsertLineTo(DocCoord(x+w,y)); shape.InsertLineTo(DocCoord(x,y)); // // create a radial fill // Fill.StartPoint=DocCoord(x+w*3/16,y+h*3/4); // Fill.EndPoint =DocCoord(x+w*3/8,y+h/2); // Fill.EndPoint2 =DocCoord(x+w*3/8,y+h); break; } case 1: { // create a pseudo ellipse shape.InsertMoveTo( DocCoord(x,y+h/2)); shape.InsertCurveTo(DocCoord(x,y+h*3/4), DocCoord(x+w/4,y+h), DocCoord(x+w/2,y+h)); shape.InsertCurveTo(DocCoord(x+w*3/4,y+h),DocCoord(x+w,y+h*3/4),DocCoord(x+w,y+h/2)); shape.InsertCurveTo(DocCoord(x+w,y+h/4), DocCoord(x+w*3/4,y), DocCoord(x+w/2,y)); shape.InsertCurveTo(DocCoord(x+w/4,y), DocCoord(x,y+h/4), DocCoord(x,y+h/2)); // // create a radial fill // Fill.StartPoint=DocCoord(x+w*3/8,y+h*5/8); // Fill.EndPoint =DocCoord(x+w*6/8,y+h/4); // Fill.EndPoint2 =DocCoord(x+w*6/8,y+h); break; } default: { // create a rounded rectangle shape.InsertMoveTo( DocCoord(x,y+h/2)); shape.InsertCurveTo(DocCoord(x,y+h), DocCoord(x,y+h), DocCoord(x+w/2,y+h)); shape.InsertCurveTo(DocCoord(x+w,y+h),DocCoord(x+w,y+h),DocCoord(x+w,y+h/2)); shape.InsertCurveTo(DocCoord(x+w,y), DocCoord(x+w,y), DocCoord(x+w/2,y)); shape.InsertCurveTo(DocCoord(x,y), DocCoord(x,y), DocCoord(x,y+h/2)); // // create a radial fill // Fill.StartPoint=DocCoord(x+w*3/16,y+h*3/4); // Fill.EndPoint =DocCoord(x+w*3/8,y+h/2); // Fill.EndPoint2 =DocCoord(x+w*3/8,y+h); break; } } // pRender->SetFillGeometry(&Fill,FALSE); pRender->SetFillColour(Fill.EndColour); pRender->DrawPath(&shape); } pRender->RestoreContext(); DestroyGRenderRegion(pRender); // also blt's to screen } }
/******************************************************************************************** INT32 HTMLExportFilter::WriteCoords(Path* ppthToWrite, TCHAR* pcValue, CCLexFile* pfileToWrite, TCHAR* pcBuffer) Author: Graham_Walmsley (Xara Group Ltd) <*****@*****.**> Created: 18/4/97 Inputs: ppthToWrite Pointer to the path to write pfileToWrite The file to write to (may be NULL) pcBuffer The text buffer to write to (may be NULL) Returns: The number of TCHARs written Purpose: Writes out the coordinates of a polygon e.g. COORDS="0,0,0,100,100,100,100,0" ********************************************************************************************/ INT32 HTMLExportFilter::WriteCoords(Path* ppthToWrite, TCHAR* pcValue, CCLexFile* pfileToWrite, TCHAR* pcBuffer) { //This is the value we will return INT32 lCharsWritten=0; //First write out a space lCharsWritten+=Write(_R(IDS_HTMLEXPORT_SPACE), pfileToWrite, pcBuffer); //Now write out COORDS lCharsWritten+=Write(_R(IDS_HTMLEXPORT_COORDS), pfileToWrite, pcBuffer); //And an equals sign lCharsWritten+=Write(_R(IDS_HTMLEXPORT_EQUALS), pfileToWrite, pcBuffer); //And an opening quote lCharsWritten+=Write(_R(IDS_HTMLEXPORT_QUOTES), pfileToWrite, pcBuffer); //Now we must write out the path's coordinates. So find out how //INT32 the path is INT32 lNumCoords=ppthToWrite->GetNumCoords(); //And get its coordinate and verb arrays DocCoord* pdcCoords=ppthToWrite->GetCoordArray(); // PathVerb* ppvVerbs=ppthToWrite->GetVerbArray(); //Keep a copy of the last coordinate written, to make sure //we don't write out two consecutive identical coordinates DocCoord dcLastWritten=DocCoord(-1, -1); //Now do the following for every coordinate in the path //EXCEPT the last, which will be the same as the first INT32 lThisCoord=0; do { //If this coordinate isn't the same as the last one we wrote if (pdcCoords[lThisCoord]!=dcLastWritten) { //Write out a comma, unless this is the first coord to be written if (lThisCoord>0) lCharsWritten+=Write(_R(IDS_HTMLEXPORT_COMMA), pfileToWrite, pcBuffer); //Write it out, followed by a comma lCharsWritten+=Write(pdcCoords[lThisCoord], pfileToWrite, pcBuffer); } //Keep a copy of this coordinate dcLastWritten=pdcCoords[lThisCoord]; //And move on to the next coordinate ppthToWrite->FindNextEndPoint(&lThisCoord); } while (lThisCoord<lNumCoords-1); //Write a closing quote lCharsWritten+=Write(_R(IDS_HTMLEXPORT_QUOTES), pfileToWrite, pcBuffer); //And return the number of characters written return lCharsWritten; }
/******************************************************************************************** > void BitmapExportPaletteControl::DrawCell(DocRect *pCellRect, DocColour colour, INT32 flags, RenderRegion *pRender, bool webSafe, bool selected, bool highlight) Author: Jonathan_Payne (Xara Group Ltd) <*****@*****.**> Created: 12/12/2000 Purpose: Draw a palette cell with the given options Inputs: pCellRect - The rect to draw the palette cell in colour - The colour of the palette entry to draw flags - The flags of that palette entry (locked, transparency, etc) pRender - The render region to render with (tested with an OS rr) webSafe - Is the colour web safe (ie do we draw the web safe mark) selected - Do we draw the cell as the selected cell? ********************************************************************************************/ void BitmapExportPaletteControl::DrawCell(DocRect *pCellRect, DocColour colour, INT32 flags, RenderRegion *pRender, bool webSafe, bool selected) { pRender->SetLineColour(COLOUR_BLACK); pRender->SetFillColour(colour); pRender->DrawRect(pCellRect); if (selected) { pRender->SetFillColour(COLOUR_TRANS); DocRect cell = *pCellRect; // make temp copy // Draw the outer line in white pRender->SetLineColour(COLOUR_WHITE); cell.Inflate(-1 * m_nPixelSize); pRender->DrawRect(&cell); // Draw the inner line in black pRender->SetLineColour(COLOUR_BLACK); cell.Inflate(-1 * m_nPixelSize); pRender->DrawRect(&cell); } if (flags & DELETED_COLOUR) { // Draw a mark to show that this palette entry has been deleted // Draw a black line from top left to bottom right pRender->SetLineColour(COLOUR_BLACK); pRender->DrawLine( DocCoord(pCellRect->lo.x, pCellRect->hi.y + m_nPixelSize), DocCoord(pCellRect->hi.x + m_nPixelSize, pCellRect->lo.y)); // Draw a white line from top right to bottom left pRender->SetLineColour(COLOUR_WHITE); pRender->DrawLine( DocCoord(pCellRect->hi.x + m_nPixelSize, pCellRect->hi.y + m_nPixelSize), DocCoord(pCellRect->lo.x + m_nPixelSize, pCellRect->lo.y + m_nPixelSize)); return; // Stop before rending any other marks } if (flags & LOCKED_COLOUR) { // Draw a mark to show that this palette entry has been // edited by the user. pRender->SetLineColour(COLOUR_BLACK); pRender->SetFillColour(COLOUR_WHITE); // Draw a rectangle in the bottom left corner of the cell DocRect markRect; markRect.hi.x = pCellRect->lo.x + m_nPixelSize * 2; markRect.lo.x = pCellRect->lo.x; markRect.hi.y = pCellRect->lo.y + m_nPixelSize * 2; markRect.lo.y = pCellRect->lo.y; pRender->DrawRect(&markRect); } if (flags & TRANSPARENT_COLOUR) { // Draw a mark to show that this palette entry is transparent pRender->SetLineColour(COLOUR_BLACK); pRender->SetFillColour(COLOUR_WHITE); // Draw a rectangle in the top left corner of the cell DocRect markRect; markRect.hi.x = pCellRect->lo.x + m_nPixelSize * 2; markRect.lo.x = pCellRect->lo.x; markRect.hi.y = pCellRect->hi.y; markRect.lo.y = pCellRect->hi.y - m_nPixelSize * 2; pRender->DrawRect(&markRect); } if (webSafe) { // Draw a mark to show that this palette entry is web-safe pRender->SetLineColour(COLOUR_BLACK); pRender->SetFillColour(COLOUR_WHITE); DocRect markRect = *pCellRect; markRect.Inflate(-4 * m_nPixelSize); pRender->DrawRect(&markRect); } }
BOOL EditTab::CommitSection() { TRACEUSER( "Neville", _T("commit edit section\n")); ERROR2IF(pPrefsDlg == NULL,FALSE,"EditTab::CommitSection called with no dialog pointer"); BOOL ok = pPrefsDlg->TalkToPage(_R(IDD_OPTSTAB_EDIT)); // The edit page identifier if (!ok) return TRUE; // Talk to page failed to return now // Section = Edit // Ok has been pressed so take the values from this section of the dialog box BOOL Valid=FALSE; // Flag for validity of value BOOL State=FALSE; // Flag for state of button/switch BOOL SetOk=TRUE; // Preference value set ok // Section = Attributes State = pPrefsDlg->GetLongGadgetValue(_R(IDC_OPTS_ASKSETATTRB), 0, 1, 0, &Valid); SetOk = Camelot.SetPrefValue(TEXT("Attributes"),TEXT("AskBeforeSettingCurrentAttr"),&State); ERROR2IF(!SetOk,2,_R(IDE_OPTS_SETPREF_EDIT)); State = pPrefsDlg->GetLongGadgetValue(_R(IDC_OPTS_LASTATTRB), 0, 1, 0, &Valid); SetOk = Camelot.SetPrefValue(TEXT("Attributes"),TEXT("LastAttrAppliedBecomesCurrent"),&State); ERROR2IF(!SetOk,2,_R(IDE_OPTS_SETPREF_EDIT)); // Set up the units that are used in the currently selected document // All units work off the selected document and so we must do nothing if there is no // selected document. ok = SetUpDocUnits(); if (!ok) return (TRUE); // Section = Constraints // Now the constraint angle combo box // Convert to double uses units and so requires a selected document double Angle = 0.0; // Angle stored in radians in the preference system double AngleInDegrees = 0; // Angle displayed in degrees to the user AngleInDegrees = pPrefsDlg->GetDoubleGadgetValue(_R(IDC_OPTS_ANGLECONST), 0, 360, _R(IDE_OPTS_INVALIDANGLE), &Valid); if (Valid) { // Angle in correct range so put it into the preference system Angle = AngleInDegrees * PI/180.0; // convert angle to radians TRACEUSER( "Neville", _T("commit constraint angle in degrees='%d' angle='%d' Valid ='%d'\n"), AngleInDegrees, Angle, Valid); SetOk = Camelot.SetPrefValue(TEXT("Constraints"), TEXT("Constrain Angle"), &Angle); ERROR2IF(!SetOk,2,_R(IDE_OPTS_SETPREF_EDIT)); } else return FALSE; // Angle incorrect, user has been warned already // Now the duplicate distance INT32 x = 0; INT32 y = 0; const INT32 Maxxy = INT_MAX; // maximum value allowed as the distance BOOL bValidX = FALSE; BOOL bValidY = FALSE; ok = pPrefsDlg->TalkToPage(_R(IDD_OPTSTAB_EDIT)); // The edit page identifier x = pPrefsDlg->GetUnitGadgetValue(_R(IDC_OPTS_XDUPLICATE), CurrentScaledUnits, -Maxxy, Maxxy, _R(IDE_OPTS_INVALIDDISTANCE), &bValidX); /* if (Valid) { SetOk = Camelot.SetPrefValue(TEXT("Duplicate"), TEXT("DuplicatePlacementX"), &x); ERROR2IF(!SetOk,2,_R(IDE_OPTS_SETPREF_EDIT)); } else return FALSE; // Duplicate x incorrect, user has been warned already */ ok = pPrefsDlg->TalkToPage(_R(IDD_OPTSTAB_EDIT)); // The edit page identifier y = pPrefsDlg->GetUnitGadgetValue(_R(IDC_OPTS_YDUPLICATE), CurrentScaledUnits, -Maxxy, Maxxy, _R(IDE_OPTS_INVALIDDISTANCE), &bValidY); /* if (Valid) { SetOk = Camelot.SetPrefValue(TEXT("Duplicate"), TEXT("DuplicatePlacementY"), &y); ERROR2IF(!SetOk,2,_R(IDE_OPTS_SETPREF_EDIT)); } else return FALSE; // Duplicate y incorrect, user has been warned already */ if (bValidX && bValidY) { pDocument->SetDuplicationOffset(DocCoord(x,y)); pDocument->SetModified(TRUE); } else return FALSE; // Now the nudge size distance UINT32 Nudge = 0; ok = pPrefsDlg->TalkToPage(_R(IDD_OPTSTAB_EDIT)); // The edit page identifier Nudge = pPrefsDlg->GetUnitGadgetValue(_R(IDC_OPTS_NUDGESIZE), CurrentScaledUnits, 0, INT_MAX, _R(IDE_OPTS_INVALIDNUDGE), &Valid); TRACEUSER( "Neville", _T("commit nudge distance='%d' Valid ='%d'\n"),Nudge, Valid); if (Valid) { /*SetOk =*/ pDocument->SetDocNudge (Nudge);//Camelot.SetPrefValue(TEXT("Nudge"), TEXT("StepSize"), &Nudge); pDocument->SetModified (TRUE); //ERROR2IF(!SetOk,2,_R(IDE_OPTS_SETPREF_EDIT)); } else return FALSE; // Nudge size incorrect, user has been warned already return TRUE; }
void PathProcessorStrokeAirbrush::ProcessPath(Path *pPath, RenderRegion *pRender, PathShape ShapePath) { PORTNOTETRACE("other","PathProcessorStrokeAirbrush::ProcessPath - do nothing"); #ifndef EXCLUDE_FROM_XARALX ERROR3IF(pPath == NULL || pRender == NULL, "Illegal NULL Params"); // --- If the provided path is not stroked, then we'll just pass it straight through // We also don't touch it if we're doing EOR rendering, or click regions // BLOCK { StrokeColourAttribute *pStrokeColour = (StrokeColourAttribute *) pRender->GetCurrentAttribute(ATTR_STROKECOLOUR); if (pRender->DrawingMode != DM_COPYPEN || pRender->IsHitDetect() || !pPath->IsStroked || pStrokeColour == NULL || pStrokeColour->Colour.IsTransparent()) { pRender->DrawPath(pPath, this, ShapePath); return; } } // --- If the quality is set low, strokes are just rendered as centrelines // BLOCK { QualityAttribute *pQuality = (QualityAttribute *) pRender->GetCurrentAttribute(ATTR_QUALITY); if (pQuality != NULL && pQuality->QualityValue.GetLineQuality() != Quality::FullLine) { pRender->DrawPath(pPath, this, ShapePath); return; } } // --- If the attribute which created us is not the current StrokeType attribute, then // we have been overridden by a different stroke type, so we do nothing. // BLOCK { StrokeTypeAttrValue *pTypeAttr = (StrokeTypeAttrValue *) pRender->GetCurrentAttribute(ATTR_STROKETYPE); if (pTypeAttr != NULL && pTypeAttr != GetParentAttr()) { pRender->DrawPath(pPath, this, ShapePath); return; } } // --- Get the current line width from the render region // In case of failure, we initialise with suitable defaults INT32 LineWidth = 5000; // BLOCK { LineWidthAttribute *pWidthAttr = (LineWidthAttribute *) pRender->GetCurrentAttribute(ATTR_LINEWIDTH); if (pWidthAttr != NULL) LineWidth = pWidthAttr->LineWidth; } // Obtain an optimal number of steps for the line // When printing, we do heaps of steps to get top quality out the other end View *pView = pRender->GetRenderView(); ERROR3IF(pView == NULL, "No render view?!"); INT32 NumSteps = MaxAirbrushSteps; if (!pRender->IsPrinting()) GetNumSteps(pView, LineWidth); // --- Now, create a transparency mask bitmap for the airbrush Spread *pSpread = pRender->GetRenderSpread(); // ERROR3IF(pSpread == NULL, "No render spread!?"); // This can happen, rendering into a gallery // Get the render region's clip rectangle in Spread Coords. We don't need to // render anything bigger than this size, so it is the upper limit on our bitmap area. DocRect ClipRegion = pRender->GetClipRect(); // Intersect this with the path bounding rectangle to get the actual region we need to redraw // The smaller this is, the faster we go and the less memory we use. //DocRect PathRect = pPath->GetBoundingRect(); DocRect PathRect = pPath->GetBlobRect(); PathRect.Inflate(LineWidth); BOOL Intersects = ClipRegion.IsIntersectedWith(PathRect); if(!Intersects) { // Don't bother drawing anything - it's clipped out return; } ClipRegion = ClipRegion.Intersection(PathRect); // Round the ClipRegion edges up so they all lie exactly on screen pixel boundaries. // If we don't do this, then there can be a sub-pixel rounding error between the ClipRegion // and the actual bitmap size, so that the bitmap is scaled slightly when we plot it. // By making sure it's pixelised, we guarantee that the bitmap & clipregion are exactly equal sizes. // (It doesn't matter if the bitmap is a bit bigger than necessary) ClipRegion.Inflate(pRender->GetScaledPixelWidth()); ClipRegion.lo.Pixelise(pView); ClipRegion.hi.Pixelise(pView); // Get the current view's rendering matrix and view scale Matrix ConvMatrix = pRender->GetMatrix();//pView->ConstructRenderingMatrix(pSpread); FIXED16 ViewScale = pView->GetViewScale(); // Generate a 256-colour greyscale palette LOGPALETTE *pPalette = MakeGreyScalePalette(); if(pPalette == NULL) { pRender->DrawPath(pPath, this, ShapePath); return; } // Work out the DPI to use. Rather than just asking for PixelWidth or DPI from the // render region, we have to do a load of non-object-oriented stuff instead... double dpi = 96.0; if (pRender->IsPrinting()) { // we are printing, so ask the print options PrintControl *pPrintControl = pView->GetPrintControl(); if (pPrintControl != NULL) dpi = (double) pPrintControl->GetDotsPerInch(); } else if (IS_A(pRender, CamelotEPSRenderRegion)) { // Use DPI as set in EPS export options dialog. dpi = (double) EPSFilter::XSEPSExportDPI; } else { ERROR3IF(pRender->GetPixelWidth() <= 0, "Stupid (<1 millipoint) Pixel Width!"); if (pRender->GetPixelWidth() > 0) dpi = (double) (72000.0 / (double)pRender->GetPixelWidth()); } GRenderBitmap *pMaskRegion = new GRenderBitmap(ClipRegion, ConvMatrix, ViewScale, 8, dpi, pRender->IsPrinting(), XARADITHER_ORDERED_GREY, pPalette, FALSE); if (pMaskRegion == NULL) { pRender->DrawPath(pPath, this, ShapePath); return; } BOOL PathIsFilled = FALSE; // Will be set TRUE if this path should be filled at the bottom of the function //BLOCK { // Change the GDraw context in this render region so as to preserve the state // of the main render region. This is because GRenderRegions currently use // a single static GDrawContext! This also sets it up with a nice greyscale palette // so that we get the output we desire. pMaskRegion->UseGreyscaleContextDangerous(); // Attach our DC to the view and render region... if (pMaskRegion->AttachDevice(pView, NULL, pSpread)) { pMaskRegion->StartRender(); // We must save & restore the attribute state around all our rendering because // attributes otherwise stay on the renderstack until we delete the RndRgn, and as our // ones are on the program stack, they will have ceased to exist before then, which // makes for a wicked explosion. pMaskRegion->SaveContext(); ///////////////////////////////////////////////////////////////////////////////////// // --- Main Airbrush rendering loop // Make sure we've got an intensity function to use. This will create a new one if necessary ValueFunction *pvValueFunction = GetIntensityFunction(); if (pvValueFunction == NULL) { ERROR3("Failed to set an intensity function on an airbrush stroke"); pRender->DrawPath(pPath, this, ShapePath); return; } if(!RenderAirBrush(pPath, pMaskRegion, LineWidth, NumSteps, pvValueFunction, pRender, ShapePath)) { // Airbrush failed - just render the path without the airbrush effect pRender->DrawPath(pPath, this, ShapePath); return; } pMaskRegion->RestoreContext(); // --- ClipRect test code ///////////////////////////////////////////////////////////////////////////////////// // --- We have drawn the airbrushed stroke - now, if the path is filled, we // will render the filled area, so that in semi-transparent cases, the // stroke will not "show through" from behind the filled area. if (pPath->IsFilled) { ColourFillAttribute *pCFAttr = (ColourFillAttribute *) pRender->GetCurrentAttribute(ATTR_FILLGEOMETRY); if (pCFAttr != NULL && (!pCFAttr->Colour.IsTransparent() || pCFAttr->IsABitmapFill())) { PathIsFilled = TRUE; pMaskRegion->SaveContext(); ColourFillAttribute *pFillAttr = NULL; FillMappingAttribute *pMapAttr = NULL; // Obtain the object's transparent fill geometry TranspFillAttribute *pTransAttr = (TranspFillAttribute *) pRender->GetCurrentAttribute(ATTR_TRANSPFILLGEOMETRY); if (pTransAttr != NULL) { // Get a non-transparent version of the fill geometry pFillAttr = pTransAttr->MakeSimilarNonTranspFillGeometry(1.0); // Convert a fill mapping TranspFillMappingAttribute *pTransMapAttr = (TranspFillMappingAttribute *) pRender->GetCurrentAttribute(ATTR_TRANSPFILLMAPPING); if(pTransMapAttr != NULL) pMapAttr = pTransMapAttr->MakeSimilarNonTranspFillMapping(); } // Setup region and draw path into it if (pFillAttr != NULL) { pMaskRegion->SetFillGeometry(pFillAttr, TRUE); if(pMapAttr != NULL) pMaskRegion->SetFillMapping(pMapAttr, TRUE); } else pMaskRegion->SetFillColour(DocColour(0, 0, 0)); pMaskRegion->SetLineColour(DocColour(COLOUR_TRANS)); pMaskRegion->DrawPath(pPath, NULL, ShapePath); pMaskRegion->RestoreContext(); } } pMaskRegion->StopRender(); } pMaskRegion->StopUsingGreyscaleContextDangerous(); } // Extract the transparency mask bitmap from the render region OILBitmap *pOilBmp = pMaskRegion->ExtractBitmap(); // We no longer need the RenderRegion, so scrap it. delete pMaskRegion; pMaskRegion = NULL; pPalette = NULL; // Now, render a rectangle to the output render region, using the transparency mask if (pOilBmp == NULL) return; KernelBitmap *pMask = new KernelBitmap(pOilBmp, TRUE); if (pMask != NULL) { // Make sure the bitmap knows it's already a greyscale, else it will spend a lot of // time "converting" itself to a greyscale, and what's more, corrupting the grey levels // so that 255 (invisible) becomes 254 (slightly visible). Arrrrrgh! pMask->SetAsGreyscale(); // Create a transparency attribute from our mask bitmap BitmapTranspFillAttribute Trans; // We don't call pTrans->AttachBitmap because it seems to be stupid, and causes ructions // when we try to attach a temporary bitmap. We thus do the same thing, but avoiding // its attempts to automatically screw us about. Trans.BitmapRef.Detach(); Trans.BitmapRef.SetBitmap(pMask); Trans.SetStartPoint(&ClipRegion.lo); DocCoord EndPoint(ClipRegion.hi.x, ClipRegion.lo.y); Trans.SetEndPoint(&EndPoint); DocCoord EndPoint2(ClipRegion.lo.x, ClipRegion.hi.y); Trans.SetEndPoint2(&EndPoint2); UINT32 TValue = 0; Trans.SetStartTransp(&TValue); TValue = 255; Trans.SetEndTransp(&TValue); // Use the same transparency type as is set on the object being rendered (if any) { TranspFillAttribute *pTransAttr = (TranspFillAttribute *) pRender->GetCurrentAttribute(ATTR_TRANSPFILLGEOMETRY); if (pTransAttr != NULL) Trans.SetTranspType(pTransAttr->GetTranspType()); else Trans.SetTranspType(TT_Mix); // By default, we'll use Mix transparency } // --- OK, we finally got here! Render the stroke, using the transparency mask we just made pRender->SaveContext(); Trans.Render(pRender); // Render the path. If it is filled, then we render the entire thing (fill & stroke) using // the current fill geometry (to get a shadow/feather effect) if (PathIsFilled) { // Render the entire thing (fill & stroke) in one go. We render a rectangle over the cliprect // so that we do everything in one go (we can't render the fill &7 stroke separately, or // the transparency will overlap & it'll look wrong) pRender->SetLineColour(DocColour(COLOUR_TRANS)); // Don't render a line Path Rect; Rect.Initialise(); Rect.AddMoveTo(ClipRegion.lo); Rect.AddLineTo(DocCoord(ClipRegion.hix, ClipRegion.loy)); Rect.AddLineTo(ClipRegion.hi); Rect.AddLineTo(DocCoord(ClipRegion.lox, ClipRegion.hiy)); Rect.AddLineTo(ClipRegion.lo); Rect.IsFilled = TRUE; Rect.IsStroked = FALSE; pRender->DrawPath(&Rect, this, ShapePath); } else { // Otherwise, create a filled-outline path for the entire stroke, and render it // !!!!****ToDo - for now, strokes always render flat-filled with the stroke colour StrokeColourAttribute *pStrokeColour = (StrokeColourAttribute *) pRender->GetCurrentAttribute(ATTR_STROKECOLOUR); if (pStrokeColour != NULL) pRender->SetFillColour(pStrokeColour->Colour); // Fill the holes pRender->SetWindingRule(NonZeroWinding); Path *pOutput = CreateVarWidthStroke(pPath, pRender, LineWidth); if (pOutput != NULL) { pRender->DrawPath(pOutput, NULL, ShapePath); delete pOutput; pOutput = NULL; } } pRender->RestoreContext(); // Delete the kernel bitmap. This auto-deletes the OIL bitmap for us delete pMask; } #endif }
BOOL ProcessPathDistance::GetCoordAndTangent(DocCoord* pCoord, double* pTangent, BOOL* pFound, double Dist, Path* pPath, UINT32* pPressure) { ERROR2IF(pCoord==NULL && pTangent==NULL,FALSE,"ProcessPathDistance::GetCoordAndTangent() - no output pointers specified!"); ERROR2IF(pFound==NULL,FALSE,"ProcessPathDistance::GetCoordAndTangent() - pFound==NULL"); ERROR2IF( pPath==NULL,FALSE,"ProcessPathDistance::GetCoordAndTangent() - pPath==NULL"); DesiredDist = Dist; CurrentDist = 0; Found = FALSE; CoordAtDist = DocCoord(0,0); TangentAtDist = 0; PressureAtDist = 0; // set up the processpath process. ProcessFlags PFlags; BOOL ok=ProcessPath::Init(pPath); if (ok) ok= Process(PFlags, 0); //ProcessPath::Process(PFlags); if (ok) { if (Found==FALSE) { // get last 2 points on line DocCoord* pPathCoords=pPath->GetCoordArray(); ERROR2IF(pPathCoords==NULL,FALSE,"ProcessPathDistance::GetCoordAndTangent() - pPathCoords==NULL"); INT32 NumPathCoords=pPath->GetNumCoords(); ERROR2IF(NumPathCoords<2,FALSE,"ProcessPathDistance::GetCoordAndTangent() - NumPathCoords < 2"); DocCoord LastCoord=pPathCoords[NumPathCoords-1]; DocCoord PrevCoord=pPathCoords[NumPathCoords-2]; double dx=LastCoord.x-PrevCoord.x; double dy=LastCoord.y-PrevCoord.y; double LineLength=sqrt(dx*dx+dy*dy); if (LineLength>0) { double FractOfLine = (DesiredDist-CurrentDist)/LineLength; double x = LastCoord.x+dx*FractOfLine; double y = LastCoord.y+dy*FractOfLine; CoordAtDist = DocCoord((MILLIPOINT)x,(MILLIPOINT)y); TangentAtDist = atan2(dy,dx); } else { CoordAtDist = LastCoord; TangentAtDist = 0; } } else if (Dist<0) Found=FALSE; // if not actually on path, flag not found on path *pFound = Found; if (pCoord) *pCoord = CoordAtDist; if (pTangent) *pTangent = TangentAtDist; if (pPressure != NULL) { *pPressure = PressureAtDist; // TRACEUSER( "Diccon", _T("Pressure At Dist = %d\n"), PressureAtDist); } } return ok; }