function drawTitle(gd, ax) {
    var fullLayout = gd._fullLayout;
    var axId = ax._id;
    var axLetter = axId.charAt(0);
    var fontSize = ax.title.font.size;
    var titleStandoff;
    var extraLines = (ax.title.text.match(svgTextUtils.BR_TAG_ALL) || []).length;

    if(ax.title.hasOwnProperty('standoff')) {
        // With ax._depth the initial drawing baseline is at the outer axis border (where the
        // ticklabels are drawn). Since the title text will be drawn above the baseline,
        // bottom/right axes must be shifted by 1 text line to draw below ticklabels instead of on
        // top of them, whereas for top/left axes, the first line would be drawn
        // before the ticklabels, but we need an offset for the descender portion of the first line
        // and all subsequent lines.
        if(ax.side === 'bottom' || ax.side === 'right') {
            titleStandoff = ax._depth + ax.title.standoff + fontSize * CAP_SHIFT;
        } else if(ax.side === 'top' || ax.side === 'left') {
            titleStandoff = ax._depth + ax.title.standoff + fontSize * (MID_SHIFT + (extraLines * LINE_SPACING));
        }
    } else {
        var isInside = insideTicklabelposition(ax);

        if(ax.type === 'multicategory') {
            titleStandoff = ax._depth;
        } else {
            var offsetBase = 1.5 * fontSize;
            if(isInside) {
                offsetBase = 0.5 * fontSize;
                if(ax.ticks === 'outside') {
                    offsetBase += ax.ticklen;
                }
            }
            titleStandoff = 10 + offsetBase + (ax.linewidth ? ax.linewidth - 1 : 0);
        }

        if(!isInside) {
            if(axLetter === 'x') {
                titleStandoff += ax.side === 'top' ?
                    fontSize * (ax.showticklabels ? 1 : 0) :
                    fontSize * (ax.showticklabels ? 1.5 : 0.5);
            } else {
                titleStandoff += ax.side === 'right' ?
                    fontSize * (ax.showticklabels ? 1 : 0.5) :
                    fontSize * (ax.showticklabels ? 0.5 : 0);
            }
        }
    }

    var pos = axes.getPxPosition(gd, ax);
    var transform, x, y;

    if(axLetter === 'x') {
        x = ax._offset + ax._length / 2;
        y = (ax.side === 'top') ? pos - titleStandoff : pos + titleStandoff;
    } else {
        y = ax._offset + ax._length / 2;
        x = (ax.side === 'right') ? pos + titleStandoff : pos - titleStandoff;
        transform = {rotate: '-90', offset: 0};
    }

    var avoid;

    if(ax.type !== 'multicategory') {
        var tickLabels = ax._selections[ax._id + 'tick'];

        avoid = {
            selection: tickLabels,
            side: ax.side
        };

        if(tickLabels && tickLabels.node() && tickLabels.node().parentNode) {
            var translation = Drawing.getTranslate(tickLabels.node().parentNode);
            avoid.offsetLeft = translation.x;
            avoid.offsetTop = translation.y;
        }

        if(ax.title.hasOwnProperty('standoff')) {
            avoid.pad = 0;
        }
    }

    ax._titleStandoff = titleStandoff;

    return Titles.draw(gd, axId + 'title', {
        propContainer: ax,
        propName: ax._name + '.title.text',
        placeholder: fullLayout._dfltTitle[axLetter],
        avoid: avoid,
        transform: transform,
        attributes: {x: x, y: y, 'text-anchor': 'middle'}
    });
}
Draw axis title, compute default standoff if necessary

@param {DOM element} gd
@param {object} ax (full) axis object
 - {string} _id
 - {string} _name
 - {string} side
 - {number} title.font.size
 - {object} _selections

 - {number} _depth
 - {number} title.standoff
 OR
 - {number} linewidth
 - {boolean} showticklabels