TextBlock outlineWidth

Hello all. I have put together a little PG showing my issue.

https://www.babylonjs-playground.com/#Y60HER#25

I have a TextBlock added to an AdvancedDynamicTexture.

The issue I am seeing is this: when I add the yellow outline it writes adds yellow pixels around the base font, effectively filling in the spacing between the font. You can see this by setting text.outlineWidth to 0, 3 and then 12.

What I am hoping to be able to do is to retain the existing edge of the base font, and instead write the yellow pixels inside that edge, retaining the spacing between characters.

thanks

Sounds like you want an inner shadow/stroke? Something in photoshop if I recall.

Would be cool if setting a negative outlineWidth did the drawing from the inside. (It doesn’t currently) A solution I can think of would be to have separate textBlocks in your own stack panel. That way you can control the spacing to how you like and retainer outlineWidths to mimic what you’re going for.

Correct. It’s in photoshop and also in Unity.

Agreed it would be cool to have negative values accomplish this. I actually tried this just to make sure it didn’t work. I’ll look at adding the functionality myself. Thanks for taking the time to reply.

1 Like

Hello! @JakeMN if you do end up adding the functionality we’d love to see it as a PR, if it’s possible for you :smiley:

1 Like

Well, I didn’t go that route since I found out another way to do it. Unfortunately that method requires you to be able to modify the .ttf file, so it does add complexity. I wound up adding functionality to my local copy of babylon.js that adds support for stroked and shadowed text rendering. I have added them here for use if anyone wants them. Given these two I was able to achieve the effect of a double stroked and shadowed text field that matched exactly what I was needing.

// added by JakeMN
    DynamicTexture.prototype.drawTextStroked = function (text, x, y, font, color, strokeColor, strokeWidth, clearColor, invertY, update) {
        if (update === void 0) { update = true; }
        var size = this.getSize();
        if (clearColor) {
            this._context.fillStyle = clearColor;
            this._context.fillRect(0, 0, size.width, size.height);
        }
        this._context.font = font;
        if (x === null || x === undefined) {
            var textSize = this._context.measureText(text);
            x = (size.width - textSize.width) / 2;
        }
        if (y === null || y === undefined) {
            var fontSize = parseInt((font.replace(/\D/g, '')));
            y = (size.height / 2) + (fontSize / 3.65);
        }

        this._context.strokeStyle = strokeColor;
        this._context.lineWidth = strokeWidth;
        this._context.strokeText(text, x, y);

        this._context.fillStyle = color || "";
        this._context.fillText(text, x, y);

        if (update) {
            this.update(invertY);
        }
    };

    // added by JakeMN
    DynamicTexture.prototype.drawTextDrop = function (text, x, y, font, color, dropColor, dropBlur, dropOffX, dropOffY, clearColor, invertY, update) {
        if (update === void 0) { update = true; }
        var size = this.getSize();
        if (clearColor) {
            this._context.fillStyle = clearColor;
            this._context.fillRect(0, 0, size.width, size.height);
        }
        this._context.font = font;
        if (x === null || x === undefined) {
            var textSize = this._context.measureText(text);
            x = (size.width - textSize.width) / 2;
        }
        if (y === null || y === undefined) {
            var fontSize = parseInt((font.replace(/\D/g, '')));
            y = (size.height / 2) + (fontSize / 3.65);
        }

        this._context.shadowColor = dropColor;
        this._context.shadowBlur  = dropBlur;
        this._context.shadowOffsetY  = dropOffY;
        this._context.shadowOffsetX  = dropOffX;

        this._context.fillStyle = color || "";
        this._context.fillText(text, x, y);

        if (update) {
            this.update(invertY);
        }
    };
2 Likes