@@ -583,19 +583,18 @@ private static int EncodePath(
583583 out int lineCount ,
584584 out int pathSegmentCount )
585585 {
586- Rectangle interest = command . RasterizerOptions . Interest ;
587586 float samplingOffset = command . RasterizerOptions . SamplingOrigin == RasterizerSamplingOrigin . PixelCenter ? 0.5F : 0F ;
588- float targetOffsetX = command . TargetBounds . X - rootTargetBounds . X ;
589- float targetOffsetY = command . TargetBounds . Y - rootTargetBounds . Y ;
590- float translateX = targetOffsetX + command . DestinationRegion . X - command . SourceOffset . X ;
591- float translateY = targetOffsetY + command . DestinationRegion . Y - command . SourceOffset . Y ;
592-
593- // Move path points from interest-local coverage space into target-local space.
594- float pointTranslateX = translateX + samplingOffset - interest . Left ;
595- float pointTranslateY = translateY + samplingOffset - interest . Top ;
587+ float pointTranslateX = ( command . DestinationOffset . X - rootTargetBounds . X ) + samplingOffset ;
588+ float pointTranslateY = ( command . DestinationOffset . Y - rootTargetBounds . Y ) + samplingOffset ;
596589 pathSegmentCount = 0 ;
597590 lineCount = 0 ;
598591
592+ // Prepared path points stay in the command's own path space until backend encoding.
593+ // Ordinary shapes often already live in target coordinates, but text glyphs are emitted
594+ // as local outlines plus a separate DestinationOffset. We therefore place every point by
595+ // applying the command's absolute destination offset directly rather than trying to
596+ // reconstruct placement from Interest/DestinationRegion/SourceOffset, which are clipping
597+ // artifacts in absolute destination space and can cancel the text offset entirely.
599598 // The lowered geometry is already contour-ordered, so the encoder walks the segment
600599 // stream once and emits each contour as: starting point, then one end point per segment.
601600 SegmentEnumerator segments = geometry . GetSegments ( ) ;
@@ -625,8 +624,8 @@ private static int EncodePath(
625624 pathTags . Add ( PathTagLineToF32 ) ;
626625 pathSegmentCount ++ ;
627626
628- float y0 = ( ( segment . Start . Y - interest . Top ) + samplingOffset ) + translateY ;
629- float y1 = ( ( segment . End . Y - interest . Top ) + samplingOffset ) + translateY ;
627+ float y0 = segment . Start . Y + pointTranslateY ;
628+ float y1 = segment . End . Y + pointTranslateY ;
630629 int fy0 = ( int ) MathF . Round ( y0 * FixedOne ) ;
631630 int fy1 = ( int ) MathF . Round ( y1 * FixedOne ) ;
632631 if ( fy0 != fy1 )
0 commit comments