From 03f9867e2ab8e217464e5918144c4663efbe783d Mon Sep 17 00:00:00 2001 From: Rossen Hristov Date: Wed, 13 Apr 2016 10:37:12 +0300 Subject: [PATCH] Generic font families `system`, `sans-serif` and `monospace` now correctly resolve the system font when possible on iOS Resolves #1864 --- CrossPlatformModules.csproj | 8 +++++ apps/sample-fonts/app.ts | 3 ++ apps/sample-fonts/main-page.ts | 62 +++++++++++++++++++++++++++++++++ apps/sample-fonts/main-page.xml | 5 +++ apps/sample-fonts/package.json | 2 ++ ui/styling/font-common.ts | 1 + ui/styling/font.android.ts | 4 +++ ui/styling/font.ios.ts | 35 ++++++++++++++----- 8 files changed, 111 insertions(+), 9 deletions(-) create mode 100644 apps/sample-fonts/app.ts create mode 100644 apps/sample-fonts/main-page.ts create mode 100644 apps/sample-fonts/main-page.xml create mode 100644 apps/sample-fonts/package.json diff --git a/CrossPlatformModules.csproj b/CrossPlatformModules.csproj index 88f3c1311..4465754e9 100644 --- a/CrossPlatformModules.csproj +++ b/CrossPlatformModules.csproj @@ -90,6 +90,10 @@ + + + main-page.xml + @@ -152,6 +156,9 @@ + + Designer + @@ -2106,6 +2113,7 @@ PreserveNewest + diff --git a/apps/sample-fonts/app.ts b/apps/sample-fonts/app.ts new file mode 100644 index 000000000..d903b1c7c --- /dev/null +++ b/apps/sample-fonts/app.ts @@ -0,0 +1,3 @@ +import application = require("application"); +application.cssFile = "app.css" +application.start({ moduleName: "main-page" }); \ No newline at end of file diff --git a/apps/sample-fonts/main-page.ts b/apps/sample-fonts/main-page.ts new file mode 100644 index 000000000..87d957983 --- /dev/null +++ b/apps/sample-fonts/main-page.ts @@ -0,0 +1,62 @@ +import { View } from "ui/core/view"; +import { EventData } from "data/observable"; +import { LayoutBase } from "ui/layouts/layout-base"; +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 typeUtils = require("utils/types"); +import { Color } from "color"; + +const fontFamilies = ["system", "sans-serif", "serif", "monospace"]; +const fontWeights = [FontWeight.normal, FontWeight.bold]; +const fontStyles = [FontStyle.normal, FontStyle.italic]; + +export function onStackLayoutLoaded(args: EventData) { + var layout = args.object; + _generateViews(() => { return new Label(); }, layout); + _generateViews(() => { return new TextField(); }, layout); + _generateViews(() => { return new TextView(); }, layout); + _generateViews(() => { return new Button(); }, layout); +} + +function _generateViews(factory: () => View, layout: LayoutBase) { + for (var f = 0; f < fontFamilies.length; f++) { + for (var w = 0; w < fontWeights.length; w++) { + for (var s = 0; s < fontStyles.length; s++) { + var view = factory(); + var css = `font-family: ${fontFamilies[f]}; font-weight: ${fontWeights[w]}; font-style: ${fontStyles[s]};`; + (view).text = `${typeUtils.getClass(view)} ${css}`; + (view).textWrap = true; + view.style.textAlignment = "left"; + view.setInlineStyle(css); + view.margin = "1 0"; + view.borderWidth = 1; + view.height = 75; + view.color = new Color("Black"); + view.backgroundColor = new Color("LightGray"); + view.on("loaded", args => { + (view).text += _getFontInfo(view); + }); + layout.addChild(view); + } + } + } +} + +function _getFontInfo(view: View): string { + if (view.ios) { + var uiFont: UIFont; + if (view.ios instanceof UIButton) { + uiFont = view.ios.titleLabel.font; + } + else if (view.ios.font) { + uiFont = view.ios.font; + } + + return ` ${uiFont.fontName} ${uiFont.pointSize}pt.`; + } + + return ""; +} \ No newline at end of file diff --git a/apps/sample-fonts/main-page.xml b/apps/sample-fonts/main-page.xml new file mode 100644 index 000000000..e029e0bf4 --- /dev/null +++ b/apps/sample-fonts/main-page.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/apps/sample-fonts/package.json b/apps/sample-fonts/package.json new file mode 100644 index 000000000..db7dfb767 --- /dev/null +++ b/apps/sample-fonts/package.json @@ -0,0 +1,2 @@ +{ "name" : "sample-fonts", + "main" : "app.js" } diff --git a/ui/styling/font-common.ts b/ui/styling/font-common.ts index 86e26f729..e5f2f8e27 100644 --- a/ui/styling/font-common.ts +++ b/ui/styling/font-common.ts @@ -130,6 +130,7 @@ export module genericFontFamilies { export var serif = "serif"; export var sansSerif = "sans-serif"; export var monospace = "monospace"; + export var system = "system"; } var styles = new Set(); diff --git a/ui/styling/font.android.ts b/ui/styling/font.android.ts index 6f012b169..bf2cf329e 100644 --- a/ui/styling/font.android.ts +++ b/ui/styling/font.android.ts @@ -102,6 +102,10 @@ export class Font extends common.Font { result = android.graphics.Typeface.MONOSPACE; break; + case common.genericFontFamilies.system: + result = android.graphics.Typeface.DEFAULT; + break; + default: result = this.loadFontFromFile(fonts[i]); break; diff --git a/ui/styling/font.ios.ts b/ui/styling/font.ios.ts index dc0ca0016..de3527586 100644 --- a/ui/styling/font.ios.ts +++ b/ui/styling/font.ios.ts @@ -3,10 +3,6 @@ import common = require("./font-common"); import fs = require("file-system"); import * as traceModule from "trace"; -var DEFAULT_SERIF = "Times New Roman"; -var DEFAULT_SANS_SERIF = "Helvetica"; -var DEFAULT_MONOSPACE = "Courier New"; - export class Font extends common.Font { public static default = new Font(undefined, undefined, enums.FontStyle.normal, enums.FontWeight.normal); @@ -18,6 +14,8 @@ export class Font extends common.Font { public getUIFont(defaultFont: UIFont): UIFont { if (!this._uiFont) { + var size = this.fontSize || defaultFont.pointSize; + var symbolicTraits: number = 0; if (this.isBold) { symbolicTraits |= UIFontDescriptorSymbolicTraits.UIFontDescriptorTraitBold; @@ -26,11 +24,30 @@ export class Font extends common.Font { symbolicTraits |= UIFontDescriptorSymbolicTraits.UIFontDescriptorTraitItalic; } - var descriptor = resolveFontDescriptor(this.fontFamily, symbolicTraits); + 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 ((UIFont).monospacedDigitSystemFontOfSizeWeight) {// This method is available on iOS 9.0 and later. + let uiFont = (UIFont).monospacedDigitSystemFontOfSizeWeight(size, 0); + descriptor = uiFont.fontDescriptor().fontDescriptorWithSymbolicTraits(symbolicTraits); + } + break; + } + + if (!descriptor) { + descriptor = resolveFontDescriptor(this.fontFamily, symbolicTraits); + } + if (!descriptor) { descriptor = defaultFont.fontDescriptor().fontDescriptorWithSymbolicTraits(symbolicTraits); } - var size = this.fontSize || defaultFont.pointSize; this._uiFont = UIFont.fontWithDescriptorSize(descriptor, size); } @@ -121,6 +138,9 @@ function resolveFontDescriptor(fontFamilyValue: string, symbolicTraits: number): return null; } +const DEFAULT_SERIF = "Times New Roman"; +const DEFAULT_MONOSPACE = "Courier New"; + function getFontFamilyRespectingGenericFonts(fontFamily: string): string { if (!fontFamily) { return fontFamily; @@ -130,9 +150,6 @@ function getFontFamilyRespectingGenericFonts(fontFamily: string): string { case common.genericFontFamilies.serif: return DEFAULT_SERIF; - case common.genericFontFamilies.sansSerif: - return DEFAULT_SANS_SERIF; - case common.genericFontFamilies.monospace: return DEFAULT_MONOSPACE;