mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-16 03:31:45 +08:00
Merge pull request #1978 from NativeScript/font-weight
Add support for CSS font-weight + sample app for testing fonts
This commit is contained in:
@ -1,62 +1,178 @@
|
|||||||
import { View } from "ui/core/view";
|
import { View } from "ui/core/view";
|
||||||
import { EventData } from "data/observable";
|
import { Page, NavigatedData } from "ui/page";
|
||||||
import { LayoutBase } from "ui/layouts/layout-base";
|
import { StackLayout } from "ui/layouts/stack-layout";
|
||||||
|
import { ScrollView } from "ui/scroll-view";
|
||||||
import { Label } from "ui/label";
|
import { Label } from "ui/label";
|
||||||
import { TextField } from "ui/text-field";
|
|
||||||
import { TextView } from "ui/text-view";
|
|
||||||
import { Button } from "ui/button";
|
|
||||||
import { FontStyle, FontWeight } from "ui/enums";
|
import { FontStyle, FontWeight } from "ui/enums";
|
||||||
import typeUtils = require("utils/types");
|
import typeUtils = require("utils/types");
|
||||||
import { Color } from "color";
|
import { Color } from "color";
|
||||||
|
import * as font from "ui/styling/font";
|
||||||
|
|
||||||
const fontFamilies = ["system", "sans-serif", "serif", "monospace"];
|
const genericFontFamilies = [
|
||||||
const fontWeights = [FontWeight.normal, FontWeight.bold];
|
"system",
|
||||||
const fontStyles = [FontStyle.normal, FontStyle.italic];
|
"sans-serif",
|
||||||
|
"serif",
|
||||||
|
"monospace",
|
||||||
|
];
|
||||||
|
var fontFamilies = [];
|
||||||
|
var fontNames = [];
|
||||||
|
const embeddedFontNames = [
|
||||||
|
"Entypo",
|
||||||
|
"EvilIcons",
|
||||||
|
"FontAwesome",
|
||||||
|
"Ionicons",
|
||||||
|
"Material-Design-Iconic-Font",
|
||||||
|
"MaterialIcons",
|
||||||
|
];
|
||||||
|
const fontStyles = [
|
||||||
|
FontStyle.normal,
|
||||||
|
FontStyle.italic
|
||||||
|
];
|
||||||
|
const fontWeights = [
|
||||||
|
FontWeight.thin,
|
||||||
|
FontWeight.extraLight,
|
||||||
|
FontWeight.light,
|
||||||
|
FontWeight.normal,
|
||||||
|
FontWeight.medium,
|
||||||
|
FontWeight.semiBold,
|
||||||
|
FontWeight.bold,
|
||||||
|
FontWeight.extraBold,
|
||||||
|
FontWeight.black,
|
||||||
|
];
|
||||||
|
|
||||||
export function onStackLayoutLoaded(args: EventData) {
|
var green = new Color("Green");
|
||||||
var layout = <LayoutBase>args.object;
|
var red = new Color("Red");
|
||||||
_generateViews(() => { return new Label(); }, layout);
|
var white = new Color("White");
|
||||||
_generateViews(() => { return new TextField(); }, layout);
|
var black = new Color("Black");
|
||||||
_generateViews(() => { return new TextView(); }, layout);
|
|
||||||
_generateViews(() => { return new Button(); }, layout);
|
var compareIgnoreCase = function (a, b) {
|
||||||
|
return a.toLowerCase().localeCompare(b.toLowerCase());
|
||||||
|
};
|
||||||
|
|
||||||
|
if (font.ios) {
|
||||||
|
for (var f = 0; f < embeddedFontNames.length; f++) {
|
||||||
|
font.ios.registerFont(`fonts/${embeddedFontNames[f]}.ttf`);
|
||||||
|
}
|
||||||
|
|
||||||
|
var font_internal = <any>font;
|
||||||
|
font_internal.ensureSystemFontSets();
|
||||||
|
|
||||||
|
(<Set<string>>font_internal.systemFontFamilies).forEach(f => fontFamilies.push(f));
|
||||||
|
fontFamilies = fontFamilies.sort(compareIgnoreCase);
|
||||||
|
|
||||||
|
(<Set<string>>font_internal.systemFonts).forEach(f => fontNames.push(f));
|
||||||
|
fontNames = fontNames.sort(compareIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _generateViews(factory: () => View, layout: LayoutBase) {
|
export function onPageLoaded(args: NavigatedData) {
|
||||||
for (var f = 0; f < fontFamilies.length; f++) {
|
var page = <Page>args.object;
|
||||||
for (var w = 0; w < fontWeights.length; w++) {
|
var scrollView = new ScrollView();
|
||||||
for (var s = 0; s < fontStyles.length; s++) {
|
var stackLayout = new StackLayout();
|
||||||
var view = factory();
|
generateLabels(stackLayout);
|
||||||
var css = `font-family: ${fontFamilies[f]}; font-weight: ${fontWeights[w]}; font-style: ${fontStyles[s]};`;
|
scrollView.content = stackLayout;
|
||||||
(<any>view).text = `${typeUtils.getClass(view)} ${css}`;
|
page.content = scrollView;
|
||||||
(<any>view).textWrap = true;
|
}
|
||||||
view.style.textAlignment = "left";
|
|
||||||
view.setInlineStyle(css);
|
function generateLabels(layout: StackLayout) {
|
||||||
view.margin = "1 0";
|
layout.addChild(prepareTitle("Generic Font Families", 24));
|
||||||
view.borderWidth = 1;
|
for (var f = 0; f < genericFontFamilies.length; f++) {
|
||||||
view.height = 75;
|
layout.addChild(prepareTitle(genericFontFamilies[f], 20));
|
||||||
view.color = new Color("Black");
|
for (var s = 0; s < fontStyles.length; s++) {
|
||||||
view.backgroundColor = new Color("LightGray");
|
for (var w = 0; w < fontWeights.length; w++) {
|
||||||
view.on("loaded", args => {
|
var view = prepareLabel(genericFontFamilies[f], fontStyles[s], fontWeights[w]);
|
||||||
(<any>view).text += _getFontInfo(view);
|
|
||||||
});
|
|
||||||
layout.addChild(view);
|
layout.addChild(view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function _getFontInfo(view: View): string {
|
if (fontFamilies.length > 0)
|
||||||
if (view.ios) {
|
{
|
||||||
var uiFont: UIFont;
|
layout.addChild(prepareTitle("Font Families", 24));
|
||||||
if (view.ios instanceof UIButton) {
|
}
|
||||||
uiFont = view.ios.titleLabel.font;
|
for (var f = 0; f < fontFamilies.length; f++) {
|
||||||
|
layout.addChild(prepareTitle(fontFamilies[f], 20));
|
||||||
|
for (var s = 0; s < fontStyles.length; s++) {
|
||||||
|
for (var w = 0; w < fontWeights.length; w++) {
|
||||||
|
var view = prepareLabel(fontFamilies[f], fontStyles[s], fontWeights[w]);
|
||||||
|
layout.addChild(view);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (view.ios.font) {
|
|
||||||
uiFont = view.ios.font;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ` ${uiFont.fontName} ${uiFont.pointSize}pt.`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
if (fontNames.length > 0) {
|
||||||
|
layout.addChild(prepareTitle("Phone Fonts", 24));
|
||||||
|
}
|
||||||
|
for (var f = 0; f < fontNames.length; f++) {
|
||||||
|
var view = prepareLabel(fontNames[f], "normal", "normal");
|
||||||
|
layout.addChild(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (embeddedFontNames.length > 0) {
|
||||||
|
layout.addChild(prepareTitle("Embedded Fonts", 24));
|
||||||
|
}
|
||||||
|
for (var f = 0; f < embeddedFontNames.length; f++) {
|
||||||
|
var view = prepareLabel(embeddedFontNames[f], "normal", "normal");
|
||||||
|
layout.addChild(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareTitle(text: string, fontSize: number) {
|
||||||
|
var title = new Label();
|
||||||
|
title.text = text;
|
||||||
|
title.height = 100;
|
||||||
|
title.backgroundColor = black;
|
||||||
|
title.color = white;
|
||||||
|
title.fontSize = fontSize;
|
||||||
|
title.style.fontStyle = "italic";
|
||||||
|
title.borderWidth = 1;
|
||||||
|
title.borderColor = white;
|
||||||
|
title.textAlignment = "center";
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareLabel(fontFamily: string, fontStyle: string, fontWeight: string): View {
|
||||||
|
var label = new Label();
|
||||||
|
label["font-family"] = fontFamily;
|
||||||
|
var fontFamilyCss = `font-family: ${fontFamily}; `;
|
||||||
|
var fontStyleCss = fontStyle !== FontStyle.normal ? `font-style: ${fontStyle}; ` : "";
|
||||||
|
var fontWeightCss = fontWeight !== FontWeight.normal ? `font-weight: ${fontWeight}; ` : "";
|
||||||
|
var css = `${fontFamilyCss}${fontStyleCss}${fontWeightCss}`;
|
||||||
|
label.text = `${typeUtils.getClass(label) } {${css}};`;
|
||||||
|
label.textWrap = true;
|
||||||
|
label.style.textAlignment = "left";
|
||||||
|
label.borderWidth = 1;
|
||||||
|
label.borderColor = black;
|
||||||
|
label.style.padding = "2";
|
||||||
|
label.setInlineStyle(css);
|
||||||
|
label.on("loaded", args => {
|
||||||
|
var sender = <Label>args.object;
|
||||||
|
if (sender.ios) {
|
||||||
|
var uiFont = _getUIFont(label);
|
||||||
|
sender.text += `\niOS Font: ${uiFont.fontName};`;
|
||||||
|
if (genericFontFamilies.indexOf(fontFamily) !== -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (uiFont.fontName.replace(" ", "").indexOf((<string>sender["font-family"]).replace(" ", "")) !== -1) {
|
||||||
|
sender.color = green;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sender.color = red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (fontFamily === "FontAwesome") {
|
||||||
|
label.text += "\uF17B\uF10B";
|
||||||
|
}
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _getUIFont(view: any): UIFont {
|
||||||
|
if (view.ios) {
|
||||||
|
if (view.ios instanceof UIButton) {
|
||||||
|
return view.ios.titleLabel.font;
|
||||||
|
}
|
||||||
|
else if (view.ios.font) {
|
||||||
|
return view.ios.font;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,5 +1,3 @@
|
|||||||
<Page xmlns="http://schemas.nativescript.org/tns.xsd" >
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd"
|
||||||
<ScrollView>
|
loaded="onPageLoaded">
|
||||||
<StackLayout loaded="onStackLayoutLoaded"/>
|
|
||||||
</ScrollView>
|
|
||||||
</Page>
|
</Page>
|
39
ui/enums/enums.d.ts
vendored
39
ui/enums/enums.d.ts
vendored
@ -485,14 +485,49 @@
|
|||||||
*/
|
*/
|
||||||
export module FontWeight {
|
export module FontWeight {
|
||||||
/**
|
/**
|
||||||
* Normal font weight.
|
* Thin font weight. CSS font-weight 100.
|
||||||
|
*/
|
||||||
|
export var thin: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extra-light / Ultra-light font weight. CSS font-weight 200.
|
||||||
|
*/
|
||||||
|
export var extraLight: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Light font weight. CSS font-weight 300.
|
||||||
|
*/
|
||||||
|
export var light: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normal font weight. CSS font-weight 400.
|
||||||
*/
|
*/
|
||||||
export var normal: string;
|
export var normal: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bold font weight.
|
* Medium font weight. CSS font-weight 500.
|
||||||
|
*/
|
||||||
|
export var medium: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Semi-bold / Demi-bold font weight. CSS font-weight 600.
|
||||||
|
*/
|
||||||
|
export var semiBold: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bold font weight. CSS font-weight 700.
|
||||||
*/
|
*/
|
||||||
export var bold: string;
|
export var bold: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extra-bold / Ultra-bold font weight. CSS font-weight 800.
|
||||||
|
*/
|
||||||
|
export var extraBold: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Black font weight. CSS font-weight 900.
|
||||||
|
*/
|
||||||
|
export var black: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -146,8 +146,15 @@ export module FontStyle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export module FontWeight {
|
export module FontWeight {
|
||||||
export var normal: string = "normal";
|
export var thin: string = "100";
|
||||||
export var bold: string = "bold";
|
export var extraLight: string = "200";
|
||||||
|
export var light: string = "300";
|
||||||
|
export var normal: string = "normal"; // 400
|
||||||
|
export var medium: string = "500";
|
||||||
|
export var semiBold: string = "600";
|
||||||
|
export var bold: string = "bold"; // 700
|
||||||
|
export var extraBold: string = "800";
|
||||||
|
export var black: string = "900";
|
||||||
}
|
}
|
||||||
|
|
||||||
export module BackgroundRepeat {
|
export module BackgroundRepeat {
|
||||||
|
@ -39,14 +39,15 @@ export class Font implements definitios.Font {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get isBold(): boolean {
|
get isBold(): boolean {
|
||||||
return this._fontWeight.toLowerCase() === enums.FontWeight.bold;;
|
return this._fontWeight.toLowerCase() === enums.FontWeight.bold
|
||||||
|
|| this._fontWeight.toLowerCase() === "700";
|
||||||
}
|
}
|
||||||
set isBold(value: boolean) {
|
set isBold(value: boolean) {
|
||||||
throw new Error("isBold is read-only");
|
throw new Error("isBold is read-only");
|
||||||
}
|
}
|
||||||
|
|
||||||
get isItalic(): boolean {
|
get isItalic(): boolean {
|
||||||
return this._fontStyle.toLowerCase() === enums.FontStyle.italic;;
|
return this._fontStyle.toLowerCase() === enums.FontStyle.italic;
|
||||||
}
|
}
|
||||||
set isItalic(value: boolean) {
|
set isItalic(value: boolean) {
|
||||||
throw new Error("isItalic is read-only");
|
throw new Error("isItalic is read-only");
|
||||||
@ -135,8 +136,21 @@ export module genericFontFamilies {
|
|||||||
|
|
||||||
var styles = new Set();
|
var styles = new Set();
|
||||||
["italic", "oblique"].forEach((val, i, a) => styles.add(val));
|
["italic", "oblique"].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)
|
||||||
var weights = new Set();
|
var weights = new Set();
|
||||||
["bold", "bolder", "lighter", "100", "200", "300", "400", "500", "600", "700", "800", "900"].forEach((val, i, a) => weights.add(val));
|
["normal", "bold", "100", "200", "300", "400", "500", "600", "700", "800", "900"].forEach((val, i, a) => weights.add(val));
|
||||||
|
|
||||||
interface ParsedFont {
|
interface ParsedFont {
|
||||||
fontStyle?: string;
|
fontStyle?: string;
|
||||||
|
@ -64,102 +64,123 @@ export class Font extends common.Font {
|
|||||||
|
|
||||||
public getAndroidTypeface(): android.graphics.Typeface {
|
public getAndroidTypeface(): android.graphics.Typeface {
|
||||||
if (!this._typeface) {
|
if (!this._typeface) {
|
||||||
var style: number = 0;
|
this._typeface = createTypeface(this);
|
||||||
|
|
||||||
if (this.isBold) {
|
|
||||||
style |= android.graphics.Typeface.BOLD;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isItalic) {
|
|
||||||
style |= android.graphics.Typeface.ITALIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
var typeFace = this.getTypeFace(this.fontFamily);
|
|
||||||
this._typeface = android.graphics.Typeface.create(typeFace, style);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._typeface;
|
return this._typeface;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private getTypeFace(fontFamily: string): android.graphics.Typeface {
|
function loadFontFromFile(fontFamily: string): android.graphics.Typeface {
|
||||||
var fonts = common.parseFontFamily(fontFamily);
|
ensureApplication();
|
||||||
var result = null;
|
|
||||||
if (fonts.length === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < fonts.length; i++) {
|
|
||||||
switch (fonts[i].toLowerCase()) {
|
|
||||||
case common.genericFontFamilies.serif:
|
|
||||||
result = android.graphics.Typeface.SERIF;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case common.genericFontFamilies.sansSerif:
|
|
||||||
result = android.graphics.Typeface.SANS_SERIF;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case common.genericFontFamilies.monospace:
|
|
||||||
result = android.graphics.Typeface.MONOSPACE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case common.genericFontFamilies.system:
|
|
||||||
result = android.graphics.Typeface.DEFAULT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
result = this.loadFontFromFile(fonts[i]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
appAssets = appAssets || application.android.context.getAssets();
|
||||||
|
if (!appAssets) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadFontFromFile(fontFamily: string): android.graphics.Typeface {
|
ensureTypes();
|
||||||
ensureApplication();
|
|
||||||
|
|
||||||
appAssets = appAssets || application.android.context.getAssets();
|
var result = typefaceCache.get(fontFamily);
|
||||||
if (!appAssets) {
|
// Check for undefined explicitly as null mean we tried to load the font, but failed.
|
||||||
return null;
|
if (types.isUndefined(result)) {
|
||||||
|
result = null;
|
||||||
|
|
||||||
|
ensureTrace();
|
||||||
|
ensureFS();
|
||||||
|
|
||||||
|
var fontAssetPath: string;
|
||||||
|
var basePath = fs.path.join(fs.knownFolders.currentApp().path, "fonts", fontFamily);
|
||||||
|
if (fs.File.exists(basePath + ".ttf")) {
|
||||||
|
fontAssetPath = FONTS_BASE_PATH + fontFamily + ".ttf";
|
||||||
|
}
|
||||||
|
else if (fs.File.exists(basePath + ".otf")) {
|
||||||
|
fontAssetPath = FONTS_BASE_PATH + fontFamily + ".otf";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
trace.write("Could not find font file for " + fontFamily, trace.categories.Error, trace.messageType.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
ensureTypes();
|
if (fontAssetPath) {
|
||||||
|
try {
|
||||||
var result = typefaceCache.get(fontFamily);
|
fontAssetPath = fs.path.join(fs.knownFolders.currentApp().path, fontAssetPath);
|
||||||
// Check for undefined explicitly as null mean we tried to load the font, but failed.
|
result = android.graphics.Typeface.createFromFile(fontAssetPath)
|
||||||
if (types.isUndefined(result)) {
|
} catch (e) {
|
||||||
result = null;
|
trace.write("Error loading font asset: " + fontAssetPath, trace.categories.Error, trace.messageType.error);
|
||||||
|
|
||||||
ensureTrace();
|
|
||||||
ensureFS();
|
|
||||||
|
|
||||||
var fontAssetPath: string;
|
|
||||||
var basePath = fs.path.join(fs.knownFolders.currentApp().path, "fonts", fontFamily);
|
|
||||||
if (fs.File.exists(basePath + ".ttf")) {
|
|
||||||
fontAssetPath = FONTS_BASE_PATH + fontFamily + ".ttf";
|
|
||||||
}
|
|
||||||
else if (fs.File.exists(basePath + ".otf")) {
|
|
||||||
fontAssetPath = FONTS_BASE_PATH + fontFamily + ".otf";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
trace.write("Could not find font file for " + fontFamily, trace.categories.Error, trace.messageType.error);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
typefaceCache.set(fontFamily, result);
|
||||||
|
}
|
||||||
|
|
||||||
if (fontAssetPath) {
|
return result;
|
||||||
try {
|
}
|
||||||
fontAssetPath = fs.path.join(fs.knownFolders.currentApp().path, fontAssetPath);
|
|
||||||
result = android.graphics.Typeface.createFromFile(fontAssetPath)
|
function createTypeface(font: Font): android.graphics.Typeface {
|
||||||
} catch (e) {
|
//http://stackoverflow.com/questions/19691530/valid-values-for-androidfontfamily-and-what-they-map-to
|
||||||
trace.write("Error loading font asset: " + fontAssetPath, trace.categories.Error, trace.messageType.error);
|
|
||||||
}
|
var fontStyle = 0;
|
||||||
}
|
if (font.isBold) {
|
||||||
typefaceCache.set(fontFamily, result);
|
fontStyle |= android.graphics.Typeface.BOLD;
|
||||||
|
}
|
||||||
|
if (font.isItalic) {
|
||||||
|
fontStyle |= android.graphics.Typeface.ITALIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fonts = common.parseFontFamily(font.fontFamily);
|
||||||
|
var result = null;
|
||||||
|
if (fonts.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < fonts.length; i++) {
|
||||||
|
switch (fonts[i].toLowerCase()) {
|
||||||
|
case common.genericFontFamilies.serif:
|
||||||
|
result = android.graphics.Typeface.create("serif" + getFontWeightSuffix(font.fontWeight), fontStyle);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case common.genericFontFamilies.sansSerif:
|
||||||
|
case common.genericFontFamilies.system:
|
||||||
|
result = android.graphics.Typeface.create("sans-serif" + getFontWeightSuffix(font.fontWeight), fontStyle);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case common.genericFontFamilies.monospace:
|
||||||
|
result = android.graphics.Typeface.create("monospace" + getFontWeightSuffix(font.fontWeight), fontStyle);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
result = loadFontFromFile(fonts[i]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
if (result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFontWeightSuffix(fontWeight: string): string {
|
||||||
|
switch (fontWeight) {
|
||||||
|
case enums.FontWeight.thin:
|
||||||
|
return android.os.Build.VERSION.SDK_INT >= 16 ? "-thin" : "";
|
||||||
|
case enums.FontWeight.extraLight:
|
||||||
|
case enums.FontWeight.light:
|
||||||
|
return android.os.Build.VERSION.SDK_INT >= 16 ? "-light" : "";
|
||||||
|
case enums.FontWeight.normal:
|
||||||
|
case "400":
|
||||||
|
case undefined:
|
||||||
|
case null:
|
||||||
|
return "";
|
||||||
|
case enums.FontWeight.medium:
|
||||||
|
case enums.FontWeight.semiBold:
|
||||||
|
return android.os.Build.VERSION.SDK_INT >= 21 ? "-medium" : "";
|
||||||
|
case enums.FontWeight.bold:
|
||||||
|
case "700":
|
||||||
|
case enums.FontWeight.extraBold:
|
||||||
|
return "";
|
||||||
|
case enums.FontWeight.black:
|
||||||
|
return android.os.Build.VERSION.SDK_INT >= 21 ? "-black" : "";
|
||||||
|
default:
|
||||||
|
throw new Error(`Invalid font weight: "${fontWeight}"`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,42 +14,7 @@ export class Font extends common.Font {
|
|||||||
|
|
||||||
public getUIFont(defaultFont: UIFont): UIFont {
|
public getUIFont(defaultFont: UIFont): UIFont {
|
||||||
if (!this._uiFont) {
|
if (!this._uiFont) {
|
||||||
var size = this.fontSize || defaultFont.pointSize;
|
this._uiFont = createUIFont(this, defaultFont);
|
||||||
|
|
||||||
var symbolicTraits: number = 0;
|
|
||||||
if (this.isBold) {
|
|
||||||
symbolicTraits |= UIFontDescriptorSymbolicTraits.UIFontDescriptorTraitBold;
|
|
||||||
}
|
|
||||||
if (this.isItalic) {
|
|
||||||
symbolicTraits |= UIFontDescriptorSymbolicTraits.UIFontDescriptorTraitItalic;
|
|
||||||
}
|
|
||||||
|
|
||||||
var descriptor: UIFontDescriptor;
|
|
||||||
switch (this.fontFamily) {
|
|
||||||
|
|
||||||
case common.genericFontFamilies.sansSerif:
|
|
||||||
case common.genericFontFamilies.system:
|
|
||||||
let uiFont = UIFont.systemFontOfSize(size);
|
|
||||||
descriptor = uiFont.fontDescriptor().fontDescriptorWithSymbolicTraits(symbolicTraits);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case common.genericFontFamilies.monospace:
|
|
||||||
if ((<any>UIFont).monospacedDigitSystemFontOfSizeWeight) {// This method is available on iOS 9.0 and later.
|
|
||||||
let uiFont = (<any>UIFont).monospacedDigitSystemFontOfSizeWeight(size, 0);
|
|
||||||
descriptor = uiFont.fontDescriptor().fontDescriptorWithSymbolicTraits(symbolicTraits);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!descriptor) {
|
|
||||||
descriptor = resolveFontDescriptor(this.fontFamily, symbolicTraits);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!descriptor) {
|
|
||||||
descriptor = defaultFont.fontDescriptor().fontDescriptorWithSymbolicTraits(symbolicTraits);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._uiFont = UIFont.fontWithDescriptorSize(descriptor, size);
|
|
||||||
}
|
}
|
||||||
return this._uiFont;
|
return this._uiFont;
|
||||||
}
|
}
|
||||||
@ -72,70 +37,26 @@ export class Font extends common.Font {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var areSystemFontSetsValid: boolean = false;
|
var areSystemFontSetsValid: boolean = false;
|
||||||
var systemFontFamilies = new Set();
|
export var systemFontFamilies = new Set<string>();
|
||||||
var systemFonts = new Set();
|
export var systemFonts = new Set<string>();
|
||||||
|
|
||||||
function assureSystemFontSets() {
|
export function ensureSystemFontSets() {
|
||||||
if (!areSystemFontSetsValid) {
|
if (areSystemFontSetsValid) {
|
||||||
var nsFontFamilies = UIFont.familyNames();
|
return;
|
||||||
for (var i = 0; i < nsFontFamilies.count; i++) {
|
|
||||||
var family = nsFontFamilies.objectAtIndex(i);
|
|
||||||
systemFontFamilies.add(family);
|
|
||||||
|
|
||||||
var nsFonts = UIFont.fontNamesForFamilyName(family);
|
|
||||||
for (var j = 0; j < nsFonts.count; j++) {
|
|
||||||
var font = nsFonts.objectAtIndex(j);
|
|
||||||
systemFonts.add(font);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
areSystemFontSetsValid = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveFontDescriptor(fontFamilyValue: string, symbolicTraits: number): UIFontDescriptor {
|
|
||||||
var fonts = common.parseFontFamily(fontFamilyValue);
|
|
||||||
var result: UIFontDescriptor = null;
|
|
||||||
if (fonts.length === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assureSystemFontSets();
|
var nsFontFamilies = UIFont.familyNames();
|
||||||
|
for (var i = 0; i < nsFontFamilies.count; i++) {
|
||||||
|
var family = nsFontFamilies.objectAtIndex(i);
|
||||||
|
systemFontFamilies.add(family);
|
||||||
|
|
||||||
for (var i = 0; i < fonts.length; i++) {
|
var nsFonts = UIFont.fontNamesForFamilyName(family);
|
||||||
var fontFamily = getFontFamilyRespectingGenericFonts(fonts[i]);
|
for (var j = 0; j < nsFonts.count; j++) {
|
||||||
|
var font = nsFonts.objectAtIndex(j);
|
||||||
if (systemFonts.has(fontFamily)) {
|
systemFonts.add(font);
|
||||||
// This is an actual font - don't apply symbolic traits
|
|
||||||
result = UIFontDescriptor.fontDescriptorWithNameSize(fontFamily, 0);
|
|
||||||
} else if (systemFontFamilies.has(fontFamily)) {
|
|
||||||
// This is a font family - we should apply symbolic traits if there are such
|
|
||||||
var fontFaceAttributes = [];
|
|
||||||
|
|
||||||
if (!symbolicTraits) {
|
|
||||||
fontFaceAttributes.push("Regular");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (symbolicTraits & UIFontDescriptorSymbolicTraits.UIFontDescriptorTraitBold) {
|
|
||||||
fontFaceAttributes.push("Bold");
|
|
||||||
}
|
|
||||||
if (symbolicTraits & UIFontDescriptorSymbolicTraits.UIFontDescriptorTraitItalic) {
|
|
||||||
fontFaceAttributes.push("Italic");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var fontAttributes = NSMutableDictionary.alloc().init();
|
|
||||||
fontAttributes.setObjectForKey(fontFamily, "NSFontFamilyAttribute");
|
|
||||||
fontAttributes.setObjectForKey(fontFaceAttributes.join(" "), "NSFontFaceAttribute");
|
|
||||||
|
|
||||||
result = UIFontDescriptor.fontDescriptorWithFontAttributes(fontAttributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result) {
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
areSystemFontSetsValid = true;
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_SERIF = "Times New Roman";
|
const DEFAULT_SERIF = "Times New Roman";
|
||||||
@ -158,6 +79,212 @@ function getFontFamilyRespectingGenericFonts(fontFamily: string): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createUIFont(font: Font, defaultFont: UIFont) {
|
||||||
|
var size = font.fontSize || defaultFont.pointSize;
|
||||||
|
var descriptor: UIFontDescriptor;
|
||||||
|
|
||||||
|
var symbolicTraits: number = 0;
|
||||||
|
if (font.isBold) {
|
||||||
|
symbolicTraits |= UIFontDescriptorSymbolicTraits.UIFontDescriptorTraitBold;
|
||||||
|
}
|
||||||
|
if (font.isItalic) {
|
||||||
|
symbolicTraits |= UIFontDescriptorSymbolicTraits.UIFontDescriptorTraitItalic;
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptor = tryResolveWithSystemFont(font, size, symbolicTraits);
|
||||||
|
|
||||||
|
if (!descriptor) {
|
||||||
|
descriptor = tryResolveByFamily(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!descriptor) {
|
||||||
|
descriptor = defaultFont.fontDescriptor().fontDescriptorWithSymbolicTraits(symbolicTraits);
|
||||||
|
}
|
||||||
|
|
||||||
|
return UIFont.fontWithDescriptorSize(descriptor, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
function tryResolveWithSystemFont(font: Font, size: number, symbolicTraits: number): UIFontDescriptor {
|
||||||
|
var systemFont: UIFont;
|
||||||
|
switch (font.fontFamily) {
|
||||||
|
case common.genericFontFamilies.sansSerif:
|
||||||
|
case common.genericFontFamilies.system:
|
||||||
|
if ((<any>UIFont).systemFontOfSizeWeight) {// This method is available on iOS 8.2 and later.
|
||||||
|
systemFont = (<any>UIFont).systemFontOfSizeWeight(size, getiOSFontWeight(font.fontWeight));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
systemFont = UIFont.systemFontOfSize(size);
|
||||||
|
}
|
||||||
|
result = systemFont.fontDescriptor().fontDescriptorWithSymbolicTraits(symbolicTraits);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case common.genericFontFamilies.monospace:
|
||||||
|
if ((<any>UIFont).monospacedDigitSystemFontOfSizeWeight) {// This method is available on iOS 9.0 and later.
|
||||||
|
systemFont = (<any>UIFont).monospacedDigitSystemFontOfSizeWeight(size, getiOSFontWeight(font.fontWeight));
|
||||||
|
result = systemFont.fontDescriptor().fontDescriptorWithSymbolicTraits(symbolicTraits);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (systemFont) {
|
||||||
|
var result = systemFont.fontDescriptor().fontDescriptorWithSymbolicTraits(symbolicTraits);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function tryResolveByFamily(font: Font): UIFontDescriptor {
|
||||||
|
var fonts = common.parseFontFamily(font.fontFamily);
|
||||||
|
var result: UIFontDescriptor = null;
|
||||||
|
if (fonts.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ensureSystemFontSets();
|
||||||
|
|
||||||
|
for (var i = 0; i < fonts.length; i++) {
|
||||||
|
var fontFamily = getFontFamilyRespectingGenericFonts(fonts[i]);
|
||||||
|
var fontFace = getiOSFontFace(fontFamily, font.fontWeight, font.isItalic);
|
||||||
|
if (systemFonts.has(fontFamily) && !fontFace) { // This is an actual font like `HelveticaNeue-UltraLightItalic` - don't apply font face attribute
|
||||||
|
result = UIFontDescriptor.fontDescriptorWithNameSize(fontFamily, 0);
|
||||||
|
}
|
||||||
|
else if (systemFontFamilies.has(fontFamily)) { // This is a font family like `Helvetica Neue` - apply font face attribute
|
||||||
|
result = createFontDescriptor(fontFamily, fontFace);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createFontDescriptor(fontFamily: string, fontFace: string): UIFontDescriptor {
|
||||||
|
var fontAttributes = NSMutableDictionary.alloc().init();
|
||||||
|
fontAttributes.setObjectForKey(fontFamily, "NSFontFamilyAttribute");
|
||||||
|
if (fontFace) {
|
||||||
|
fontAttributes.setObjectForKey(fontFace, "NSFontFaceAttribute");
|
||||||
|
}
|
||||||
|
return UIFontDescriptor.fontDescriptorWithFontAttributes(fontAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Available in iOS 8.2 and later.
|
||||||
|
declare var UIFontWeightThin: number; //0.8
|
||||||
|
declare var UIFontWeightUltraLight: number; //0.6
|
||||||
|
declare var UIFontWeightLight: number; //0.4
|
||||||
|
declare var UIFontWeightRegular: number; //0
|
||||||
|
declare var UIFontWeightMedium: number; //0.23
|
||||||
|
declare var UIFontWeightSemibold: number; //0.3
|
||||||
|
declare var UIFontWeightBold: number; //0.4
|
||||||
|
declare var UIFontWeightHeavy: number; //0.56
|
||||||
|
declare var UIFontWeightBlack: number; //0.62
|
||||||
|
function getiOSFontWeight(fontWeight: string): number {
|
||||||
|
if (!(<any>UIFont).systemFontOfSizeWeight) {
|
||||||
|
throw new Error("Font weight is available in iOS 8.2 and later.");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (fontWeight) {
|
||||||
|
case enums.FontWeight.thin:
|
||||||
|
return UIFontWeightThin;
|
||||||
|
case enums.FontWeight.extraLight:
|
||||||
|
return UIFontWeightUltraLight;
|
||||||
|
case enums.FontWeight.light:
|
||||||
|
return UIFontWeightLight;
|
||||||
|
case enums.FontWeight.normal:
|
||||||
|
case "400":
|
||||||
|
case undefined:
|
||||||
|
case null:
|
||||||
|
return UIFontWeightRegular;
|
||||||
|
case enums.FontWeight.medium:
|
||||||
|
return UIFontWeightMedium;
|
||||||
|
case enums.FontWeight.semiBold:
|
||||||
|
return UIFontWeightSemibold;
|
||||||
|
case enums.FontWeight.bold:
|
||||||
|
case "700":
|
||||||
|
return UIFontWeightBold;
|
||||||
|
case enums.FontWeight.extraBold:
|
||||||
|
return UIFontWeightHeavy;
|
||||||
|
case enums.FontWeight.black:
|
||||||
|
return UIFontWeightBlack;
|
||||||
|
default:
|
||||||
|
throw new Error(`Invalid font weight: "${fontWeight}"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function combineWeightStringWithItalic(weight: string, isItalic: boolean) {
|
||||||
|
if (!isItalic) {
|
||||||
|
return weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!weight) {
|
||||||
|
return "Italic";
|
||||||
|
}
|
||||||
|
|
||||||
|
return weight + " Italic";
|
||||||
|
}
|
||||||
|
|
||||||
|
function canLoadFont(fontFamily: string, fontFace: string) {
|
||||||
|
var trialDescriptor = createFontDescriptor(fontFamily, fontFace);
|
||||||
|
var trialFont = UIFont.fontWithDescriptorSize(trialDescriptor, 0);
|
||||||
|
return trialFont.familyName === fontFamily;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findCorrectWeightString(fontFamily: string, weightStringAlternatives: Array<string>, isItalic: boolean) {
|
||||||
|
var i = 0;
|
||||||
|
let length = weightStringAlternatives.length;
|
||||||
|
for (; i < length; i++) {
|
||||||
|
var possibleFontFace = combineWeightStringWithItalic(weightStringAlternatives[i], isItalic);
|
||||||
|
if (canLoadFont(fontFamily, possibleFontFace)) {
|
||||||
|
return weightStringAlternatives[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return weightStringAlternatives[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getiOSFontFace(fontFamily: string, fontWeight: string, isItalic: boolean): string {
|
||||||
|
// ... with a lot of fuzzy logic and artificial intelligence thanks to the lack of font naming standards.
|
||||||
|
var weight: string;
|
||||||
|
switch (fontWeight) {
|
||||||
|
case enums.FontWeight.thin:
|
||||||
|
weight = "Thin";
|
||||||
|
break;
|
||||||
|
case enums.FontWeight.extraLight:
|
||||||
|
weight = findCorrectWeightString(fontFamily, ["Ultra Light", "UltraLight", "Extra Light", "ExtraLight", "Ultra light", "Ultralight", "Extra light", "Extralight"], isItalic);
|
||||||
|
break;
|
||||||
|
case enums.FontWeight.light:
|
||||||
|
weight = "Light";
|
||||||
|
break;
|
||||||
|
case enums.FontWeight.normal:
|
||||||
|
case "400":
|
||||||
|
case undefined:
|
||||||
|
case null:
|
||||||
|
weight = ""; // We dont' need to write Regular
|
||||||
|
break;
|
||||||
|
case enums.FontWeight.medium:
|
||||||
|
weight = "Medium";
|
||||||
|
break;
|
||||||
|
case enums.FontWeight.semiBold:
|
||||||
|
weight = findCorrectWeightString(fontFamily, ["Demi Bold", "DemiBold", "Semi Bold", "SemiBold", "Demi bold", "Demibold", "Semi bold", "Semibold"], isItalic);
|
||||||
|
break;
|
||||||
|
case enums.FontWeight.bold:
|
||||||
|
case "700":
|
||||||
|
weight = "Bold";
|
||||||
|
break;
|
||||||
|
case enums.FontWeight.extraBold:
|
||||||
|
weight = findCorrectWeightString(fontFamily, ["Heavy", "Extra Bold", "ExtraBold", "Extra bold", "Extrabold"], isItalic);
|
||||||
|
break;
|
||||||
|
case enums.FontWeight.black:
|
||||||
|
weight = "Black";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Invalid font weight: "${fontWeight}"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return combineWeightStringWithItalic(weight, isItalic);
|
||||||
|
}
|
||||||
|
|
||||||
export module ios {
|
export module ios {
|
||||||
export function registerFont(fontFile: string) {
|
export function registerFont(fontFile: string) {
|
||||||
var filePath = fs.path.join(fs.knownFolders.currentApp().path, "fonts", fontFile);
|
var filePath = fs.path.join(fs.knownFolders.currentApp().path, "fonts", fontFile);
|
||||||
|
@ -423,7 +423,19 @@ function isLetterSpacingValid(value: string): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isFontWeightValid(value: string): boolean {
|
function isFontWeightValid(value: string): boolean {
|
||||||
return value === enums.FontWeight.normal || value === enums.FontWeight.bold;
|
if (!value) {
|
||||||
|
console.trace();
|
||||||
|
}
|
||||||
|
return value === enums.FontWeight.thin
|
||||||
|
|| value === enums.FontWeight.extraLight
|
||||||
|
|| value === enums.FontWeight.light
|
||||||
|
|| value === enums.FontWeight.normal || value === "400"
|
||||||
|
|| value === enums.FontWeight.medium
|
||||||
|
|| value === enums.FontWeight.semiBold
|
||||||
|
|| value === enums.FontWeight.bold || value === "700"
|
||||||
|
|| value === enums.FontWeight.extraBold
|
||||||
|
|| value === enums.FontWeight.black
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isFontStyleValid(value: string): boolean {
|
function isFontStyleValid(value: string): boolean {
|
||||||
|
Reference in New Issue
Block a user