From 426e3d1d3ac7ddf38386c166c5275df99cc1a7f2 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Wed, 2 Apr 2025 12:45:34 +0700 Subject: [PATCH 1/5] fix(web): apply layout font-scaling to banner When a keyboard's layout specifies font-upscaling, that scaling should also be applied to the banner. This was not previously being done, which could lead to font-size discrepancies between the two (as noted with `khmer_angkor` in the base issue). --- .../engine/osk/src/keyboard-layout/oskLayerGroup.ts | 8 -------- web/src/engine/osk/src/views/oskView.ts | 12 +++++++++++- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/web/src/engine/osk/src/keyboard-layout/oskLayerGroup.ts b/web/src/engine/osk/src/keyboard-layout/oskLayerGroup.ts index 4bf4bc01b4..2f15957308 100644 --- a/web/src/engine/osk/src/keyboard-layout/oskLayerGroup.ts +++ b/web/src/engine/osk/src/keyboard-layout/oskLayerGroup.ts @@ -40,14 +40,6 @@ export default class OSKLayerGroup { return; } - // Set default OSK font size (Build 344, KMEW-90) - let layoutFS = layout['fontsize']; - if(typeof layoutFS == 'undefined' || layoutFS == null || layoutFS == '') { - ls.fontSize='1em'; - } else { - ls.fontSize=layout['fontsize']; - } - ls.width = '100%'; ls.height = '100%'; diff --git a/web/src/engine/osk/src/views/oskView.ts b/web/src/engine/osk/src/views/oskView.ts index 53a9bbe253..41989dd72f 100644 --- a/web/src/engine/osk/src/views/oskView.ts +++ b/web/src/engine/osk/src/views/oskView.ts @@ -518,7 +518,17 @@ export default abstract class OSKView this._baseFontSize = OSKView.defaultFontSize(this.targetDevice, this.computedHeight, this.isEmbedded); } - return this._baseFontSize; + // Set default OSK font size (Build 344, KMEW-90) + // If the layer group specifies a fontsize value, we need + // to apply that to the banner as well. + const layerFontSize = this.vkbd?.layerGroup?.spec.fontsize; + + if(layerFontSize) { + const parsedSize = new ParsedLengthStyle(layerFontSize); + return parsedSize.absolute ? parsedSize : this._baseFontSize.scaledBy(parsedSize.val); + } else { + return this._baseFontSize; + } } public static defaultFontSize(device: DeviceSpec, computedHeight: number, isEmbedded: boolean): ParsedLengthStyle { From 831ca4eeafaa1dc1408a18bf9329a7ef779e822e Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Wed, 2 Apr 2025 12:48:53 +0700 Subject: [PATCH 2/5] fix(web): add banner font downscaling Fixes: #13644 The banner should also double-check the height of its suggestions, applying downscaling where needed to ensure the suggestions' text does not flow out of bounds. Additionally, if the main keyboard body's keys required downscaling due to text height, this will likely also result in similar scaling for the suggestions. --- .../engine/osk/src/banner/suggestionBanner.ts | 33 ++++++++++++++++--- web/src/resources/osk/kmwosk.css | 3 +- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/web/src/engine/osk/src/banner/suggestionBanner.ts b/web/src/engine/osk/src/banner/suggestionBanner.ts index 0cecd1aa46..cfb629af79 100644 --- a/web/src/engine/osk/src/banner/suggestionBanner.ts +++ b/web/src/engine/osk/src/banner/suggestionBanner.ts @@ -67,7 +67,13 @@ interface BannerSuggestionFormatSpec { * Sets a target width to use when 'collapsing' suggestions. Only affects those long * enough to need said 'collapsing'. */ - collapsedWidth?: number + collapsedWidth?: number; + + /** + * The height allotted to each suggestion; needed to support font scaling if the + * font would otherwise be too large. + */ + height?: number } export class BannerSuggestion { @@ -170,7 +176,22 @@ export class BannerSuggestion { if(suggestion && suggestion.displayAs) { const rawMetrics = getTextMetrics(suggestion.displayAs, format.emSize, format.styleForFont); - this._textWidth = rawMetrics.width; + let projectedHeight = 0; + if(rawMetrics.fontBoundingBoxAscent) { + projectedHeight = rawMetrics.fontBoundingBoxAscent + rawMetrics.fontBoundingBoxDescent; + } + let ratio = Math.min(1, format.height / projectedHeight); + let width = rawMetrics.width; + + // do we need font-height scaling? + this._textWidth = width * ratio; + // Apply styling to the container element so that it does not override CSS styling on the + // display element (for tablets) + if(ratio < 1) { + this.container.style.fontSize = ParsedLengthStyle.forScalar(ratio).styleString; + } else { + delete this.container.style.fontSize; + } } else { this._textWidth = 0; } @@ -726,14 +747,15 @@ export class SuggestionBanner extends Banner { const emSizeStr = getComputedStyle(document.body).fontSize; const emSize = getFontSizeStyle(emSizeStr).val; - const textStyle = getComputedStyle(this.options[0].container.firstChild as HTMLSpanElement); + const textElementStyle = getComputedStyle(this.options[0].container.firstChild as HTMLSpanElement); const targetWidth = this.width / SuggestionBanner.LONG_SUGGESTION_DISPLAY_LIMIT; + const height = this.height * .85; // .85 is a modifier seen in the CSS. // computedStyle will fail if the element's not in the DOM yet. // Seeks to get the values specified within kmwosk.css. - const textLeftPad = new ParsedLengthStyle(textStyle.paddingLeft || '4px'); - const textRightPad = new ParsedLengthStyle(textStyle.paddingRight || '4px'); + const textLeftPad = new ParsedLengthStyle(textElementStyle.paddingLeft || '4px'); + const textRightPad = new ParsedLengthStyle(textElementStyle.paddingRight || '4px'); let optionFormat: BannerSuggestionFormatSpec = { paddingWidth: textLeftPad.val + textRightPad.val, // Assumes fixed px padding. @@ -741,6 +763,7 @@ export class SuggestionBanner extends Banner { styleForFont: fontStyle, collapsedWidth: targetWidth, minWidth: 0, + height: height } for (let i=0; i Date: Thu, 3 Apr 2025 08:12:02 +0700 Subject: [PATCH 3/5] fix(web): prevent div-by-zero potential from prior commit --- web/src/engine/osk/src/banner/suggestionBanner.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/engine/osk/src/banner/suggestionBanner.ts b/web/src/engine/osk/src/banner/suggestionBanner.ts index cfb629af79..da59121921 100644 --- a/web/src/engine/osk/src/banner/suggestionBanner.ts +++ b/web/src/engine/osk/src/banner/suggestionBanner.ts @@ -176,7 +176,7 @@ export class BannerSuggestion { if(suggestion && suggestion.displayAs) { const rawMetrics = getTextMetrics(suggestion.displayAs, format.emSize, format.styleForFont); - let projectedHeight = 0; + let projectedHeight = 1; if(rawMetrics.fontBoundingBoxAscent) { projectedHeight = rawMetrics.fontBoundingBoxAscent + rawMetrics.fontBoundingBoxDescent; } From 41106a1d850efca663b556952f28018051b38b3d Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Thu, 3 Apr 2025 15:47:03 +0700 Subject: [PATCH 4/5] chore(web): code cleanup per review --- web/src/engine/osk/src/banner/suggestionBanner.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/web/src/engine/osk/src/banner/suggestionBanner.ts b/web/src/engine/osk/src/banner/suggestionBanner.ts index da59121921..e92e199ff4 100644 --- a/web/src/engine/osk/src/banner/suggestionBanner.ts +++ b/web/src/engine/osk/src/banner/suggestionBanner.ts @@ -26,6 +26,9 @@ const BANNER_SCROLLER_CLASS = 'kmw-suggest-banner-scroller'; const BANNER_VERT_ROAMING_HEIGHT_RATIO = 0.666; +// .85 is seen in kmwosk.css on `.kmw-banner-bar .kmw-suggest-option`. +const SUGGESTION_HEIGHT_IN_BANNER_RATIO = 0.85; + /** * The style to temporarily apply when updating suggestion text in order to prevent * fade transitions at that time. @@ -176,15 +179,13 @@ export class BannerSuggestion { if(suggestion && suggestion.displayAs) { const rawMetrics = getTextMetrics(suggestion.displayAs, format.emSize, format.styleForFont); - let projectedHeight = 1; - if(rawMetrics.fontBoundingBoxAscent) { - projectedHeight = rawMetrics.fontBoundingBoxAscent + rawMetrics.fontBoundingBoxDescent; - } + const projectedHeight = rawMetrics.fontBoundingBoxAscent + ? rawMetrics.fontBoundingBoxAscent + rawMetrics.fontBoundingBoxDescent + : 1; let ratio = Math.min(1, format.height / projectedHeight); - let width = rawMetrics.width; // do we need font-height scaling? - this._textWidth = width * ratio; + this._textWidth = rawMetrics.width * ratio; // Apply styling to the container element so that it does not override CSS styling on the // display element (for tablets) if(ratio < 1) { @@ -750,7 +751,7 @@ export class SuggestionBanner extends Banner { const textElementStyle = getComputedStyle(this.options[0].container.firstChild as HTMLSpanElement); const targetWidth = this.width / SuggestionBanner.LONG_SUGGESTION_DISPLAY_LIMIT; - const height = this.height * .85; // .85 is a modifier seen in the CSS. + const height = this.height * SUGGESTION_HEIGHT_IN_BANNER_RATIO; // computedStyle will fail if the element's not in the DOM yet. // Seeks to get the values specified within kmwosk.css. From 970db6f8237abbce67432a4140633cf17d03d665 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Thu, 3 Apr 2025 15:49:39 +0700 Subject: [PATCH 5/5] chore(web): one more clean-up nit --- web/src/engine/osk/src/banner/suggestionBanner.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/engine/osk/src/banner/suggestionBanner.ts b/web/src/engine/osk/src/banner/suggestionBanner.ts index e92e199ff4..7c153d14e4 100644 --- a/web/src/engine/osk/src/banner/suggestionBanner.ts +++ b/web/src/engine/osk/src/banner/suggestionBanner.ts @@ -182,7 +182,7 @@ export class BannerSuggestion { const projectedHeight = rawMetrics.fontBoundingBoxAscent ? rawMetrics.fontBoundingBoxAscent + rawMetrics.fontBoundingBoxDescent : 1; - let ratio = Math.min(1, format.height / projectedHeight); + const ratio = Math.min(1, format.height / projectedHeight); // do we need font-height scaling? this._textWidth = rawMetrics.width * ratio;