Expose emboldening in the demo UI

This commit is contained in:
Patrick Walton 2017-12-03 17:28:30 -08:00
parent 9b59ce2443
commit 30062aea81
5 changed files with 69 additions and 25 deletions

View File

@ -80,6 +80,12 @@
{{>partials/switch.html id="pf-stem-darkening"
title="Stem Darkening"}}
</div>
<div class="form-group">
<label for="pf-embolden">Faux Bold</label>
<input class="form-control" id="pf-embolden" type="range"
min="-0.015" max="0.015" step="0.0005" value="0.0"
autocomplete="off">
</div>
</form>
</div>
<div class="pf-arrow-box"></div>

View File

@ -35,7 +35,7 @@ export class Atlas {
pixelsPerUnit: number,
rotationAngle: number,
hint: Hint,
stemDarkeningAmount: glmatrix.vec2):
emboldenAmount: glmatrix.vec2):
void {
let nextOrigin = glmatrix.vec2.fromValues(1.0, 1.0);
let shelfBottom = 2.0;
@ -46,7 +46,7 @@ export class Atlas {
if (metrics == null)
continue;
const unitMetrics = new UnitMetrics(metrics, rotationAngle, stemDarkeningAmount);
const unitMetrics = new UnitMetrics(metrics, rotationAngle, emboldenAmount);
glyph.setPixelLowerLeft(nextOrigin, unitMetrics, pixelsPerUnit);
let pixelOrigin = glyph.calculateSubpixelOrigin(pixelsPerUnit);

View File

@ -122,6 +122,7 @@ class TextDemoController extends DemoAppController<TextDemoView> {
atlasGlyphs: AtlasGlyph[];
private hintingSelect: HTMLSelectElement;
private emboldenInput: HTMLInputElement;
private editTextModal: HTMLElement;
private editTextArea: HTMLTextAreaElement;
@ -132,6 +133,7 @@ class TextDemoController extends DemoAppController<TextDemoView> {
private _fontSize: number;
private _rotationAngle: number;
private _emboldenAmount: number;
private text: string;
@ -146,11 +148,16 @@ class TextDemoController extends DemoAppController<TextDemoView> {
this._fontSize = INITIAL_FONT_SIZE;
this._rotationAngle = 0.0;
this._emboldenAmount = 0.0;
this.hintingSelect = unwrapNull(document.getElementById('pf-hinting-select')) as
HTMLSelectElement;
this.hintingSelect.addEventListener('change', () => this.hintingChanged(), false);
this.emboldenInput = unwrapNull(document.getElementById('pf-embolden')) as
HTMLInputElement;
this.emboldenInput.addEventListener('input', () => this.emboldenAmountChanged(), false);
this.editTextModal = unwrapNull(document.getElementById('pf-edit-text-modal'));
this.editTextArea = unwrapNull(document.getElementById('pf-edit-text-area')) as
HTMLTextAreaElement;
@ -167,6 +174,10 @@ class TextDemoController extends DemoAppController<TextDemoView> {
window.jQuery(this.editTextModal).modal();
}
get emboldenAmount(): number {
return this._emboldenAmount;
}
protected createView(gammaLUT: HTMLImageElement,
commonShaderSource: string,
shaderSources: ShaderMap<ShaderProgramSource>):
@ -183,6 +194,11 @@ class TextDemoController extends DemoAppController<TextDemoView> {
this.view.then(view => view.renderer.updateHinting());
}
private emboldenAmountChanged(): void {
this._emboldenAmount = parseFloat(this.emboldenInput.value);
this.view.then(view => view.renderer.updateEmboldenAmount());
}
private updateText(): void {
this.text = this.editTextArea.value;
window.jQuery(this.editTextModal).modal('hide');
@ -246,8 +262,12 @@ class TextDemoController extends DemoAppController<TextDemoView> {
this.view.then(view => view.renderer.relayoutText());
}
get unitsPerEm(): number {
return this.font.opentypeFont.unitsPerEm;
}
get pixelsPerUnit(): number {
return this._fontSize / this.font.opentypeFont.unitsPerEm;
return this._fontSize / this.unitsPerEm;
}
get useHinting(): boolean {
@ -391,6 +411,12 @@ class TextDemoRenderer extends TextRenderer {
return this.renderContext.appController.rotationAngle;
}
protected get extraEmboldenAmount(): glmatrix.vec2 {
const appController = this.renderContext.appController;
const emboldenLength = appController.emboldenAmount * appController.unitsPerEm;
return glmatrix.vec2.clone([emboldenLength, emboldenLength]);
}
prepareToAttachText(): void {
if (this.atlasFramebuffer == null)
this.createAtlasFramebuffer();
@ -428,6 +454,13 @@ class TextDemoRenderer extends TextRenderer {
this.renderContext.setDirty();
}
updateEmboldenAmount(): void {
// Likewise, need to relayout the text.
this.layoutText();
this.buildGlyphs();
this.renderContext.setDirty();
}
viewPanned(): void {
this.buildGlyphs();
this.renderContext.setDirty();
@ -513,7 +546,7 @@ class TextDemoRenderer extends TextRenderer {
run.recalculatePixelRects(pixelsPerUnit,
rotationAngle,
hint,
this.stemDarkeningAmount,
this.emboldenAmount,
SUBPIXEL_GRANULARITY,
textBounds);
@ -638,7 +671,7 @@ class TextDemoRenderer extends TextRenderer {
const atlasGlyphUnitMetrics = new UnitMetrics(atlasGlyphMetrics,
rotationAngle,
this.stemDarkeningAmount);
this.emboldenAmount);
const atlasGlyphPixelOrigin =
atlasGlyph.calculateSubpixelOrigin(pixelsPerUnit);

View File

@ -81,7 +81,9 @@ export abstract class TextRenderer extends Renderer {
}
get emboldenAmount(): glmatrix.vec2 {
return this.stemDarkeningAmount;
const emboldenAmount = glmatrix.vec2.create();
glmatrix.vec2.add(emboldenAmount, this.extraEmboldenAmount, this.stemDarkeningAmount);
return emboldenAmount;
}
get bgColor(): glmatrix.vec4 {
@ -127,6 +129,10 @@ export abstract class TextRenderer extends Renderer {
return this.meshes == null ? 0 : this.meshes.length;
}
protected get extraEmboldenAmount(): glmatrix.vec2 {
return glmatrix.vec2.create();
}
private stemDarkening: StemDarkeningMode;
private subpixelAA: SubpixelAAType;
@ -162,9 +168,7 @@ export abstract class TextRenderer extends Renderer {
const atlasGlyphMetrics = font.metricsForGlyph(glyph.glyphKey.id);
if (atlasGlyphMetrics == null)
continue;
const atlasUnitMetrics = new UnitMetrics(atlasGlyphMetrics,
0.0,
this.stemDarkeningAmount);
const atlasUnitMetrics = new UnitMetrics(atlasGlyphMetrics, 0.0, this.emboldenAmount);
const pathID = glyph.pathID;
boundingRects[pathID * 4 + 0] = atlasUnitMetrics.left;
@ -201,7 +205,8 @@ export abstract class TextRenderer extends Renderer {
protected clearForDirectRendering(): void {}
protected buildAtlasGlyphs(atlasGlyphs: AtlasGlyph[]): void {
const font = this.renderContext.font;
const renderContext = this.renderContext;
const font = renderContext.font;
const pixelsPerUnit = this.pixelsPerUnit;
const rotationAngle = this.rotationAngle;
const hint = this.createHint();
@ -211,13 +216,13 @@ export abstract class TextRenderer extends Renderer {
if (atlasGlyphs.length === 0)
return;
this.renderContext.atlasGlyphs = atlasGlyphs;
this.renderContext.atlas.layoutGlyphs(atlasGlyphs,
font,
pixelsPerUnit,
rotationAngle,
hint,
this.stemDarkeningAmount);
renderContext.atlasGlyphs = atlasGlyphs;
renderContext.atlas.layoutGlyphs(atlasGlyphs,
font,
pixelsPerUnit,
rotationAngle,
hint,
this.emboldenAmount);
this.uploadPathTransforms(1);
this.uploadPathColors(1);
@ -250,10 +255,10 @@ export abstract class TextRenderer extends Renderer {
// the ascenders and x-heights of the glyphs are pixel snapped, while they aren't on macOS.
// But we should really figure out what macOS does…
const ascender = this.renderContext.font.opentypeFont.ascender;
const stemDarkeningAmount = this.stemDarkeningAmount;
const stemDarkeningYScale = (ascender + stemDarkeningAmount[1]) / ascender;
const emboldenAmount = this.emboldenAmount;
const stemDarkeningYScale = (ascender + emboldenAmount[1]) / ascender;
const stemDarkeningOffset = glmatrix.vec2.clone(stemDarkeningAmount);
const stemDarkeningOffset = glmatrix.vec2.clone(emboldenAmount);
glmatrix.vec2.scale(stemDarkeningOffset, stemDarkeningOffset, pixelsPerUnit);
glmatrix.vec2.scale(stemDarkeningOffset, stemDarkeningOffset, SQRT_1_2);
glmatrix.vec2.mul(stemDarkeningOffset, stemDarkeningOffset, [1, stemDarkeningYScale]);

View File

@ -167,13 +167,13 @@ export class TextRun {
recalculatePixelRects(pixelsPerUnit: number,
rotationAngle: number,
hint: Hint,
stemDarkeningAmount: glmatrix.vec2,
emboldenAmount: glmatrix.vec2,
subpixelGranularity: number,
textFrameBounds: glmatrix.vec4):
void {
for (let index = 0; index < this.glyphIDs.length; index++) {
const metrics = unwrapNull(this.font.metricsForGlyph(this.glyphIDs[index]));
const unitMetrics = new UnitMetrics(metrics, rotationAngle, stemDarkeningAmount);
const unitMetrics = new UnitMetrics(metrics, rotationAngle, emboldenAmount);
const textGlyphOrigin = this.calculatePixelOriginForGlyphAt(index,
pixelsPerUnit,
rotationAngle,
@ -381,11 +381,11 @@ export class UnitMetrics {
ascent: number;
descent: number;
constructor(metrics: Metrics, rotationAngle: number, stemDarkeningAmount: glmatrix.vec2) {
constructor(metrics: Metrics, rotationAngle: number, emboldenAmount: glmatrix.vec2) {
const left = metrics.xMin;
const bottom = metrics.yMin;
const right = metrics.xMax + stemDarkeningAmount[0] * 2;
const top = metrics.yMax + stemDarkeningAmount[1] * 2;
const right = metrics.xMax + emboldenAmount[0] * 2;
const top = metrics.yMax + emboldenAmount[1] * 2;
const transform = glmatrix.mat2.create();
glmatrix.mat2.fromRotation(transform, -rotationAngle);