diff --git a/web/source/osk/lengthStyle.ts b/web/source/osk/lengthStyle.ts index 16c5c5a790..aeb2e48112 100644 --- a/web/source/osk/lengthStyle.ts +++ b/web/source/osk/lengthStyle.ts @@ -59,6 +59,10 @@ namespace com.keyman.osk { return new ParsedLengthStyle({val: val, absolute: false}); } + public static special(val: number, suffix: 'em' | 'rem'): ParsedLengthStyle { + return new ParsedLengthStyle({val: val, absolute: false, special: suffix}); + } + private static parseLengthStyle(spec: string): LengthStyle { var val: number; diff --git a/web/source/osk/oskKey.ts b/web/source/osk/oskKey.ts index c547629018..808333626e 100644 --- a/web/source/osk/oskKey.ts +++ b/web/source/osk/oskKey.ts @@ -263,6 +263,13 @@ namespace com.keyman.osk { * This version has been substantially modified to work for this particular application. */ static getTextMetrics(text: string, emScale: number, style: {fontFamily?: string, fontSize: string}): TextMetrics { + // Since we may mutate the incoming style, let's make sure to copy it first. + // Only the relevant properties, though. + style = { + fontFamily: style.fontFamily, + fontSize: style.fontSize + }; + // A final fallback - having the right font selected makes a world of difference. if(!style.fontFamily) { style.fontFamily = getComputedStyle(document.body).fontFamily; @@ -298,7 +305,7 @@ namespace com.keyman.osk { let emScale = vkbd.getKeyEmFontSize(); let metrics = OSKKey.getTextMetrics(this.spec.text, emScale, style); - let fontSpec = getFontSizeStyle(style.fontSize); + let fontSpec = getFontSizeStyle(style.fontSize || '1em'); let keyWidth = this.getKeyWidth(vkbd); const MAX_X_PROPORTION = 0.90; const MAX_Y_PROPORTION = 0.90; @@ -425,9 +432,6 @@ namespace com.keyman.osk { spec['font'] = "SpecialOSK"; } - // Grab our default for the key's font and font size. - ts.fontSize=vkbd.fontSize; //Build 344, KMEW-90 - //Override font spec if set for this key in the layout if(typeof spec['font'] == 'string' && spec['font'] != '') { ts.fontFamily=spec['font']; diff --git a/web/source/osk/oskLayerGroup.ts b/web/source/osk/oskLayerGroup.ts index 2a959868c4..ca1b856a91 100644 --- a/web/source/osk/oskLayerGroup.ts +++ b/web/source/osk/oskLayerGroup.ts @@ -28,8 +28,6 @@ namespace com.keyman.osk { ls.fontSize=layout['fontsize']; } - vkbd.fontSize=ls.fontSize; //TODO: move outside function********* - // Create a separate OSK div for each OSK layer, only one of which will ever be visible var n: number, i: number, j: number; var layers: keyboards.LayoutLayer[]; diff --git a/web/source/osk/oskManager.ts b/web/source/osk/oskManager.ts index 97f21e5a38..9aa6d38247 100644 --- a/web/source/osk/oskManager.ts +++ b/web/source/osk/oskManager.ts @@ -46,13 +46,13 @@ namespace com.keyman.osk { * The configured width for this OSKManager. May be `undefined` or `null` * to allow automatic width scaling. */ - private _width: ParsedLengthStyle; + private _width: ParsedLengthStyle; - /** - * The configured height for this OSKManager. May be `undefined` or `null` - * to allow automatic height scaling. - */ - private _height: ParsedLengthStyle; + /** + * The configured height for this OSKManager. May be `undefined` or `null` + * to allow automatic height scaling. + */ + private _height: ParsedLengthStyle; /** * The computed width for this OSKManager. May be null if auto sizing @@ -66,6 +66,12 @@ namespace com.keyman.osk { */ private _computedHeight: number; + /** + * The base font size to use for hosted `Banner`s and `VisualKeyboard` + * instances. + */ + private _baseFontSize: ParsedLengthStyle; + private needsLayout: boolean = true; // Key code definition aliases for legacy keyboards (They expect window['keyman']['osk'].___) @@ -148,23 +154,6 @@ namespace com.keyman.osk { s.zIndex='9999'; s.display='none'; s.width= device.touchable ? '100%' : 'auto'; s.position = (device.formFactor == 'desktop' ? 'absolute' : 'fixed'); - // Use smaller base font size for mobile devices - //if(screen.availHeight < 500) s.fontSize='10pt'; - //else if(screen.availHeight < 800) s.fontSize='11pt'; - //else s.fontSize='12pt'; - - // Set scaling for mobile devices here. - if(device.touchable) { - let fontScale = this.defaultFontSize(device, keymanweb.isEmbedded); - - // Finalize the font size parameter. - if(fontScale.absolute) { - s.fontSize = fontScale.styleString; - } else { - s.fontSize = fontScale.val + 'em'; - } - } - if(this.vkbd) { this.vkbd.shutdown(); } @@ -190,12 +179,14 @@ namespace com.keyman.osk { // Add suggestion banner bar to OSK if (this.banner) { this._Box.appendChild(this.banner.element); + this.banner.element.style.fontSize = this.baseFontSize; } let kbdView: KeyboardView = this._GenerateKeyboardView(activeKeyboard); this._Box.appendChild(kbdView.element); if(kbdView instanceof VisualKeyboard) { this.vkbd = kbdView; + kbdView.fontSize = this.parsedBaseFontSize; } kbdView.postInsert(); @@ -292,6 +283,50 @@ namespace com.keyman.osk { return this._computedHeight; } + /** + * The top-level style string for the font size used by the predictive banner + * and the primary keyboard visualization elements. + */ + get baseFontSize(): string { + return this.parsedBaseFontSize.styleString; + } + + private get parsedBaseFontSize(): ParsedLengthStyle { + if(!this._baseFontSize) { + let keymanweb = com.keyman.singleton; + let device = keymanweb.util.device; + this._baseFontSize = this.defaultFontSize(device, keymanweb.isEmbedded); + } + + return this._baseFontSize; + } + + public defaultFontSize(device: Device, isEmbedded: boolean): ParsedLengthStyle { + if(device.touchable) { + var fontScale: number = 1; + if(device.formFactor == 'phone') { + fontScale = 1.6 * (isEmbedded ? 0.65 : 0.6) * 1.2; // Combines original scaling factor with one previously applied to the layer group. + } else { + // The following is a *temporary* fix for small format tablets, e.g. PendoPad + var pixelRatio = 1; + if(device.OS == 'Android' && 'devicePixelRatio' in window) { + pixelRatio = window.devicePixelRatio; + } + + if(device.OS == 'Android' && device.formFactor == 'tablet' && this.getHeight() < 300 * pixelRatio) { + fontScale *= 1.2; + } else { + fontScale *= 2; //'2.5em'; + } + } + + // Finalize the font size parameter. + return ParsedLengthStyle.special(fontScale, 'em'); + } else { + return this.computedHeight ? ParsedLengthStyle.inPixels(this.computedHeight / 8) : undefined; + } + } + private layerChangeHandler: text.SystemStoreMutationHandler = function(this: OSKManager, source: text.MutableSystemStore, newValue: string) { @@ -620,32 +655,6 @@ namespace com.keyman.osk { return width; } - public defaultFontSize(device: Device, isEmbedded: boolean): ParsedLengthStyle { - if(device.touchable) { - var fontScale: number = 1; - if(device.formFactor == 'phone') { - fontScale = 1.6 * (isEmbedded ? 0.65 : 0.6) * 1.2; // Combines original scaling factor with one previously applied to the layer group. - } else { - // The following is a *temporary* fix for small format tablets, e.g. PendoPad - var pixelRatio = 1; - if(device.OS == 'Android' && 'devicePixelRatio' in window) { - pixelRatio = window.devicePixelRatio; - } - - if(device.OS == 'Android' && device.formFactor == 'tablet' && this.getHeight() < 300 * pixelRatio) { - fontScale *= 1.2; - } else { - fontScale *= 2; //'2.5em'; - } - } - - // Finalize the font size parameter. - return ParsedLengthStyle.forScalar(fontScale); - } else { - return this.computedHeight ? ParsedLengthStyle.inPixels(this.computedHeight / 8) : undefined; - } - } - /** * Allow UI to update OSK position and properties * diff --git a/web/source/osk/visualKeyboard.ts b/web/source/osk/visualKeyboard.ts index 07ebcc6b8c..5a5643c80a 100644 --- a/web/source/osk/visualKeyboard.ts +++ b/web/source/osk/visualKeyboard.ts @@ -46,7 +46,8 @@ namespace com.keyman.osk { // Style-related properties fontFamily: string; - fontSize: string; + private _fontSize: ParsedLengthStyle; + // fontSize: string; // State-related properties keyPending: KeyElement; @@ -199,6 +200,15 @@ namespace com.keyman.osk { return this._height; } + get fontSize(): ParsedLengthStyle { + return this._fontSize; + } + + set fontSize(value: ParsedLengthStyle) { + this._fontSize = value; + this.kbdDiv.style.fontSize = value.styleString; + } + /** * Uses fixed scaling for internal elements, rather than relative, percent- * based scaling. @@ -987,28 +997,25 @@ namespace com.keyman.osk { * Use of `getComputedStyle` is ideal, but in many of our use cases its preconditions are not met. * This function allows us to calculate the font size in those situations. */ - getKeyEmFontSize() { - let keyman = com.keyman.singleton; + getKeyEmFontSize(): number { + if(!this.fontSize) { + return 0; + } if(this.device.formFactor == 'desktop') { - let kbdFontSize = this.defaultDesktopFontSize(); let keySquareScale = 0.8; // Set in kmwosk.css, is relative. - return kbdFontSize * keySquareScale; + return this.fontSize.scaledBy(keySquareScale).val; } else { let emSizeStr = getComputedStyle(document.body).fontSize; let emSize = getFontSizeStyle(emSizeStr).val; var emScale = 1; if(!this.isStatic) { - // Reading this requires the OSK to be active, so we filter out - // BuildVisualKeyboard calls here. - let boxFontStyle = getFontSizeStyle(keyman.osk._Box); - // Double-check against the font scaling applied to the _Box element. - if(boxFontStyle.absolute) { - return boxFontStyle.val; + if(this.fontSize.absolute) { + return this.fontSize.val; } else { - emScale = boxFontStyle.val; + emScale = this.fontSize.val; } } return emSize * emScale;