/**************************************************************************\ * * Copyright (c) 1999 Microsoft Corporation * * Module Name: * * PathWidener.hpp * * Abstract: * * Class used for Path widening * * Revision History: * * 11/24/99 ikkof * Created it. * \**************************************************************************/ #ifndef _PATHWIDENER_HPP #define _PATHWIDENER_HPP enum GpLineCapMode { LineCapDefaultMode = 0, LineCapDashMode = 1 }; class GpPathWidener { private: // We now use an ObjectTag to determine if the object is valid // instead of using a BOOL. This is much more robust and helps // with debugging. It also enables us to version our objects // more easily with a version number in the ObjectTag. ObjectTag Tag; // Keep this as the 1st value in the object! protected: VOID SetValid(BOOL valid) { Tag = valid ? ObjectTagPathWidener : ObjectTagInvalid; } public: GpPathWidener( const GpPointF* points, const BYTE* types, INT count, const DpPen* pen, const GpMatrix* matrix, REAL dpiX, REAL dpiY, BOOL isAntiAliased, BOOL isInsetPen = FALSE ) { Initialize( points, types, count, pen, matrix, dpiX, dpiY, isAntiAliased, isInsetPen ); } GpPathWidener( GpPath *path, const DpPen* pen, const GpMatrix* matrix, REAL dpiX, REAL dpiY, BOOL isAntiAliased, BOOL isInsetPen = FALSE ) { const GpPointF* points = path->GetPathPoints(); const BYTE* types = path->GetPathTypes(); INT count = path->GetPointCount(); Initialize( points, types, count, pen, matrix, dpiX, dpiY, isAntiAliased, isInsetPen ); } GpPathWidener( const GpPointF* points, const BYTE* types, INT count, const DpPen* pen, const GpMatrix* matrix, REAL dpiX, REAL dpiY, BOOL isAntiAliased, BYTE* centerTypesBuffer, GpPointF* centerPointsBuffer, GpPointF* gradientsBuffer, GpPointF* normalsBuffer, BYTE* leftTypesBuffer, GpPointF* leftPointsBuffer, BYTE* rightTypesBuffer, GpPointF* rightPointsBuffer, INT bufferCount, BOOL isInsetPen = FALSE ) : CenterTypes(centerTypesBuffer, bufferCount), CenterPoints(centerPointsBuffer, bufferCount), Gradients(gradientsBuffer, bufferCount), Normals(normalsBuffer, bufferCount), LeftTypes(leftTypesBuffer, bufferCount), LeftPoints(leftPointsBuffer, bufferCount), RightTypes(rightTypesBuffer, bufferCount), RightPoints(rightPointsBuffer, bufferCount) { Initialize(points, types, count, pen, matrix, dpiX, dpiY, isAntiAliased, isInsetPen); } ~GpPathWidener() { SetValid(FALSE); // so we don't use a deleted object } GpStatus Widen( DynPointFArray* widenedPoints, DynByteArray* widenedTypes ); GpStatus Widen(GpPath **path); BOOL IsValid() const { ASSERT((Tag == ObjectTagPathWidener) || (Tag == ObjectTagInvalid)); #if DBG if (Tag == ObjectTagInvalid) { WARNING1("Invalid PathWidener"); } #endif return (Tag == ObjectTagPathWidener); } REAL GetPenDelta(); protected: VOID Initialize( const GpPointF* points, const BYTE* types, INT count, const DpPen* pen, const GpMatrix* matrix, REAL dpiX, REAL dpiY, BOOL isAntiAliased, BOOL isInsetPen = FALSE ); GpStatus WidenSubpath( DynPointFArray* widenedPoints, DynByteArray* widenedTypes, REAL leftWidth, REAL rightWidth, INT startIndex, INT endIndex, BOOL isClosed, GpLineCap startCap, GpLineCap endCap, BOOL useBevelJoinInside ); GpStatus CalculateGradients( INT startIndex, INT endIndex ); GpStatus CalculateNormals( REAL leftWidth, REAL rightWidth ); GpStatus SetPolygonJoin( REAL leftWidth, REAL rightWidth, BOOL isAntialiased ); GpStatus SetStartCapInset( REAL inset ) { Inset1 = inset; return Ok; } GpStatus SetEndCapInset( REAL inset ) { Inset2 = inset; return Ok; } VOID WidenFirstPoint( REAL leftWidth, REAL rightWidth, GpLineJoin lineJoin, REAL miterLimit2, GpPointF* leftPoints, BYTE* leftTypes, INT* addedLeftCount, GpPointF* rightPoints, BYTE* rightTypes, INT* addedRightCount, GpPointF* leftEndPt, GpPointF* rightEndPt, const GpPointF* grad, const GpPointF* norm, const GpPointF* dataPoints, INT dataCount, GpPointF* lastPt, const REAL* firstInsets, INT flag ); GpStatus WidenEachPathType( BYTE pathType, REAL leftWidth, REAL rightWidth, GpLineJoin lineJoin, REAL miterLimit2, GpPointF* leftPoints, BYTE* leftTypes, INT* addedLeftCount, GpPointF* rightPoints, BYTE* rightTypes, INT* addedRightCount, const GpPointF* grad, const GpPointF* norm, const GpPointF* dataPoints, INT dataCount, GpPointF* lastPt, const REAL* lastInsets, INT flag ); GpStatus WidenLinePoints( REAL leftWidth, REAL rightWidth, GpLineJoin lineJoin, REAL miterLimit2, GpPointF* leftPoints, BYTE* leftTypes, INT* addedLeftCount, GpPointF* rightPoints, BYTE* rightTypes, INT* addedRightCount, const GpPointF* grad, const GpPointF* norm, const GpPointF* dataPoints, INT dataCount, GpPointF* lastPt, const REAL* lastInsets, INT flag ); GpStatus WidenBezierPoints( REAL leftWidth, REAL rightWidth, GpLineJoin lineJoin, REAL miterLimit2, GpPointF* leftPoints, BYTE* leftTypes, INT* addedLeftCount, GpPointF* rightPoints, BYTE* rightTypes, INT* addedRightCount, const GpPointF* grad, const GpPointF* norm, const GpPointF* dataPoints, INT dataCount, GpPointF* lastPt, const REAL* lastInsets, INT flag ); GpStatus SetCaps( GpLineCap startCap, GpLineCap endCap, const GpPointF& startPoint, const GpPointF& startGrad, const GpPointF& startNorm, const GpPointF& endPoint, const GpPointF& endGrad, const GpPointF& endNorm, REAL leftWidth, REAL rightWidth, const GpPointF *points, INT pointCount ); GpStatus SetCustomFillCaps( GpCustomLineCap* customStartCap, GpCustomLineCap* customEndCap, const GpPointF& startPoint, const GpPointF& endPoint, REAL leftWidth, REAL rightWidth, const GpPointF *centerPoints, const BYTE *centerTypes, INT centerPointCount, DynPointFArray *startCapPoints, DynPointFArray *endCapPoints, DynByteArray *startCapTypes, DynByteArray *endCapTypes ); GpStatus SetCustomStrokeCaps( GpCustomLineCap* customStartCap, GpCustomLineCap* customEndCap, const GpPointF& startPoint, const GpPointF& endPoint, REAL leftWidth, REAL rightWidth, const GpPointF *centerPoints, const BYTE *centerTypes, INT centerPointCount, DynPointFArray *startCapPoints, DynPointFArray *endCapPoints, DynByteArray *startCapTypes, DynByteArray *endCapTypes ); GpStatus SetRoundCap( const GpPointF& point, const GpPointF& grad, BOOL isStartCap, REAL leftWidth, REAL rightWidth ); GpStatus SetDoubleRoundCap( const GpPointF& point, const GpPointF& grad, BOOL isStartCap, REAL leftWidth, REAL rightWidth ); GpStatus SetTriangleCap( const GpPointF& point, const GpPointF& grad, BOOL isStartCap, REAL leftWidth, REAL rightWidth, const GpPointF *points, INT pointCount ); GpStatus CombineSubpathOutlines( DynPointFArray* widenedPoints, DynByteArray* widenedTypes, BOOL isClosed, BOOL closeStartCap = FALSE, BOOL closeEndCap = FALSE ); GpStatus CombineClosedCaps( DynPointFArray* widenedPoints, DynByteArray* widenedTypes, DynPointFArray *daStartCapPoints, DynPointFArray *daEndCapPoints, DynByteArray *daStartCapTypes, DynByteArray *daEndCapTypes ); GpStatus AddCompoundCaps( DynPointFArray* widenedPoints, DynByteArray* widenedTypes, REAL leftWidth, REAL rightWidth, INT startIndex, INT endIndex, GpLineCap startCap, GpLineCap endCap ); REAL GetSubpathPenMiterDelta(BOOL isClosed); protected: DpPathIterator Iterator; DynByteArray CenterTypes; DynPointFArray CenterPoints; DynPointFArray Gradients; DynPointFArray Normals; DynByteArray LeftTypes; DynPointFArray LeftPoints; DynByteArray RightTypes; DynPointFArray RightPoints; BOOL InsetPenMode; // are we doing inset pen using a center pen. const DpPen* Pen; GpMatrix XForm; GpMatrix InvXForm; REAL UnitScale; // Scale factor for Page to Device units REAL StrokeWidth; REAL OriginalStrokeWidth; // StrokeWidth is clamped to a minimum value // but OriginalStrokeWidth is actual transformed // pen width. REAL MinimumWidth; REAL MaximumWidth; BOOL IsAntiAliased; BOOL NeedsToTransform; BOOL NeedsToAdjustNormals; REAL DpiX; REAL DpiY; DynPointFArray JoinPolygonPoints; DynRealArray JoinPolygonAngles; // CapTypes1 and CapPoints1 are used for the start cap and left join. DynByteArray CapTypes1; DynPointFArray CapPoints1; REAL Inset1; // Inset value for the starting position. // CapTypes2 and CapPoints2 are used for the end cap and right join. DynByteArray CapTypes2; DynPointFArray CapPoints2; REAL Inset2; // Inset value for the ending position. }; #endif