UNPKG

cheetah-grid

Version:

Cheetah Grid is a high performance grid engine that works on canvas

112 lines (106 loc) 2.68 kB
import type { RectProps } from "../ts-types"; export type PaddingOption = { left?: number; right?: number; top?: number; bottom?: number; }; const fontSizeCache: { [key: string]: { width: number; height: number; }; } = {}; export function getFontSize( ctx: CanvasRenderingContext2D, font: string | null | undefined ): { width: number; height: number; } { const fontName = font || ctx.font; if (fontSizeCache[fontName]) { return fontSizeCache[fontName]; } const bk = ctx.font; // To calculate the size of the letters correctly, letterSpacing must be 'normal'. // `ctx.letterSpacing` is not used yet because it is Baseline 2024. ctx.canvas.style.letterSpacing = "normal"; try { ctx.font = fontName; const em = ctx.measureText("あ").width; return (fontSizeCache[fontName] = { width: em, height: em, }); } finally { ctx.canvas.style.letterSpacing = ""; ctx.font = bk; } } export function calcBasePosition( ctx: CanvasRenderingContext2D, rect: RectProps, { offset = 0, padding: { left: paddingLeft = 0, right: paddingRight = 0, top: paddingTop = 0, bottom: paddingBottom = 0, } = {}, }: { offset?: number; padding?: PaddingOption; } = {} ): { x: number; y: number } { return calcStartPosition(ctx, rect, 0, 0, { offset, padding: { left: paddingLeft, right: paddingRight, top: paddingTop, bottom: paddingBottom, }, }); } export function calcStartPosition( ctx: CanvasRenderingContext2D, rect: RectProps, width: number, height: number, { offset = 0, padding: { left: paddingLeft = 0, right: paddingRight = 0, top: paddingTop = 0, bottom: paddingBottom = 0, } = {}, }: { offset?: number; padding?: PaddingOption; } = {} ): { x: number; y: number } { const textAlign = ctx.textAlign || "left"; const textBaseline = ctx.textBaseline || "middle"; ctx.textAlign = textAlign; ctx.textBaseline = textBaseline; let x = rect.left + offset + paddingLeft; if (textAlign === "right" || textAlign === "end") { x = rect.right - width - offset - paddingRight; } else if (textAlign === "center") { x = rect.left + (rect.width - width + paddingLeft - paddingRight) / 2; } let y = rect.top + offset + paddingTop; if ( textBaseline === "bottom" || textBaseline === "alphabetic" || textBaseline === "ideographic" ) { y = rect.bottom - height - offset - paddingBottom; } else if (textBaseline === "middle") { y = rect.top + (rect.height - height + paddingTop - paddingBottom) / 2; } return { x, y }; }