diff --git a/client/src/app/core/ui-services/load-font.service.ts b/client/src/app/core/ui-services/load-font.service.ts index 8b1fa3037..a92e2488d 100644 --- a/client/src/app/core/ui-services/load-font.service.ts +++ b/client/src/app/core/ui-services/load-font.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@angular/core'; import { ConfigService } from './config.service'; +import { FontConfigObject } from './media-manage.service'; /** * Enables the usage of the FontFace constructor @@ -10,7 +11,7 @@ declare let FontFace: any; /** * The linter refuses to allow Document['fonts']. * Since Document.fonts is working draft since 2016, typescript - * dies not yet support it natively (even though it exists in normal browsers) + * does not yet support it natively (even though it exists in normal browsers) */ interface FontDocument extends Document { fonts: any; @@ -40,23 +41,33 @@ export class LoadFontService { } /** - * Observes and loads custom fonts for the projector. - * Currently, normal and regular fonts can be considered, since - * italic fonts can easily be calculated by the browser. + * Observes and loads custom fonts. * Falls back to the normal OSFont when no custom font was set. */ private loadCustomFont(): void { - this.configService.get('font_regular').subscribe(regular => { + this.configService.get('font_regular').subscribe(regular => { if (regular) { this.setCustomProjectorFont(regular, 400); } }); - this.configService.get('font_bold').subscribe(bold => { + this.configService.get('font_bold').subscribe(bold => { if (bold) { this.setCustomProjectorFont(bold, 500); } }); + + this.configService.get('font_monospace').subscribe(mono => { + if (mono) { + this.setNewFontFace('OSFont Monospace', mono.path || mono.default); + } + }); + + this.configService.get('font_chyron_speaker_name').subscribe(chyronFont => { + if (chyronFont) { + this.setNewFontFace('OSFont ChyronName', chyronFont.path || chyronFont.default); + } + }); } /** @@ -66,20 +77,24 @@ export class LoadFontService { * @param font the font object from the config service * @param weight the desired weight of the font */ - private setCustomProjectorFont(font: any, weight: number): void { - const path = font.path ? font.path : font.default; + private setCustomProjectorFont(font: FontConfigObject, weight: number): void { + const path = font.path || font.default; if (!path) { return; } - const url = font.path ? `${this.urlPrefix}${path}` : path; - const fontFace = new FontFace('customProjectorFont', `url(${url})`, { weight: weight }); - fontFace + const url: string = font.path ? `${this.urlPrefix}${path}` : path; + this.setNewFontFace('customProjectorFont', url, weight); + } + + private setNewFontFace(fontName: string, fontPath: string, weight: number = 400): void { + const customFont = new FontFace(fontName, `url(${fontPath})`, { weight: weight }); + customFont .load() .then(res => { (document as FontDocument).fonts.add(res); }) .catch(error => { - console.error(error); + console.log(error); }); } } diff --git a/client/src/app/shared/components/contdown-time/countdown-time.component.ts b/client/src/app/shared/components/contdown-time/countdown-time.component.ts index ed46a4ccf..c16721128 100644 --- a/client/src/app/shared/components/contdown-time/countdown-time.component.ts +++ b/client/src/app/shared/components/contdown-time/countdown-time.component.ts @@ -1,10 +1,6 @@ -import { Component, Input, OnDestroy, OnInit } from '@angular/core'; +import { Component, Input, OnDestroy } from '@angular/core'; import { ServertimeService } from 'app/core/core-services/servertime.service'; -import { ConfigService } from 'app/core/ui-services/config.service'; -import { FontConfigObject } from 'app/core/ui-services/media-manage.service'; - -declare let FontFace: any; export interface CountdownData { running: boolean; @@ -19,7 +15,7 @@ export interface CountdownData { templateUrl: './countdown-time.component.html', styleUrls: ['./countdown-time.component.scss'] }) -export class CountdownTimeComponent implements OnInit, OnDestroy { +export class CountdownTimeComponent implements OnDestroy { /** * The time in seconds to make the countdown orange, is the countdown is below this value. */ @@ -96,23 +92,7 @@ export class CountdownTimeComponent implements OnInit, OnDestroy { return this._countdown; } - public constructor(private servertimeService: ServertimeService, private configService: ConfigService) {} - - public ngOnInit(): void { - this.configService.get('font_monospace').subscribe(font => { - if (font) { - const customFont = new FontFace('OSFont Monospace', `url(${font.path || font.default})`); - customFont - .load() - .then(res => { - (document as any).fonts.add(res); - }) - .catch(error => { - console.log(error); - }); - } - }); - } + public constructor(private servertimeService: ServertimeService) {} /** * Updates the countdown time and string format it. diff --git a/client/src/app/site/mediafiles/models/view-mediafile.ts b/client/src/app/site/mediafiles/models/view-mediafile.ts index 7e37e6835..376ec4a69 100644 --- a/client/src/app/site/mediafiles/models/view-mediafile.ts +++ b/client/src/app/site/mediafiles/models/view-mediafile.ts @@ -6,7 +6,33 @@ import { Searchable } from 'app/site/base/searchable'; import { ViewGroup } from 'app/site/users/models/view-group'; export const IMAGE_MIMETYPES = ['image/png', 'image/jpeg', 'image/gif']; -export const FONT_MIMETYPES = ['font/ttf', 'font/woff', 'application/font-woff', 'application/font-sfnt']; + +export const FONT_MIMETYPES = [ + /** + * Standard fonts by iana May 2021. See: + * https://www.iana.org/assignments/media-types/media-types.xhtml#font + */ + 'font/ttf', + 'font/sfnt', + 'font/otf', + 'font/woff', + 'font/woff2', + /** + * Non standard types + */ + /** (IANA: March 2013) (special non standard OTF fonts) */ + 'font/opentype', + 'application/x-font-opentype', + 'application/vnd.oasis.opendocument.formula-template', + /** (IANA: January 2013) */ + 'application/font-woff', + /** (W3C W./E.Draft: May 2014/March 2016) */ + 'application/font-woff2', + /** (IANA: March 2013) */ + 'application/font-sfnt', + 'application/x-font-ttf', + 'application/x-font-truetype' +]; export const PDF_MIMETYPES = ['application/pdf']; export const VIDEO_MIMETYPES = [ 'video/quicktime', diff --git a/client/src/app/slides/agenda/current-speaker-chyron/current-speaker-chyron-slide-data.ts b/client/src/app/slides/agenda/current-speaker-chyron/current-speaker-chyron-slide-data.ts index 40aa57933..abcaeb68d 100644 --- a/client/src/app/slides/agenda/current-speaker-chyron/current-speaker-chyron-slide-data.ts +++ b/client/src/app/slides/agenda/current-speaker-chyron/current-speaker-chyron-slide-data.ts @@ -1,5 +1,6 @@ export interface CurrentSpeakerChyronSlideData { - current_speaker?: string; + current_speaker_name?: string; + current_speaker_level?: string; background_color: string; font_color: string; } diff --git a/client/src/app/slides/agenda/current-speaker-chyron/current-speaker-chyron-slide.component.html b/client/src/app/slides/agenda/current-speaker-chyron/current-speaker-chyron-slide.component.html index cbbfdef05..c03bc7fac 100644 --- a/client/src/app/slides/agenda/current-speaker-chyron/current-speaker-chyron-slide.component.html +++ b/client/src/app/slides/agenda/current-speaker-chyron/current-speaker-chyron-slide.component.html @@ -1,8 +1,13 @@ -
- +
- {{ data.data.current_speaker }} +
{{ data.data.current_speaker_name }}
+
{{ data.data.current_speaker_level }}
diff --git a/client/src/app/slides/agenda/current-speaker-chyron/current-speaker-chyron-slide.component.scss b/client/src/app/slides/agenda/current-speaker-chyron/current-speaker-chyron-slide.component.scss index 94643ba73..6b3024190 100644 --- a/client/src/app/slides/agenda/current-speaker-chyron/current-speaker-chyron-slide.component.scss +++ b/client/src/app/slides/agenda/current-speaker-chyron/current-speaker-chyron-slide.component.scss @@ -1,19 +1,33 @@ +@import '~assets/styles/fonts.scss'; + #chyron { position: absolute; - left: 0; - bottom: 0; + left: 50px; + bottom: 20px; + right: 0; z-index: 10; - width: 100%; - height: 100px; + height: 80px; font-size: 32px; - text-align: center; - line-height: 1.1; - display: table; + text-align: left; + line-height: 1; + opacity: 0.8; #inner { - display: table-cell; vertical-align: middle; - padding-left: 20px; + padding-left: 18px; padding-right: 20px; + padding-top: 10px; + padding-bottom: 10px; + height: 60px; + display: table-cell; + + #inner-name { + font-family: $font-chyronname; + } + + #inner-level { + margin-top: 5px; + font-size: 70%; + } } } diff --git a/client/src/assets/styles/font-variables.scss b/client/src/assets/styles/font-variables.scss index 02b36fb17..2d4dc059d 100644 --- a/client/src/assets/styles/font-variables.scss +++ b/client/src/assets/styles/font-variables.scss @@ -25,3 +25,8 @@ $font-weight-condensed-regular: 400; $font-monospace: 'OSFont Monospace'; $font-monospace-src: url('../fonts/roboto-condensed-bold.woff') format('woff'); $font-weight-monospace: 400; + +/** Special Chyron Name Font */ +$font-chyronname: 'OSFont ChyronName'; +$font-chyronname-src: url('../fonts/fira-sans-latin-400.woff') format('woff'); +$font-weight-chyronname: 400; diff --git a/client/src/assets/styles/fonts.scss b/client/src/assets/styles/fonts.scss index 489397cc0..b9f83c7a5 100644 --- a/client/src/assets/styles/fonts.scss +++ b/client/src/assets/styles/fonts.scss @@ -53,3 +53,12 @@ font-weight: $font-weight-monospace; src: $font-monospace-src; } + +/** Chyron Name */ +@font-face { + font-family: $font-chyronname; + font-style: normal; + font-display: swap; + font-weight: $font-weight-chyronname; + src: $font-chyronname-src; +} diff --git a/server/openslides/core/config_variables.py b/server/openslides/core/config_variables.py index d8d520226..58bad5d61 100644 --- a/server/openslides/core/config_variables.py +++ b/server/openslides/core/config_variables.py @@ -478,6 +478,7 @@ def get_config_variables(): "font_bold", "font_bold_italic", "font_monospace", + "font_chyron_speaker_name", ], weight=320, group="Font", @@ -549,6 +550,19 @@ def get_config_variables(): hidden=True, ) + yield ConfigVariable( + name="font_chyron_speaker_name", + default_value={ + "display_name": "Font for speaker name (chyron)", + "default": "assets/fonts/fira-sans-latin-400.woff", + "path": "", + }, + input_type="static", + weight=321, + group="Font", + hidden=True, + ) + # Custom translations yield ConfigVariable( name="translations",