Вы можете реализовать свой OTF
шрифт, используя @ font-face, например:
@font-face {
font-family: GraublauWeb;
src: url("path/GraublauWeb.otf") format("opentype");
}
@font-face {
font-family: GraublauWeb;
font-weight: bold;
src: url("path/GraublauWebBold.otf") format("opentype");
}
Однако, если вы хотите поддерживать широкий спектр современных браузеров , я бы порекомендовал вам: переключитесь на WOFF
и TTF
типы шрифтов. Тип WOFF
реализован каждым основным настольным браузером, а тип TTF
является запасным вариантом для старых браузеров Safari, Android и iOS. Если ваш шрифт бесплатный, вы можете конвертировать его, например, с помощью onlinefontconverter .
@font-face {
font-family: GraublauWeb;
src: url("path/GraublauWebBold.woff") format("woff"), url("path/GraublauWebBold.ttf") format("truetype");
}
Если вы хотите поддерживать почти все браузеры, которые все еще существуют (больше не нужно, IMHO), вы должны добавить еще несколько типов шрифтов, например:
@font-face {
font-family: GraublauWeb;
src: url("webfont.eot"); /* IE9 Compat Modes */
src: url("webfont.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */
url("webfont.woff") format("woff"), /* Modern Browsers */
url("webfont.ttf") format("truetype"), /* Safari, Android, iOS */
url("webfont.svg#svgFontName") format("svg"); /* Legacy iOS */
}
Вы можете узнать больше о том, почему все эти типы реализованы и их хаки здесь . Чтобы получить подробное представление о том, какие типы файлов поддерживаются какими браузерами, см .:
@ Поддержка браузера font-face
Поддержка браузера SVG-шрифтов
надеюсь, это поможет
Потому что вы можете это сделать (это не реальный образец, но он «работает»):
private EventHandler _explicitEvent_A;
private EventHandler _explicitEvent_B;
private bool flag;
public event EventHandler ExplicitEvent {
add {
if ( flag = !flag ) { _explicitEvent_A += value; /* or do anything else */ }
else { _explicitEvent_B += value; /* or do anything else */ }
}
remove {
if ( flag = !flag ) { _explicitEvent_A -= value; /* or do anything else */ }
else { _explicitEvent_B -= value; /* or do anything else */ }
}
}
Как компилятор может узнать, что он должен делать с ExplicitEvent.RaiseEvent () ; "? Ответ: Не может.
The "ExplicitEvent.RaiseEvent ();" является только синтаксическим сахаром, который можно предсказать, только если событие реализовано неявно.
Когда вы создаете «подобное поле» событие, например:
public event EventHandler Foo;
компилятор генерирует поле и событие. В исходном коде класса, который объявляет событие, каждый раз, когда вы обращаетесь к Foo
, компилятор понимает, что вы имеете в виду поле . Однако это поле является частным, поэтому каждый раз, когда вы обращаетесь к Foo
из других классов, оно ссылается на событие (и, следовательно, на код добавления / удаления).
Если вы объявите свой собственный явный код добавления / удаления, вы не получите автоматически сгенерированное поле. Итак, у вас есть только событие, и вы не можете вызвать событие непосредственно в C # - вы можете вызвать только экземпляр делегата. Событие не является экземпляром делегата, это просто пара добавления / удаления.
Теперь ваш код содержит следующее:
public EventHandler TypicalEvent;
Это немного отличается - оно вообще не объявляло событие - оно объявляло публичное поле типа делегата EventHandler
. Любой может вызвать это, потому что значение - это просто экземпляр делегата. Важно понимать разницу между полем и событием. Вы никогда не должны писать такой код, так же как я уверен, что у вас обычно нет общедоступных полей других типов, таких как string
и int
. К сожалению, это простая опечатка, и ее относительно сложно исправить. Вы могли бы заметить это, только заметив, что компилятор позволяет вам назначать или использовать значение из другого класса.
См. Мою статью о событиях и делегатах для получения дополнительной информации.
t объявление события вообще - оно объявляло общедоступное поле типа делегата EventHandler
. Любой может вызвать это, потому что значение - это просто экземпляр делегата. Важно понимать разницу между полем и событием. Вы никогда не должны писать такой код, так же как я уверен, что у вас обычно нет общедоступных полей других типов, таких как string
и int
. К сожалению, это простая опечатка, и ее относительно сложно исправить. Вы могли бы заметить это, только заметив, что компилятор позволяет вам назначать или использовать значение из другого класса.
См. Мою статью о событиях и делегатах для получения дополнительной информации.
t объявление события вообще - оно объявляло общедоступное поле типа делегата EventHandler
. Любой может вызвать это, потому что значение - это просто экземпляр делегата. Важно понимать разницу между полем и событием. Вы никогда не должны писать такой код, так же как я уверен, что у вас обычно нет общедоступных полей других типов, таких как string
и int
. К сожалению, это простая опечатка, и ее относительно сложно исправить. Вы могли бы заметить это, только заметив, что компилятор позволяет вам назначать или использовать значение из другого класса.
См. Мою статью о событиях и делегатах для получения дополнительной информации.
Важно понимать разницу между полем и событием. Вы никогда не должны писать такой код, так же как я уверен, что у вас обычно нет общедоступных полей других типов, таких как string
и int
. К сожалению, это простая опечатка, и ее относительно сложно исправить. Вы могли бы заметить это, только заметив, что компилятор позволяет вам назначать или использовать значение из другого класса.
См. Мою статью о событиях и делегатах для получения дополнительной информации.
Важно понимать разницу между полем и событием. Вы никогда не должны писать такой код, так же как я уверен, что у вас обычно нет общедоступных полей других типов, таких как string
и int
. К сожалению, это простая опечатка, и ее относительно сложно исправить. Вы могли бы заметить это, только заметив, что компилятор позволяет вам назначать или использовать значение из другого класса.
См. Мою статью о событиях и делегатах для получения дополнительной информации.
"Простое" объявление для TypicalEvent позволяет компилятору обмануть себя. Он создает запись метаданных события, добавляет и удаляет методы и поле поддержки. Когда ваш код ссылается на TypicalEvent, компилятор переводит его в ссылку на резервное поле; когда внешний код ссылается на TypicalEvent (с использованием + = и - =), компилятор переводит его в ссылку на метод добавления или удаления.
«Явное» объявление обходит эту уловку компилятора. Вы указываете методы добавления и удаления и поле поддержки: действительно, как указывает TcKs, может даже не быть поля поддержки (это обычная причина использования явной формы: см., Например, события в System.Windows.Forms.Control). Поэтому компилятор больше не может спокойно переводить ссылку на TypicalEvent в ссылку на резервное поле: если вы хотите, чтобы резервное поле, фактический объект делегата, вы должны напрямую ссылаться на резервное поле:
_explicitEvent.RaiseEvent()