import { Font as FontDefinition, ParsedFont } from "./font"; import { makeValidator, makeParser } from "../core/properties"; export abstract class Font implements FontDefinition { public static default = undefined; get isItalic(): boolean { return this.fontStyle === FontStyle.ITALIC; } get isBold(): boolean { return this.fontWeight === FontWeight.SEMI_BOLD || this.fontWeight === FontWeight.BOLD || this.fontWeight === "700" || this.fontWeight === FontWeight.EXTRA_BOLD || this.fontWeight === FontWeight.BLACK; } protected constructor( public readonly fontFamily: string, public readonly fontSize: number, public readonly fontStyle: FontStyle, public readonly fontWeight: FontWeight) { } public abstract getAndroidTypeface(): any /* android.graphics.Typeface */; public abstract getUIFont(defaultFont: any /* UIFont */): any /* UIFont */; public abstract withFontFamily(family: string): Font; public abstract withFontStyle(style: string): Font; public abstract withFontWeight(weight: string): Font; public abstract withFontSize(size: number): Font; public static equals(value1: Font, value2: Font): boolean { // both values are falsy if (!value1 && !value2) { return true; } // only one is falsy if (!value1 || !value2) { return false; } return value1.fontFamily === value2.fontFamily && value1.fontSize === value2.fontSize && value1.fontStyle === value2.fontStyle && value1.fontWeight === value2.fontWeight; } } export type FontStyle = "normal" | "italic"; export namespace FontStyle { export const NORMAL: "normal" = "normal"; export const ITALIC: "italic" = "italic"; export const isValid = makeValidator(NORMAL, ITALIC); export const parse = makeParser(isValid); } export type FontWeight = "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900"; export namespace FontWeight { export const THIN: "100" = "100"; export const EXTRA_LIGHT: "200" = "200"; export const LIGHT: "300" = "300"; export const NORMAL: "normal" = "normal"; export const MEDIUM: "500" = "500"; export const SEMI_BOLD: "600" = "600"; export const BOLD: "bold" = "bold"; export const EXTRA_BOLD: "800" = "800"; export const BLACK: "900" = "900"; export const isValid = makeValidator(THIN, EXTRA_LIGHT, LIGHT, NORMAL, "400", MEDIUM, SEMI_BOLD, BOLD, "700", EXTRA_BOLD, BLACK); export const parse = makeParser(isValid); } export function parseFontFamily(value: string): Array { const result = new Array(); if (!value) { return result; } const split = value.split(","); for (let i = 0; i < split.length; i++) { let str = split[i].trim().replace(/['"]+/g, ""); if (str) { result.push(str); } } return result; } export module genericFontFamilies { export const serif = "serif"; export const sansSerif = "sans-serif"; export const monospace = "monospace"; export const system = "system"; } const styles = new Set(); [ FontStyle.NORMAL, FontStyle.ITALIC ].forEach((val, i, a) => styles.add(val)); // http://www.w3schools.com/cssref/pr_font_weight.asp //- normal(same as 400) //- bold(same as 700) //- 100(Thin) (API16 -thin) //- 200(Extra Light / Ultra Light) (API16 -light) //- 300(Light) (API16 -light) //- 400(Normal) //- 500(Medium) (API21 -medium) //- 600(Semi Bold / Demi Bold) (API21 -medium) //- 700(Bold) (API16 -bold) //- 800(Extra Bold / Ultra Bold) (API16 -bold) //- 900(Black / Heavy) (API21 -black) const weights = new Set(); [ FontWeight.THIN, FontWeight.EXTRA_LIGHT, FontWeight.LIGHT, FontWeight.NORMAL, "400", FontWeight.MEDIUM, FontWeight.SEMI_BOLD, FontWeight.BOLD, "700", FontWeight.EXTRA_BOLD, FontWeight.BLACK ].forEach((val, i, a) => weights.add(val)); export function parseFont(fontValue: string): ParsedFont { let result: ParsedFont = { fontStyle: "normal", fontVariant: "normal", fontWeight: "normal" }; const parts = fontValue.split(/\s+/); let part: string; while (part = parts.shift()) { if (part === "normal") { // nothing to do here } else if (part === "small-caps") { // The only supported font variant in shorthand font result.fontVariant = part; } else if (styles.has(part)) { result.fontStyle = part; } else if (weights.has(part)) { result.fontWeight = part; } else if (!result.fontSize) { let sizes = part.split("/"); result.fontSize = sizes[0]; result.lineHeight = sizes.length > 1 ? sizes[1] : undefined; } else { result.fontFamily = part; if (parts.length) { result.fontFamily += " " + parts.join(" "); } break; } } return result; }