diff --git a/src/pixie/contexts.nim b/src/pixie/contexts.nim index 7ba9e4a..b3f029d 100644 --- a/src/pixie/contexts.nim +++ b/src/pixie/contexts.nim @@ -7,6 +7,15 @@ import bumpy, chroma, pixie/common, pixie/fonts, pixie/images, pixie/masks, ## https://developer.mozilla.org/en-US/docs/Web/API/ContextRenderingContext2D type + + BaseLineAlignment* = enum + TopBaseAlign + HangingBaseAlign + MiddleBaseAlign + AlphabeticBaseAlign + IdeographicBaseAlign + BottomBaseAlign + Context* = ref object image*: Image fillStyle*, strokeStyle*: Paint @@ -18,6 +27,7 @@ type font*: string ## File path to a .ttf or .otf file. fontSize*: float32 textAlign*: HorizontalAlignment + textBaseline*: BaseLineAlignment lineDash: seq[float32] path: Path mat: Mat3 @@ -58,6 +68,7 @@ proc newContext*(image: Image): Context {.raises: [].} = result.strokeStyle = newPaint(SolidPaint) result.strokeStyle.color = color(0, 0, 0, 1) result.fontSize = 12 + result.textBaseline = AlphabeticBaseAlign proc newContext*(width, height: int): Context {.inline, raises: [PixieError].} = ## Create a new Context that will draw to a new image of width and height. @@ -185,7 +196,22 @@ proc fillText(ctx: Context, image: Image, text: string, at: Vec2) = # Canvas positions text relative to the alphabetic baseline by default var at = at - at.y -= round(font.typeface.ascent * font.scale) + + case ctx.textBaseline: + of TopBaseAlign: + at.y += 0 + of HangingBaseAlign: + # TODO: make accurate (Used by Tibetan and other Indic scripts.) + at.y += 0 + of MiddleBaseAlign: + at.y -= round((font.typeface.ascent - font.typeface.descent) / 2 * font.scale) + of AlphabeticBaseAlign: + at.y -= round(font.typeface.ascent * font.scale) + of IdeographicBaseAlign: + # TODO: make accurate (Used by Chinese, Japanese, and Korean scripts.) + at.y -= round((font.typeface.ascent - font.typeface.descent) * font.scale) + of BottomBaseAlign: + at.y -= round((font.typeface.ascent - font.typeface.descent) * font.scale) font.paint = ctx.fillStyle diff --git a/tests/contexts/textBaseline_1.png b/tests/contexts/textBaseline_1.png new file mode 100644 index 0000000..628d120 Binary files /dev/null and b/tests/contexts/textBaseline_1.png differ diff --git a/tests/test_contexts.nim b/tests/test_contexts.nim index ae4bac4..4330643 100644 --- a/tests/test_contexts.nim +++ b/tests/test_contexts.nim @@ -644,3 +644,34 @@ block: ctx.restore() ctx.fillRect(0, 0, ctx.image.width.float32, ctx.image.height.float32) ctx.image.writeFile("tests/contexts/paintSaveRestore.png") + +block: + # From https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textBaseline + let + image = newImage(550, 500) + ctx = newContext(image) + image.fill(rgba(255, 255, 255, 255)) + + const baselines = @[ + TopBaseAlign, + HangingBaseAlign, + MiddleBaseAlign, + AlphabeticBaseAlign, + IdeographicBaseAlign, + BottomBaseAlign, + ] + + ctx.font = "tests/fonts/Roboto-Regular_1.ttf" + ctx.fontSize = 28 + ctx.strokeStyle = "red" + + for index, baseline in baselines: + ctx.textBaseline = baseline + let y = (75 + index * 75).float32 + ctx.beginPath() + ctx.moveTo(0, y + 0.5) + ctx.lineTo(550, y + 0.5) + ctx.stroke() + ctx.fillText("Abcdefghijklmnop (" & $baseline & ")", 0, y) + + ctx.image.writeFile("tests/contexts/textBaseline_1.png")