Expose emboldening in the demo UI
This commit is contained in:
parent
9b59ce2443
commit
30062aea81
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue