refactor(web): font-size style placement

This commit is contained in:
jahorton 2021-07-15 09:46:29 +07:00
parent 4dc09ce9b9
commit eeae512656
5 changed files with 89 additions and 67 deletions

View file

@ -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;

View file

@ -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'];

View file

@ -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[];

View file

@ -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
*

View file

@ -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;