mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 04:12:46 +02:00
Whitelist TTS scripting interface to TTS app, which is now a default script
This commit is contained in:
parent
1eca1bfd55
commit
1d8994993c
7 changed files with 363 additions and 6 deletions
304
interface/resources/qml/hifi/tts/TTS.qml
Normal file
304
interface/resources/qml/hifi/tts/TTS.qml
Normal file
|
@ -0,0 +1,304 @@
|
||||||
|
//
|
||||||
|
// TTS.qml
|
||||||
|
//
|
||||||
|
// TTS App
|
||||||
|
//
|
||||||
|
// Created by Zach Fox on 2018-10-10
|
||||||
|
// Copyright 2018 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
import Hifi 1.0 as Hifi
|
||||||
|
import QtQuick 2.10
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
|
import "qrc:////qml//styles-uit" as HifiStylesUit
|
||||||
|
import "qrc:////qml//controls-uit" as HifiControlsUit
|
||||||
|
import "qrc:////qml//controls" as HifiControls
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
HifiStylesUit.HifiConstants { id: hifi; }
|
||||||
|
|
||||||
|
id: root;
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.darkGray;
|
||||||
|
property bool keyboardRaised: false;
|
||||||
|
|
||||||
|
//
|
||||||
|
// TITLE BAR START
|
||||||
|
//
|
||||||
|
Item {
|
||||||
|
id: titleBarContainer;
|
||||||
|
// Size
|
||||||
|
width: root.width;
|
||||||
|
height: 50;
|
||||||
|
// Anchors
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.top: parent.top;
|
||||||
|
|
||||||
|
// Title bar text
|
||||||
|
HifiStylesUit.RalewaySemiBold {
|
||||||
|
id: titleBarText;
|
||||||
|
text: "Text-to-Speech";
|
||||||
|
// Text size
|
||||||
|
size: hifi.fontSizes.overlayTitle;
|
||||||
|
// Anchors
|
||||||
|
anchors.top: parent.top;
|
||||||
|
anchors.bottom: parent.bottom;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.leftMargin: 16;
|
||||||
|
width: paintedWidth;
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.lightGrayText;
|
||||||
|
// Alignment
|
||||||
|
horizontalAlignment: Text.AlignHLeft;
|
||||||
|
verticalAlignment: Text.AlignVCenter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separator
|
||||||
|
HifiControlsUit.Separator {
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
anchors.bottom: parent.bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// TITLE BAR END
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: tagButtonContainer;
|
||||||
|
anchors.top: titleBarContainer.bottom;
|
||||||
|
anchors.topMargin: 2;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
height: 70;
|
||||||
|
|
||||||
|
HifiStylesUit.RalewaySemiBold {
|
||||||
|
id: tagButtonTitle;
|
||||||
|
text: "Insert Tag:";
|
||||||
|
// Text size
|
||||||
|
size: 18;
|
||||||
|
// Anchors
|
||||||
|
anchors.top: parent.top;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
height: 35;
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.lightGrayText;
|
||||||
|
// Alignment
|
||||||
|
horizontalAlignment: Text.AlignHCenter;
|
||||||
|
verticalAlignment: Text.AlignVCenter;
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: pitch10Button;
|
||||||
|
focusPolicy: Qt.NoFocus;
|
||||||
|
color: hifi.buttons.none;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.top: tagButtonTitle.bottom;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.leftMargin: 3;
|
||||||
|
width: parent.width/6 - 6;
|
||||||
|
height: 30;
|
||||||
|
text: "Pitch 10";
|
||||||
|
onClicked: {
|
||||||
|
messageToSpeak.insert(messageToSpeak.cursorPosition, "<pitch absmiddle='10'/>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: pitch0Button;
|
||||||
|
focusPolicy: Qt.NoFocus;
|
||||||
|
color: hifi.buttons.none;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.top: tagButtonTitle.bottom;
|
||||||
|
anchors.left: pitch10Button.right;
|
||||||
|
anchors.leftMargin: 6;
|
||||||
|
width: parent.width/6 - anchors.leftMargin;
|
||||||
|
height: 30;
|
||||||
|
text: "Pitch 0";
|
||||||
|
onClicked: {
|
||||||
|
messageToSpeak.insert(messageToSpeak.cursorPosition, "<pitch absmiddle='0'/>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: pitchNeg10Button;
|
||||||
|
focusPolicy: Qt.NoFocus;
|
||||||
|
color: hifi.buttons.none;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.top: tagButtonTitle.bottom;
|
||||||
|
anchors.left: pitch0Button.right;
|
||||||
|
anchors.leftMargin: 6;
|
||||||
|
width: parent.width/6 - anchors.leftMargin;
|
||||||
|
height: 30;
|
||||||
|
text: "Pitch -10";
|
||||||
|
onClicked: {
|
||||||
|
messageToSpeak.insert(messageToSpeak.cursorPosition, "<pitch absmiddle='-10'/>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: speed5Button;
|
||||||
|
focusPolicy: Qt.NoFocus;
|
||||||
|
color: hifi.buttons.none;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.top: tagButtonTitle.bottom;
|
||||||
|
anchors.left: pitchNeg10Button.right;
|
||||||
|
anchors.leftMargin: 6;
|
||||||
|
width: parent.width/6 - anchors.leftMargin;
|
||||||
|
height: 30;
|
||||||
|
text: "Speed 5";
|
||||||
|
onClicked: {
|
||||||
|
messageToSpeak.insert(messageToSpeak.cursorPosition, "<rate absspeed='5'/>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: speed0Button;
|
||||||
|
focusPolicy: Qt.NoFocus;
|
||||||
|
color: hifi.buttons.none;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.top: tagButtonTitle.bottom;
|
||||||
|
anchors.left: speed5Button.right;
|
||||||
|
anchors.leftMargin: 6;
|
||||||
|
width: parent.width/6 - anchors.leftMargin;
|
||||||
|
height: 30;
|
||||||
|
text: "Speed 0";
|
||||||
|
onClicked: {
|
||||||
|
messageToSpeak.insert(messageToSpeak.cursorPosition, "<rate absspeed='0'/>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: speedNeg10Button;
|
||||||
|
focusPolicy: Qt.NoFocus;
|
||||||
|
color: hifi.buttons.none;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.top: tagButtonTitle.bottom;
|
||||||
|
anchors.left: speed0Button.right;
|
||||||
|
anchors.leftMargin: 6;
|
||||||
|
width: parent.width/6 - anchors.leftMargin;
|
||||||
|
height: 30;
|
||||||
|
text: "Speed -10";
|
||||||
|
onClicked: {
|
||||||
|
messageToSpeak.insert(messageToSpeak.cursorPosition, "<rate absspeed='-10'/>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.top: tagButtonContainer.bottom;
|
||||||
|
anchors.topMargin: 8;
|
||||||
|
anchors.bottom: keyboardContainer.top;
|
||||||
|
anchors.bottomMargin: 16;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.leftMargin: 16;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
anchors.rightMargin: 16;
|
||||||
|
|
||||||
|
TextArea {
|
||||||
|
id: messageToSpeak;
|
||||||
|
placeholderText: "<i>Message to Speak</i>";
|
||||||
|
font.family: "Fira Sans SemiBold";
|
||||||
|
font.pixelSize: 20;
|
||||||
|
// Anchors
|
||||||
|
anchors.top: parent.top;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
anchors.bottom: speakButton.top;
|
||||||
|
anchors.bottomMargin: 8;
|
||||||
|
// Style
|
||||||
|
background: Rectangle {
|
||||||
|
anchors.fill: parent;
|
||||||
|
color: parent.activeFocus ? hifi.colors.black : hifi.colors.baseGrayShadow;
|
||||||
|
border.width: parent.activeFocus ? 1 : 0;
|
||||||
|
border.color: parent.activeFocus ? hifi.colors.primaryHighlight : hifi.colors.textFieldLightBackground;
|
||||||
|
}
|
||||||
|
color: hifi.colors.white;
|
||||||
|
textFormat: TextEdit.PlainText;
|
||||||
|
wrapMode: TextEdit.Wrap;
|
||||||
|
activeFocusOnPress: true;
|
||||||
|
activeFocusOnTab: true;
|
||||||
|
Keys.onPressed: {
|
||||||
|
if (event.key == Qt.Key_Return || event.key == Qt.Key_Enter) {
|
||||||
|
TextToSpeech.speakText(messageToSpeak.text, 480, 10, 24000, 16, true);
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: speakButton;
|
||||||
|
focusPolicy: Qt.NoFocus;
|
||||||
|
color: hifi.buttons.blue;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
anchors.bottom: parent.bottom;
|
||||||
|
width: 215;
|
||||||
|
height: 40;
|
||||||
|
text: "Speak";
|
||||||
|
onClicked: {
|
||||||
|
TextToSpeech.speakText(messageToSpeak.text, 480, 10, 24000, 16, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: clearButton;
|
||||||
|
focusPolicy: Qt.NoFocus;
|
||||||
|
color: hifi.buttons.white;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.right: speakButton.left;
|
||||||
|
anchors.rightMargin: 16;
|
||||||
|
anchors.bottom: parent.bottom;
|
||||||
|
width: 100;
|
||||||
|
height: 40;
|
||||||
|
text: "Clear";
|
||||||
|
onClicked: {
|
||||||
|
messageToSpeak.text = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: stopButton;
|
||||||
|
focusPolicy: Qt.NoFocus;
|
||||||
|
color: hifi.buttons.red;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.right: clearButton.left;
|
||||||
|
anchors.rightMargin: 16;
|
||||||
|
anchors.bottom: parent.bottom;
|
||||||
|
width: 100;
|
||||||
|
height: 40;
|
||||||
|
text: "Stop Last";
|
||||||
|
onClicked: {
|
||||||
|
TextToSpeech.stopLastSpeech();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: keyboardContainer;
|
||||||
|
z: 998;
|
||||||
|
visible: keyboard.raised;
|
||||||
|
property bool punctuationMode: false;
|
||||||
|
anchors {
|
||||||
|
bottom: parent.bottom;
|
||||||
|
left: parent.left;
|
||||||
|
right: parent.right;
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControlsUit.Keyboard {
|
||||||
|
id: keyboard;
|
||||||
|
raised: HMD.mounted && root.keyboardRaised;
|
||||||
|
numeric: parent.punctuationMode;
|
||||||
|
anchors {
|
||||||
|
bottom: parent.bottom;
|
||||||
|
left: parent.left;
|
||||||
|
right: parent.right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2906,7 +2906,7 @@ void Application::initializeUi() {
|
||||||
LoginDialog::registerType();
|
LoginDialog::registerType();
|
||||||
Tooltip::registerType();
|
Tooltip::registerType();
|
||||||
UpdateDialog::registerType();
|
UpdateDialog::registerType();
|
||||||
QmlContextCallback callback = [](QQmlContext* context) {
|
QmlContextCallback commerceCallback = [](QQmlContext* context) {
|
||||||
context->setContextProperty("Commerce", new QmlCommerce());
|
context->setContextProperty("Commerce", new QmlCommerce());
|
||||||
};
|
};
|
||||||
OffscreenQmlSurface::addWhitelistContextHandler({
|
OffscreenQmlSurface::addWhitelistContextHandler({
|
||||||
|
@ -2932,7 +2932,13 @@ void Application::initializeUi() {
|
||||||
QUrl{ "hifi/commerce/wallet/Wallet.qml" },
|
QUrl{ "hifi/commerce/wallet/Wallet.qml" },
|
||||||
QUrl{ "hifi/commerce/wallet/WalletHome.qml" },
|
QUrl{ "hifi/commerce/wallet/WalletHome.qml" },
|
||||||
QUrl{ "hifi/commerce/wallet/WalletSetup.qml" },
|
QUrl{ "hifi/commerce/wallet/WalletSetup.qml" },
|
||||||
}, callback);
|
}, commerceCallback);
|
||||||
|
QmlContextCallback ttsCallback = [](QQmlContext* context) {
|
||||||
|
context->setContextProperty("TextToSpeech", DependencyManager::get<TTSScriptingInterface>().data());
|
||||||
|
};
|
||||||
|
OffscreenQmlSurface::addWhitelistContextHandler({
|
||||||
|
QUrl{ "hifi/tts/TTS.qml" }
|
||||||
|
}, ttsCallback);
|
||||||
qmlRegisterType<ResourceImageItem>("Hifi", 1, 0, "ResourceImageItem");
|
qmlRegisterType<ResourceImageItem>("Hifi", 1, 0, "ResourceImageItem");
|
||||||
qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");
|
qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");
|
||||||
qmlRegisterType<WebBrowserSuggestionsEngine>("HifiWeb", 1, 0, "WebBrowserSuggestionsEngine");
|
qmlRegisterType<WebBrowserSuggestionsEngine>("HifiWeb", 1, 0, "WebBrowserSuggestionsEngine");
|
||||||
|
@ -3135,7 +3141,6 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) {
|
||||||
surfaceContext->setContextProperty("ContextOverlay", DependencyManager::get<ContextOverlayInterface>().data());
|
surfaceContext->setContextProperty("ContextOverlay", DependencyManager::get<ContextOverlayInterface>().data());
|
||||||
surfaceContext->setContextProperty("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
|
surfaceContext->setContextProperty("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
|
||||||
surfaceContext->setContextProperty("HiFiAbout", AboutUtil::getInstance());
|
surfaceContext->setContextProperty("HiFiAbout", AboutUtil::getInstance());
|
||||||
surfaceContext->setContextProperty("TextToSpeech", DependencyManager::get<TTSScriptingInterface>().data());
|
|
||||||
|
|
||||||
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
||||||
surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
|
surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
|
||||||
|
@ -6818,7 +6823,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
||||||
scriptEngine->registerGlobalObject("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
|
scriptEngine->registerGlobalObject("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
|
||||||
scriptEngine->registerGlobalObject("AddressManager", DependencyManager::get<AddressManager>().data());
|
scriptEngine->registerGlobalObject("AddressManager", DependencyManager::get<AddressManager>().data());
|
||||||
scriptEngine->registerGlobalObject("HifiAbout", AboutUtil::getInstance());
|
scriptEngine->registerGlobalObject("HifiAbout", AboutUtil::getInstance());
|
||||||
scriptEngine->registerGlobalObject("TextToSpeech", DependencyManager::get<TTSScriptingInterface>().data());
|
|
||||||
|
|
||||||
qScriptRegisterMetaType(scriptEngine.data(), OverlayIDtoScriptValue, OverlayIDfromScriptValue);
|
qScriptRegisterMetaType(scriptEngine.data(), OverlayIDtoScriptValue, OverlayIDfromScriptValue);
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,9 @@ void TTSScriptingInterface::speakText(const QString& textToSpeak,
|
||||||
_lastSoundByteArray.resize(0);
|
_lastSoundByteArray.resize(0);
|
||||||
_lastSoundByteArray.append(buf1, dwSize);
|
_lastSoundByteArray.append(buf1, dwSize);
|
||||||
|
|
||||||
emit ttsSampleCreated(_lastSoundByteArray, newChunkSize, timerInterval);
|
// Commented out because this doesn't work completely :)
|
||||||
|
// Obviously, commenting this out isn't fit for production, but it's fine for a test PR
|
||||||
|
//emit ttsSampleCreated(_lastSoundByteArray, newChunkSize, timerInterval);
|
||||||
|
|
||||||
if (alsoInject) {
|
if (alsoInject) {
|
||||||
AudioInjectorOptions options;
|
AudioInjectorOptions options;
|
||||||
|
|
|
@ -32,7 +32,8 @@ var DEFAULT_SCRIPTS_COMBINED = [
|
||||||
"system/firstPersonHMD.js",
|
"system/firstPersonHMD.js",
|
||||||
"system/tablet-ui/tabletUI.js",
|
"system/tablet-ui/tabletUI.js",
|
||||||
"system/emote.js",
|
"system/emote.js",
|
||||||
"system/miniTablet.js"
|
"system/miniTablet.js",
|
||||||
|
"system/tts/TTS.js"
|
||||||
];
|
];
|
||||||
var DEFAULT_SCRIPTS_SEPARATE = [
|
var DEFAULT_SCRIPTS_SEPARATE = [
|
||||||
"system/controllers/controllerScripts.js",
|
"system/controllers/controllerScripts.js",
|
||||||
|
|
28
scripts/system/tts/TTS.js
Normal file
28
scripts/system/tts/TTS.js
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
"use strict";
|
||||||
|
/*jslint vars:true, plusplus:true, forin:true*/
|
||||||
|
/*global Tablet, Script, */
|
||||||
|
/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */
|
||||||
|
//
|
||||||
|
// TTS.js
|
||||||
|
//
|
||||||
|
// Created by Zach Fox on 2018-10-10
|
||||||
|
// Copyright 2018 High Fidelity, Inc
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
(function () { // BEGIN LOCAL_SCOPE
|
||||||
|
var AppUi = Script.require('appUi');
|
||||||
|
|
||||||
|
var ui;
|
||||||
|
function startup() {
|
||||||
|
ui = new AppUi({
|
||||||
|
buttonName: "TTS",
|
||||||
|
//home: Script.resolvePath("TTS.qml")
|
||||||
|
home: "hifi/tts/TTS.qml",
|
||||||
|
graphicsDirectory: Script.resolvePath("./") // speech by Danil Polshin from the Noun Project
|
||||||
|
});
|
||||||
|
}
|
||||||
|
startup();
|
||||||
|
}()); // END LOCAL_SCOPE
|
9
scripts/system/tts/tts-a.svg
Normal file
9
scripts/system/tts/tts-a.svg
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="21.167mm" height="21.167mm" version="1.1" viewBox="0 0 21.167 21.167" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g transform="translate(-86.935 -154.12)">
|
||||||
|
<g transform="matrix(.26458 0 0 .26458 86.935 154.12)">
|
||||||
|
<path d="m56.667 0c-12.885 0-23.334 10.449-23.334 23.333v3.258l-6.406 15.467h-6e-3c-0.163 0.391-0.254 0.82-0.254 1.275 0 1.836 1.494 3.334 3.333 3.334h3.333v6.666c0 5.521 4.477 10 10 10h8.334v16.667h28.333v-56.667c0-12.884-10.442-23.333-23.333-23.333zm16.666 73.334h-15v-16.666h-15c-1.836 0-3.333-1.498-3.333-3.334v-13.334h-5.003l5.003-12.081v-4.586c0-9.189 7.478-16.667 16.667-16.667 9.192 0 16.666 7.478 16.666 16.667z"/>
|
||||||
|
<path d="m21.81 44.324-6.158-2.553c-3.093 7.455-3.093 15.671-0.014 23.132l6.166-2.546c-2.409-5.82-2.403-12.219 6e-3 -18.033z"/>
|
||||||
|
<path d="m9.4916 39.218-6.159-2.552c-4.27 10.295-4.609 22.222-0.013 33.335l6.159-2.552c-3.763-9.101-3.763-19.128 0.013-28.231z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 985 B |
9
scripts/system/tts/tts-i.svg
Normal file
9
scripts/system/tts/tts-i.svg
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<svg width="21.167mm" height="21.167mm" version="1.1" viewBox="0 0 21.167 21.167" fill="#FFFFFF" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g transform="translate(-86.935 -154.12)">
|
||||||
|
<g transform="matrix(.26458 0 0 .26458 86.935 154.12)">
|
||||||
|
<path d="m56.667 0c-12.885 0-23.334 10.449-23.334 23.333v3.258l-6.406 15.467h-6e-3c-0.163 0.391-0.254 0.82-0.254 1.275 0 1.836 1.494 3.334 3.333 3.334h3.333v6.666c0 5.521 4.477 10 10 10h8.334v16.667h28.333v-56.667c0-12.884-10.442-23.333-23.333-23.333zm16.666 73.334h-15v-16.666h-15c-1.836 0-3.333-1.498-3.333-3.334v-13.334h-5.003l5.003-12.081v-4.586c0-9.189 7.478-16.667 16.667-16.667 9.192 0 16.666 7.478 16.666 16.667z"/>
|
||||||
|
<path d="m21.81 44.324-6.158-2.553c-3.093 7.455-3.093 15.671-0.014 23.132l6.166-2.546c-2.409-5.82-2.403-12.219 6e-3 -18.033z"/>
|
||||||
|
<path d="m9.4916 39.218-6.159-2.552c-4.27 10.295-4.609 22.222-0.013 33.335l6.159-2.552c-3.763-9.101-3.763-19.128 0.013-28.231z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1,000 B |
Loading…
Reference in a new issue