PathElement[] getUnderlineShape(int from, int to) {
        // get a Path for the text underline
        List<PathElement> result = new ArrayList<>();
        
        PathElement[] shape = rangeShape( from, to );
        // The shape is a closed Path for one or more rectangles AROUND the selected text. 
        // shape: [MoveTo origin, LineTo top R, LineTo bottom R, LineTo bottom L, LineTo origin, *]

        // Extract the bottom left and right coordinates for each rectangle to get the underline path.
        for ( int ele = 2; ele < shape.length; ele += 5 )
        {
            LineTo bl = (LineTo) shape[ele+1];
            LineTo br = (LineTo) shape[ele];
            double y = br.getY() - 2.5;
            
            result.add( new MoveTo( bl.getX(), y ) );
            result.add( new LineTo( br.getX(), y ) );
        }

        return result.toArray(new PathElement[0]);
    }
PathElement [ ] getUnderlineShape ( int from , int to ) { List < PathElement > result = new ArrayList < > ( ) ; PathElement [ ] shape = rangeShape ( from , to ) ; for ( int ele = 2 ; ele < shape . length ; ele += 5 ) { LineTo bl = ( LineTo ) shape [ ele + 1 ] ; LineTo br = ( LineTo ) shape [ ele ] ; double y = br . getY ( ) - 2.5 ; result . add ( new MoveTo ( bl . getX ( ) , y ) ) ; result . add ( new LineTo ( br . getX ( ) , y ) ) ; } return result . toArray ( new PathElement [ 0 ] ) ; }
@param from The index of the first character.
@param to The index of the last character.
@return An array with the PathElement objects which define an
underline from the first to the last character.