code: private void render(SVG.Text obj)
     {
        debug("Text render");
  
        updateStyleForElement(state, obj);
  
        if (!display())
           return;
  
        if (obj.transform != null)
           canvas.concat(obj.transform);
  
        // Get the first coordinate pair from the lists in the x and y properties.
        float  x = (obj.x == null || obj.x.size() == 0) ? 0f : obj.x.get(0).floatValueX(this);
        float  y = (obj.y == null || obj.y.size() == 0) ? 0f : obj.y.get(0).floatValueY(this);
        float  dx = (obj.dx == null || obj.dx.size() == 0) ? 0f : obj.dx.get(0).floatValueX(this);
        float  dy = (obj.dy == null || obj.dy.size() == 0) ? 0f : obj.dy.get(0).floatValueY(this);
  
        // Handle text alignment
        Style.TextAnchor  anchor = getAnchorPosition();
        if (anchor != Style.TextAnchor.Start) {
           float  textWidth = calculateTextWidth(obj);
           if (anchor == Style.TextAnchor.Middle) {
              x -= (textWidth / 2);
           } else {
              x -= textWidth;  // 'End' (right justify)
           }
        }
  
        if (obj.boundingBox == null) {
           TextBoundsCalculator  proc = new TextBoundsCalculator(x, y);
           enumerateTextSpans(obj, proc);
           obj.boundingBox = new Box(proc.bbox.left, proc.bbox.top, proc.bbox.width(), proc.bbox.height());
        }
        updateParentBoundingBox(obj);
  
        checkForGradientsAndPatterns(obj);
        checkForClipPath(obj);
        
        boolean  compositing = pushLayer();
  
        enumerateTextSpans(obj, new PlainTextDrawer(x + dx, y + dy));
  
        if (compositing)
           popLayer(obj);
     }
docs: ==============================================================================