mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-22 17:47:16 +00:00
More font properties, including True Type fonts
This commit is contained in:
parent
09d1fef1ab
commit
e82f3ccdb3
8 changed files with 223 additions and 3 deletions
|
|
@ -1,9 +1,11 @@
|
|||
import Bitmap from "./skin/Bitmap";
|
||||
import TrueTypeFont from "./skin/TrueTypeFont";
|
||||
import { assert } from "./utils";
|
||||
|
||||
class UIRoot {
|
||||
// Just a temporary place to stash things
|
||||
_bitmaps: Bitmap[] = [];
|
||||
_trueTypeFonts: TrueTypeFont[] = [];
|
||||
|
||||
addBitmap(bitmap: Bitmap) {
|
||||
this._bitmaps.push(bitmap);
|
||||
|
|
@ -17,6 +19,19 @@ class UIRoot {
|
|||
assert(found != null, `Could not find bitmap with id ${id}.`);
|
||||
return found;
|
||||
}
|
||||
|
||||
addTrueTypeFont(font: TrueTypeFont) {
|
||||
this._trueTypeFonts.push(font);
|
||||
}
|
||||
|
||||
getTrueTypeFont(id: string): TrueTypeFont {
|
||||
const found = this._trueTypeFonts.find(
|
||||
(font) => font._id.toLowerCase() === id.toLowerCase()
|
||||
);
|
||||
|
||||
assert(found != null, `Could not find bitmap with id ${id}.`);
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
// Global Singleton for now
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ export default class Bitmap {
|
|||
return true;
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
getWidth() {
|
||||
return this._width;
|
||||
}
|
||||
|
|
@ -73,9 +77,19 @@ export default class Bitmap {
|
|||
this.setUrl(imgUrl);
|
||||
}
|
||||
|
||||
getBackgrondCSSAttribute(): string {
|
||||
getBackgrondImageCSSAttribute(): string {
|
||||
return `url(${this._url})`;
|
||||
}
|
||||
|
||||
getBackgrondPositionCSSAttribute(): string {
|
||||
const x = Utils.px(-this._x);
|
||||
const y = Utils.px(-this._y);
|
||||
return `${x} ${y}`;
|
||||
}
|
||||
|
||||
getBackgrondSizeCSSAttribute(): string {
|
||||
const width = Utils.px(this._width);
|
||||
const height = Utils.px(this._height);
|
||||
return `url(${this._url}) ${width} ${height}`;
|
||||
return `${width} ${height}`;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,41 @@
|
|||
import GuiObj from "./GuiObj";
|
||||
import UI_ROOT from "../UIRoot";
|
||||
import { px } from "../utils";
|
||||
|
||||
// http://wiki.winamp.com/wiki/XML_GUI_Objects#.3Cbutton.2F.3E_.26_.3Ctogglebutton.2F.3E
|
||||
export default class Button extends GuiObj {
|
||||
_image: string;
|
||||
setXmlAttr(key: string, value: string): boolean {
|
||||
if (super.setXmlAttr(key, value)) {
|
||||
return true;
|
||||
}
|
||||
switch (key) {
|
||||
case "image":
|
||||
this._image = value;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
getDebugDom(): HTMLDivElement {
|
||||
const div = super.getDebugDom();
|
||||
div.setAttribute("data-obj-name", "Button");
|
||||
if (this._image != null) {
|
||||
const bitmap = UI_ROOT.getBitmap(this._image);
|
||||
div.style.backgroundImage = bitmap.getBackgrondImageCSSAttribute();
|
||||
div.style.backgroundPosition = bitmap.getBackgrondPositionCSSAttribute();
|
||||
if (div.style.width === "" && bitmap.getWidth()) {
|
||||
div.style.width = px(bitmap.getWidth());
|
||||
}
|
||||
if (div.style.height === "" && bitmap.getHeight()) {
|
||||
div.style.height = px(bitmap.getHeight());
|
||||
}
|
||||
}
|
||||
return div;
|
||||
}
|
||||
|
||||
/*
|
||||
extern Button.onActivate(int activated);
|
||||
extern Button.onLeftClick();
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ export default class Layer extends GuiObj {
|
|||
div.setAttribute("data-obj-name", "Layer");
|
||||
if (this._image != null) {
|
||||
const bitmap = UI_ROOT.getBitmap(this._image);
|
||||
div.style.background = bitmap.getBackgrondCSSAttribute();
|
||||
div.style.backgroundImage = bitmap.getBackgrondImageCSSAttribute();
|
||||
div.style.backgroundPosition = bitmap.getBackgrondPositionCSSAttribute();
|
||||
if (div.style.width === "" && bitmap.getWidth()) {
|
||||
div.style.width = px(bitmap.getWidth());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,118 @@
|
|||
import GuiObj from "./GuiObj";
|
||||
import * as Utils from "../utils";
|
||||
import UI_ROOT from "../UIRoot";
|
||||
|
||||
// http://wiki.winamp.com/wiki/XML_GUI_Objects#.3Ctext.2F.3E_.26_.3CWasabi:Text.2F.3E
|
||||
export default class Text extends GuiObj {
|
||||
_display: string;
|
||||
_text: string;
|
||||
_bold: boolean;
|
||||
_forceupcase: boolean;
|
||||
_forceuppercase: boolean;
|
||||
_forcelocase: boolean;
|
||||
_forcelowercase: boolean;
|
||||
_align: string;
|
||||
_font: string;
|
||||
_fontSize: number;
|
||||
setXmlAttr(key: string, value: string): boolean {
|
||||
if (super.setXmlAttr(key, value)) {
|
||||
return true;
|
||||
}
|
||||
switch (key) {
|
||||
case "display":
|
||||
// (str) Either a specific system display string or the string identifier of a text feed. Setting this value will override the text parameter. See below.
|
||||
this._display = value;
|
||||
break;
|
||||
case "text":
|
||||
// (str) A static string to be displayed.
|
||||
this._text = value;
|
||||
break;
|
||||
case "bold":
|
||||
// (str) A static string to be displayed.
|
||||
this._bold = Utils.toBool(value);
|
||||
break;
|
||||
case "forceupcase":
|
||||
// (bool) Force the system to make the display string all uppercase before display.
|
||||
this._forceupcase = Utils.toBool(value);
|
||||
break;
|
||||
case "forceuppercase":
|
||||
// (bool) Force the system to make the display string all uppercase before display.
|
||||
this._forceuppercase = Utils.toBool(value);
|
||||
break;
|
||||
case "font":
|
||||
// (id) The id of a bitmapfont or truetypefont element. If no element with that id can be found, the OS will be asked for a font with that name instead.
|
||||
this._font = value;
|
||||
break;
|
||||
case "align":
|
||||
// (str) One of the following three possible strings: "left" "center" "right" -- Default is "left."
|
||||
this._align = value;
|
||||
break;
|
||||
case "fontsize":
|
||||
// (int) The size to render the chosen font.
|
||||
this._fontSize = Utils.num(value);
|
||||
/*
|
||||
ticker - (bool) Setting this flag causes the object to scroll left and right if the text does not fit the rectangular area of the text object.
|
||||
antialias - (bool) Setting this flag causes the text to be rendered antialiased if possible.
|
||||
default - (str) A parameter alias for text.
|
||||
align - (str) One of the following three possible strings: "left" "center" "right" -- Default is "left."
|
||||
valign - (str) One of the following three possible strings: "top" "center" "bottom" -- Default is "top."
|
||||
color - (int) The comma delimited RGB color of the text.
|
||||
shadowcolor - (int) The comma delimited RGB color for underrendered shadow text.
|
||||
shadowx - (int) The x offset of the shadowrender.
|
||||
shadowy - (int) The y offset of the shadowrender.
|
||||
timeroffstyle - (int) How to display an empty timer: "0" = " : ", "1" = "00:00", and "2"="" (if one is displaying time)
|
||||
timecolonwidth - (int) How many extra pixels wider or smaller should the colon be when displaying time. Default is -1.
|
||||
nograb - (bool) Setting this flag will cause the text object to ignore left button down messages. Default is off.
|
||||
showlen - (bool) Setting this flag will cause the text display to be appended with the length in minutes and seconds of the current song. Default is off.
|
||||
forcefixed - (bool) Force the system to attempt to render the display string with fixed-width font spacing.
|
||||
forcelocase - (bool) Force the system to make the display string all lowercase before display.
|
||||
forcelowercase - (bool) Force the system to make the display string all lowercase before display.
|
||||
bold - (bool) Render the display string in bold.
|
||||
wrap - (bool) Setting this flag will cause the text to wrap in its rectangular space. Default is off.
|
||||
dblclickaction - (str) A string in the form "SWITCH;layout" where layout is the id of a layout in this object's parent container. No other actions function on this object. This action is deprecated.
|
||||
offsetx - (int) Extra pixels to be added to or subtracted from the calculated x value for the display string to render.
|
||||
offsety - (int) Extra pixels to be added to or subtracted from the calculated x value for the display string to render.
|
||||
*/
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
getText() {
|
||||
switch (this._display) {
|
||||
case "time":
|
||||
return "01:58";
|
||||
case "songname":
|
||||
return "Niente da Caprie (3";
|
||||
case "songinfo":
|
||||
return "112kbps stereo 44.";
|
||||
default:
|
||||
throw new Error(`Unknown text display name: "${this._display}".`);
|
||||
}
|
||||
return this._display ?? this._text;
|
||||
}
|
||||
|
||||
getDebugDom(): HTMLDivElement {
|
||||
const div = super.getDebugDom();
|
||||
div.innerText = this.getText();
|
||||
if (this._bold) {
|
||||
div.style.fontWeight = "bold";
|
||||
}
|
||||
if (this._align) {
|
||||
div.style.textAlign = this._align;
|
||||
}
|
||||
|
||||
if (this._font) {
|
||||
const font = UI_ROOT.getTrueTypeFont(this._font);
|
||||
div.style.fontFamily = font.getFontFamily();
|
||||
}
|
||||
|
||||
div.style.fontSize = Utils.px(this._fontSize ?? 14);
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
extern Text.setText(String txt); // changes the display/text="something" param
|
||||
|
|
|
|||
55
packages/webamp-modern-2/src/skin/TrueTypeFont.ts
Normal file
55
packages/webamp-modern-2/src/skin/TrueTypeFont.ts
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
import * as Utils from "../utils";
|
||||
import ImageManager from "./ImageManager";
|
||||
|
||||
export default class TrueTypeFont {
|
||||
_file: string;
|
||||
_id: string;
|
||||
_fontFace: FontFace;
|
||||
|
||||
setXmlAttributes(attributes: { [attrName: string]: string }) {
|
||||
for (const [key, value] of Object.entries(attributes)) {
|
||||
this.setXmlAttr(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
setXmlAttr(key: string, value: string) {
|
||||
switch (key) {
|
||||
case "id":
|
||||
this._id = value;
|
||||
break;
|
||||
case "file":
|
||||
this._file = value;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
getFontFamily() {
|
||||
return this._fontFace.family;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
document.fonts.delete(this._fontFace);
|
||||
}
|
||||
|
||||
// Ensure we've loaded the font into our asset loader.
|
||||
async ensureFontLoaded(imageManager: ImageManager) {
|
||||
Utils.assert(
|
||||
this._fontFace == null,
|
||||
"Tried to ensure a TrueTypeFont was laoded more than once."
|
||||
);
|
||||
const fontUrl = await imageManager.getUrl(this._file);
|
||||
|
||||
const sanitizedFile = this._file.replace(/\./, "_");
|
||||
const fontFamily = `font-${Utils.getId()}-${this.getId()}-${sanitizedFile}`;
|
||||
|
||||
const font = new FontFace(fontFamily, `url(${fontUrl})`);
|
||||
this._fontFace = await font.load();
|
||||
document.fonts.add(this._fontFace);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ import Status from "./Status";
|
|||
import { parse as parseMaki } from "../maki/parser";
|
||||
import SystemObject from "./SystemObject";
|
||||
import ToggleButton from "./ToggleButton";
|
||||
import TrueTypeFont from "./TrueTypeFont";
|
||||
|
||||
class ParserContext {
|
||||
container: Container | null = null;
|
||||
|
|
@ -166,6 +167,7 @@ export default class SkinParser {
|
|||
node.children.length === 0,
|
||||
"Unexpected children in <bitmapFont> XML node."
|
||||
);
|
||||
console.log(node);
|
||||
}
|
||||
|
||||
async text(node: XmlElement) {
|
||||
|
|
@ -416,6 +418,11 @@ export default class SkinParser {
|
|||
node.children.length === 0,
|
||||
"Unexpected children in <truetypefont> XML node."
|
||||
);
|
||||
const font = new TrueTypeFont();
|
||||
font.setXmlAttributes(node.attributes);
|
||||
await font.ensureFontLoaded(this._imageManager);
|
||||
|
||||
UI_ROOT.addTrueTypeFont(font);
|
||||
}
|
||||
|
||||
async include(node: XmlElement) {
|
||||
|
|
|
|||
|
|
@ -33,3 +33,8 @@ export function toBool(str: string) {
|
|||
assert(str === "0" || str === "1", 'Expected bool value to be "0" or "1".');
|
||||
return str === "1";
|
||||
}
|
||||
|
||||
let id = 0;
|
||||
export function getId(): number {
|
||||
return id++;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue