mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
add stroke text, stretch symbols
This commit is contained in:
@@ -122,6 +122,8 @@ menu:
|
|||||||
help: 帮助
|
help: 帮助
|
||||||
index: 索引... F1
|
index: 索引... F1
|
||||||
website: 官方网站...
|
website: 官方网站...
|
||||||
|
#TODO: Localize
|
||||||
|
documentation: &Documentation...
|
||||||
about: 关于Magic Set Editor...
|
about: 关于Magic Set Editor...
|
||||||
|
|
||||||
## symbol editor menus
|
## symbol editor menus
|
||||||
@@ -258,6 +260,8 @@ help:
|
|||||||
# help menu
|
# help menu
|
||||||
index: 指数
|
index: 指数
|
||||||
website: 网站
|
website: 网站
|
||||||
|
#TODO: Localize
|
||||||
|
documentation: Open the MSE documentation website
|
||||||
about: 关于
|
about: 关于
|
||||||
|
|
||||||
# new set window
|
# new set window
|
||||||
@@ -726,6 +730,9 @@ label:
|
|||||||
installer status: 地位
|
installer status: 地位
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
|
#TODO: Localize
|
||||||
|
load image: Double click to load image
|
||||||
|
|
||||||
# print dialog
|
# print dialog
|
||||||
#TODO: Localize section
|
#TODO: Localize section
|
||||||
put space between cards: Put space between cards?
|
put space between cards: Put space between cards?
|
||||||
@@ -801,6 +808,11 @@ button:
|
|||||||
if internet connection exists: 如果接入互联网
|
if internet connection exists: 如果接入互联网
|
||||||
never: 从不
|
never: 从不
|
||||||
internal image extension: 内部存储带有文件扩展名的图像
|
internal image extension: 内部存储带有文件扩展名的图像
|
||||||
|
#TODO: Localize
|
||||||
|
allow image download:
|
||||||
|
Allow downloading of images.
|
||||||
|
This may significantly increase the
|
||||||
|
duration of JSON and CSV imports.
|
||||||
|
|
||||||
# column select
|
# column select
|
||||||
move up: 向上移动
|
move up: 向上移动
|
||||||
|
|||||||
@@ -122,6 +122,8 @@ menu:
|
|||||||
help: 幫助
|
help: 幫助
|
||||||
index: 索引... F1
|
index: 索引... F1
|
||||||
website: 官方網站...
|
website: 官方網站...
|
||||||
|
#TODO: Localize
|
||||||
|
documentation: &Documentation...
|
||||||
about: 關於Magic Set Editor...
|
about: 關於Magic Set Editor...
|
||||||
|
|
||||||
## symbol editor menus
|
## symbol editor menus
|
||||||
@@ -258,6 +260,8 @@ help:
|
|||||||
# help menu
|
# help menu
|
||||||
index: 指數
|
index: 指數
|
||||||
website: 網站
|
website: 網站
|
||||||
|
#TODO: Localize
|
||||||
|
documentation: Open the MSE documentation website
|
||||||
about: 關於
|
about: 關於
|
||||||
|
|
||||||
# new set window
|
# new set window
|
||||||
@@ -724,6 +728,9 @@ label:
|
|||||||
installer status: 地位
|
installer status: 地位
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
|
#TODO: Localize
|
||||||
|
load image: Double click to load image
|
||||||
|
|
||||||
# print dialog
|
# print dialog
|
||||||
#TODO: Localize section
|
#TODO: Localize section
|
||||||
put space between cards: Put space between cards?
|
put space between cards: Put space between cards?
|
||||||
@@ -799,6 +806,11 @@ button:
|
|||||||
if internet connection exists: 如果接入互聯網
|
if internet connection exists: 如果接入互聯網
|
||||||
never: 從不
|
never: 從不
|
||||||
internal image extension: 內部儲存帶有檔案副檔名的映像
|
internal image extension: 內部儲存帶有檔案副檔名的映像
|
||||||
|
#TODO: Localize
|
||||||
|
allow image download:
|
||||||
|
Allow downloading of images.
|
||||||
|
This may significantly increase the
|
||||||
|
duration of JSON and CSV imports.
|
||||||
|
|
||||||
# column select
|
# column select
|
||||||
move up: 向上移動
|
move up: 向上移動
|
||||||
|
|||||||
@@ -127,6 +127,8 @@ menu:
|
|||||||
help: &Hjælp
|
help: &Hjælp
|
||||||
index: &Indeks... F1
|
index: &Indeks... F1
|
||||||
website: &Hjemmeside...
|
website: &Hjemmeside...
|
||||||
|
#TODO: Localize
|
||||||
|
documentation: &Documentation...
|
||||||
about: &Om Magic Set Editor...
|
about: &Om Magic Set Editor...
|
||||||
|
|
||||||
## symbol editor menus
|
## symbol editor menus
|
||||||
@@ -264,6 +266,8 @@ help:
|
|||||||
# help menu
|
# help menu
|
||||||
index: Indeks
|
index: Indeks
|
||||||
website: Internet side
|
website: Internet side
|
||||||
|
#TODO: Localize
|
||||||
|
documentation: Open the MSE documentation website
|
||||||
about: Om
|
about: Om
|
||||||
|
|
||||||
# new set window
|
# new set window
|
||||||
@@ -742,6 +746,9 @@ label:
|
|||||||
installer status: Status:
|
installer status: Status:
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
|
#TODO: Localize
|
||||||
|
load image: Double click to load image
|
||||||
|
|
||||||
# print dialog
|
# print dialog
|
||||||
#TODO: Localize section
|
#TODO: Localize section
|
||||||
put space between cards: Put space between cards?
|
put space between cards: Put space between cards?
|
||||||
@@ -817,6 +824,11 @@ button:
|
|||||||
if internet connection exists: Hvis internetforbindelse findes
|
if internet connection exists: Hvis internetforbindelse findes
|
||||||
never: Aldrig
|
never: Aldrig
|
||||||
internal image extension: Gem billeder internt med filtypenavn
|
internal image extension: Gem billeder internt med filtypenavn
|
||||||
|
#TODO: Localize
|
||||||
|
allow image download:
|
||||||
|
Allow downloading of images.
|
||||||
|
This may significantly increase the
|
||||||
|
duration of JSON and CSV imports.
|
||||||
|
|
||||||
# column select
|
# column select
|
||||||
move up: Flyt &Op
|
move up: Flyt &Op
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ menu:
|
|||||||
help: &Hilfe
|
help: &Hilfe
|
||||||
index: &Index... F1
|
index: &Index... F1
|
||||||
website: &Website...
|
website: &Website...
|
||||||
|
documentation: &Dokumentation...
|
||||||
about: &Über Magic Set Editor...
|
about: &Über Magic Set Editor...
|
||||||
|
|
||||||
## symbol editor menus
|
## symbol editor menus
|
||||||
@@ -246,6 +247,7 @@ help:
|
|||||||
# help menu
|
# help menu
|
||||||
index: Index öffnen
|
index: Index öffnen
|
||||||
website: MSE-Website öffnen
|
website: MSE-Website öffnen
|
||||||
|
documentation: MSE-Dokumentationswebsite öffnen
|
||||||
about: Informationen zu dieser App anzeigen
|
about: Informationen zu dieser App anzeigen
|
||||||
|
|
||||||
# new set window
|
# new set window
|
||||||
@@ -693,6 +695,8 @@ label:
|
|||||||
installer status: Status:
|
installer status: Status:
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
|
load image: Doppelklicken Sie, um ein Bild zu laden
|
||||||
|
|
||||||
# print dialog
|
# print dialog
|
||||||
put space between cards: Soll zwischen den Karten ein Leerzeichen eingefügt werden?
|
put space between cards: Soll zwischen den Karten ein Leerzeichen eingefügt werden?
|
||||||
spacing print: Kartenabstand in Millimetern
|
spacing print: Kartenabstand in Millimetern
|
||||||
@@ -761,6 +765,10 @@ button:
|
|||||||
if internet connection exists: Wenn Internetverbindung besteht
|
if internet connection exists: Wenn Internetverbindung besteht
|
||||||
never: Niemals
|
never: Niemals
|
||||||
internal image extension: Speichern Sie Bilder intern mit der Dateierweiterung
|
internal image extension: Speichern Sie Bilder intern mit der Dateierweiterung
|
||||||
|
allow image download:
|
||||||
|
Bilder herunterladen zulassen.
|
||||||
|
Dies kann die Dauer von JSON- und
|
||||||
|
CSV-Importen erheblich verlängern.
|
||||||
|
|
||||||
# column select
|
# column select
|
||||||
move up: A&ufwärts
|
move up: A&ufwärts
|
||||||
@@ -1050,6 +1058,12 @@ error:
|
|||||||
bulk modify nothing: Es wurden keine Karten geändert.
|
bulk modify nothing: Es wurden keine Karten geändert.
|
||||||
bulk modify success: Anzahl der erfolgreich geänderten Karten: %s
|
bulk modify success: Anzahl der erfolgreich geänderten Karten: %s
|
||||||
|
|
||||||
|
# web request
|
||||||
|
web request failed: Webanfrage fehlgeschlagen
|
||||||
|
web request cant create: Webanfrageobjekt konnte nicht erstellt werden
|
||||||
|
web request corrupted: Download erfolgreich, aber Daten sind beschädigt
|
||||||
|
web request unsupported format: Download erfolgreich, aber Daten haben ein nicht unterstütztes Format
|
||||||
|
|
||||||
# stats panel
|
# stats panel
|
||||||
dimension not found: Keine Statistikdimension '%s'
|
dimension not found: Keine Statistikdimension '%s'
|
||||||
|
|
||||||
|
|||||||
@@ -695,6 +695,8 @@ label:
|
|||||||
installer status: Status:
|
installer status: Status:
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
|
load image: Double click to load image
|
||||||
|
|
||||||
# print dialog
|
# print dialog
|
||||||
put space between cards: Put space between cards?
|
put space between cards: Put space between cards?
|
||||||
spacing print: Spacing between cards in millimeters
|
spacing print: Spacing between cards in millimeters
|
||||||
|
|||||||
@@ -122,6 +122,8 @@ menu:
|
|||||||
help: &Ayuda
|
help: &Ayuda
|
||||||
index: &Índice... F1
|
index: &Índice... F1
|
||||||
website: &Página web...
|
website: &Página web...
|
||||||
|
#TODO: Localize
|
||||||
|
documentation: &Documentation...
|
||||||
about: &Sobre Magic Set Editor...
|
about: &Sobre Magic Set Editor...
|
||||||
|
|
||||||
## symbol editor menus
|
## symbol editor menus
|
||||||
@@ -258,6 +260,8 @@ help:
|
|||||||
# help menu
|
# help menu
|
||||||
index: Índice
|
index: Índice
|
||||||
website: Sitio web
|
website: Sitio web
|
||||||
|
#TODO: Localize
|
||||||
|
documentation: Open the MSE documentation website
|
||||||
about: Acerca
|
about: Acerca
|
||||||
|
|
||||||
# new set window
|
# new set window
|
||||||
@@ -727,6 +731,9 @@ label:
|
|||||||
installer status: Estado:
|
installer status: Estado:
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
|
#TODO: Localize
|
||||||
|
load image: Double click to load image
|
||||||
|
|
||||||
# print dialog
|
# print dialog
|
||||||
#TODO: Localize section
|
#TODO: Localize section
|
||||||
put space between cards: Put space between cards?
|
put space between cards: Put space between cards?
|
||||||
@@ -802,6 +809,11 @@ button:
|
|||||||
if internet connection exists: Si hay conexión de internet
|
if internet connection exists: Si hay conexión de internet
|
||||||
never: Nunca
|
never: Nunca
|
||||||
internal image extension: Almacenar imágenes internamente con extensión de archivo
|
internal image extension: Almacenar imágenes internamente con extensión de archivo
|
||||||
|
#TODO: Localize
|
||||||
|
allow image download:
|
||||||
|
Allow downloading of images.
|
||||||
|
This may significantly increase the
|
||||||
|
duration of JSON and CSV imports.
|
||||||
|
|
||||||
# column select
|
# column select
|
||||||
move up: Mover &hacia arriba
|
move up: Mover &hacia arriba
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ menu:
|
|||||||
help: &Aide
|
help: &Aide
|
||||||
index: &Index... F1
|
index: &Index... F1
|
||||||
website: &Site Web...
|
website: &Site Web...
|
||||||
|
documentation: &Documentation...
|
||||||
about: &À propos de Magic Set Editor...
|
about: &À propos de Magic Set Editor...
|
||||||
|
|
||||||
## symbol editor menus
|
## symbol editor menus
|
||||||
@@ -246,6 +247,7 @@ help:
|
|||||||
# help menu
|
# help menu
|
||||||
index: Ouvrir l'index
|
index: Ouvrir l'index
|
||||||
website: Ouvrir le site web de Magic Set Editor
|
website: Ouvrir le site web de Magic Set Editor
|
||||||
|
documentation: Ouvrir le site web de documentation de Magic Set Editor
|
||||||
about: Informations concernant Magic Set Editor
|
about: Informations concernant Magic Set Editor
|
||||||
|
|
||||||
# new set window
|
# new set window
|
||||||
@@ -694,6 +696,8 @@ label:
|
|||||||
installer status: État:
|
installer status: État:
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
|
load image: Double-cliquer pour charger une image
|
||||||
|
|
||||||
# print dialog
|
# print dialog
|
||||||
put space between cards: Ajouter un espace entre les cartes?
|
put space between cards: Ajouter un espace entre les cartes?
|
||||||
spacing print: Espace entre les cartes en millimètres
|
spacing print: Espace entre les cartes en millimètres
|
||||||
@@ -762,6 +766,10 @@ button:
|
|||||||
if internet connection exists: Si il y a une connexion internet
|
if internet connection exists: Si il y a une connexion internet
|
||||||
never: Jamais
|
never: Jamais
|
||||||
internal image extension: Stocker les images avec une extension en interne
|
internal image extension: Stocker les images avec une extension en interne
|
||||||
|
allow image download:
|
||||||
|
Autoriser le téléchargement des images.
|
||||||
|
Cela peut considérablement augmenter la
|
||||||
|
durée des importations de JSON et CSV.
|
||||||
|
|
||||||
# column select
|
# column select
|
||||||
move up: Rem&onter
|
move up: Rem&onter
|
||||||
@@ -1051,6 +1059,12 @@ error:
|
|||||||
bulk modify nothing: Aucune carte n'a été modifiée.
|
bulk modify nothing: Aucune carte n'a été modifiée.
|
||||||
bulk modify success: Nombre de cartes modifiées avec succès : %s
|
bulk modify success: Nombre de cartes modifiées avec succès : %s
|
||||||
|
|
||||||
|
# web request
|
||||||
|
web request failed: Échec de la requête Web
|
||||||
|
web request cant create: Impossible de créer l'objet de requête Web
|
||||||
|
web request corrupted: Téléchargement réussi, mais les données sont corrompues
|
||||||
|
web request unsupported format: Téléchargement réussi, mais le format des données n'est pas pris en charge
|
||||||
|
|
||||||
# stats panel
|
# stats panel
|
||||||
dimension not found: Il n'y a pas de statistique de type '%s'
|
dimension not found: Il n'y a pas de statistique de type '%s'
|
||||||
|
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ menu:
|
|||||||
help: &Aiuto
|
help: &Aiuto
|
||||||
index: &Indice... F1
|
index: &Indice... F1
|
||||||
website: &Sito web...
|
website: &Sito web...
|
||||||
|
documentation: &Documentazione...
|
||||||
about: Informazioni su Magic Set Editor...
|
about: Informazioni su Magic Set Editor...
|
||||||
|
|
||||||
## symbol editor menus
|
## symbol editor menus
|
||||||
@@ -246,6 +247,7 @@ help:
|
|||||||
# help menu
|
# help menu
|
||||||
index: Apri l'indice
|
index: Apri l'indice
|
||||||
website: Apri il sito web MSE
|
website: Apri il sito web MSE
|
||||||
|
documentation: Apri il sito web della documentazione MSE
|
||||||
about: Mostra informazioni su questa app
|
about: Mostra informazioni su questa app
|
||||||
|
|
||||||
# new set window
|
# new set window
|
||||||
@@ -694,6 +696,8 @@ label:
|
|||||||
installer status: Stato:
|
installer status: Stato:
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
|
load image: Fai doppio clic per caricare un'immagine
|
||||||
|
|
||||||
# print dialog
|
# print dialog
|
||||||
put space between cards: Inserire uno spazio tra le carte?
|
put space between cards: Inserire uno spazio tra le carte?
|
||||||
spacing print: Spaziatura tra le carte in millimetri
|
spacing print: Spaziatura tra le carte in millimetri
|
||||||
@@ -762,6 +766,10 @@ button:
|
|||||||
if internet connection exists: Se è presente una connessione a Internet
|
if internet connection exists: Se è presente una connessione a Internet
|
||||||
never: Mai
|
never: Mai
|
||||||
internal image extension: Memorizza le immagini internamente con l'estensione del file
|
internal image extension: Memorizza le immagini internamente con l'estensione del file
|
||||||
|
allow image download:
|
||||||
|
Consenti il download delle immagini.
|
||||||
|
Questo potrebbe aumentare significativamente
|
||||||
|
la durata delle importazioni JSON e CSV.
|
||||||
|
|
||||||
# column select
|
# column select
|
||||||
move up: Muovi S&u
|
move up: Muovi S&u
|
||||||
@@ -1051,6 +1059,12 @@ error:
|
|||||||
bulk modify nothing: Nessuna scheda è stata modificata.
|
bulk modify nothing: Nessuna scheda è stata modificata.
|
||||||
bulk modify success: Numero di schede modificate correttamente: %s.
|
bulk modify success: Numero di schede modificate correttamente: %s.
|
||||||
|
|
||||||
|
# web request
|
||||||
|
web request failed: Richiesta Web non riuscita
|
||||||
|
web request cant create: Impossibile creare l'oggetto della richiesta Web
|
||||||
|
web request corrupted: Download riuscito, ma i dati sono danneggiati
|
||||||
|
web request unsupported format: Download riuscito, ma i dati sono in un formato non supportato
|
||||||
|
|
||||||
# stats panel
|
# stats panel
|
||||||
dimension not found: Non c'è dimensione di statistiche '%s'
|
dimension not found: Non c'è dimensione di statistiche '%s'
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,8 @@ menu:
|
|||||||
help: &ヘルプ
|
help: &ヘルプ
|
||||||
index: &索引... F1
|
index: &索引... F1
|
||||||
website: &Magic Set Editorのウェブサイトを開く...
|
website: &Magic Set Editorのウェブサイトを開く...
|
||||||
|
#TODO: Localize
|
||||||
|
documentation: &Documentation...
|
||||||
about: &Magic Set Editorについて...
|
about: &Magic Set Editorについて...
|
||||||
|
|
||||||
## symbol editor menus
|
## symbol editor menus
|
||||||
@@ -258,6 +260,8 @@ help:
|
|||||||
# help menu
|
# help menu
|
||||||
index: 索引
|
index: 索引
|
||||||
website: Webサイト
|
website: Webサイト
|
||||||
|
#TODO: Localize
|
||||||
|
documentation: Open the MSE documentation website
|
||||||
about: について
|
about: について
|
||||||
|
|
||||||
# new set window
|
# new set window
|
||||||
@@ -726,6 +730,9 @@ label:
|
|||||||
installer status: 状態
|
installer status: 状態
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
|
#TODO: Localize
|
||||||
|
load image: Double click to load image
|
||||||
|
|
||||||
# print dialog
|
# print dialog
|
||||||
#TODO: Localize section
|
#TODO: Localize section
|
||||||
put space between cards: Put space between cards?
|
put space between cards: Put space between cards?
|
||||||
@@ -801,6 +808,11 @@ button:
|
|||||||
if internet connection exists: インターネットに接続していれば
|
if internet connection exists: インターネットに接続していれば
|
||||||
never: 行わない
|
never: 行わない
|
||||||
internal image extension: ファイル拡張子を付けて画像を内部に保存する
|
internal image extension: ファイル拡張子を付けて画像を内部に保存する
|
||||||
|
#TODO: Localize
|
||||||
|
allow image download:
|
||||||
|
Allow downloading of images.
|
||||||
|
This may significantly increase the
|
||||||
|
duration of JSON and CSV imports.
|
||||||
|
|
||||||
# column select
|
# column select
|
||||||
move up: 上へ移動
|
move up: 上へ移動
|
||||||
|
|||||||
@@ -122,6 +122,8 @@ menu:
|
|||||||
help: &도움말
|
help: &도움말
|
||||||
index: &색인... F1
|
index: &색인... F1
|
||||||
website: &Magic Set Editor 웹사이트...
|
website: &Magic Set Editor 웹사이트...
|
||||||
|
#TODO: Localize
|
||||||
|
documentation: &Documentation...
|
||||||
about: &Magic Set Editor 소개...
|
about: &Magic Set Editor 소개...
|
||||||
|
|
||||||
## symbol editor menus
|
## symbol editor menus
|
||||||
@@ -259,6 +261,8 @@ help:
|
|||||||
#TODO: Localize Section
|
#TODO: Localize Section
|
||||||
index: Open the index
|
index: Open the index
|
||||||
website: Open the MSE website
|
website: Open the MSE website
|
||||||
|
#TODO: Localize
|
||||||
|
documentation: Open the MSE documentation website
|
||||||
about: Show information about this app
|
about: Show information about this app
|
||||||
|
|
||||||
# new set window
|
# new set window
|
||||||
@@ -732,6 +736,9 @@ label:
|
|||||||
installer status: 상태:
|
installer status: 상태:
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
|
#TODO: Localize
|
||||||
|
load image: Double click to load image
|
||||||
|
|
||||||
# print dialog
|
# print dialog
|
||||||
#TODO: Localize section
|
#TODO: Localize section
|
||||||
put space between cards: Put space between cards?
|
put space between cards: Put space between cards?
|
||||||
@@ -807,6 +814,11 @@ button:
|
|||||||
if internet connection exists: 인터넷 연결이 존재하는 경우
|
if internet connection exists: 인터넷 연결이 존재하는 경우
|
||||||
never: 절대
|
never: 절대
|
||||||
internal image extension: 파일 확장자로 이미지 저장
|
internal image extension: 파일 확장자로 이미지 저장
|
||||||
|
#TODO: Localize
|
||||||
|
allow image download:
|
||||||
|
Allow downloading of images.
|
||||||
|
This may significantly increase the
|
||||||
|
duration of JSON and CSV imports.
|
||||||
|
|
||||||
# column select
|
# column select
|
||||||
move up: 숭진시키다
|
move up: 숭진시키다
|
||||||
|
|||||||
@@ -137,6 +137,8 @@ menu:
|
|||||||
help: &Pomoc
|
help: &Pomoc
|
||||||
index: Spis &treści... F1
|
index: Spis &treści... F1
|
||||||
website: &Strona internetowa...
|
website: &Strona internetowa...
|
||||||
|
#TODO: Localize
|
||||||
|
documentation: &Documentation...
|
||||||
about: &O programie Magic Set Editor...
|
about: &O programie Magic Set Editor...
|
||||||
|
|
||||||
## symbol editor menus
|
## symbol editor menus
|
||||||
@@ -282,6 +284,8 @@ help:
|
|||||||
#TODO: Localize Section
|
#TODO: Localize Section
|
||||||
index: Open the index
|
index: Open the index
|
||||||
website: Open the MSE website
|
website: Open the MSE website
|
||||||
|
#TODO: Localize
|
||||||
|
documentation: Open the MSE documentation website
|
||||||
about: Show information about this app
|
about: Show information about this app
|
||||||
|
|
||||||
# new set window
|
# new set window
|
||||||
@@ -776,6 +780,9 @@ label:
|
|||||||
installer status: Stan:
|
installer status: Stan:
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
|
#TODO: Localize
|
||||||
|
load image: Double click to load image
|
||||||
|
|
||||||
# print dialog
|
# print dialog
|
||||||
#TODO: Localize section
|
#TODO: Localize section
|
||||||
put space between cards: Put space between cards?
|
put space between cards: Put space between cards?
|
||||||
@@ -855,6 +862,11 @@ button:
|
|||||||
never: Nigdy
|
never: Nigdy
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
internal image extension: Store images internally with file extension
|
internal image extension: Store images internally with file extension
|
||||||
|
#TODO: Localize
|
||||||
|
allow image download:
|
||||||
|
Allow downloading of images.
|
||||||
|
This may significantly increase the
|
||||||
|
duration of JSON and CSV imports.
|
||||||
|
|
||||||
# column select
|
# column select
|
||||||
move up: Przesuń w &górę
|
move up: Przesuń w &górę
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ menu:
|
|||||||
help: &Ajuda
|
help: &Ajuda
|
||||||
index: &Indíce... F1
|
index: &Indíce... F1
|
||||||
website: &Site...
|
website: &Site...
|
||||||
|
documentation: &Documentação...
|
||||||
about: &About Magic Set Editor...
|
about: &About Magic Set Editor...
|
||||||
|
|
||||||
## symbol editor menus
|
## symbol editor menus
|
||||||
@@ -246,6 +247,7 @@ help:
|
|||||||
# help menu
|
# help menu
|
||||||
index: Abrir o índice
|
index: Abrir o índice
|
||||||
website: Abrir o site do MSE
|
website: Abrir o site do MSE
|
||||||
|
documentation: Abrir o site de documentação do MSE
|
||||||
about: Mostrar informações sobre este aplicativo
|
about: Mostrar informações sobre este aplicativo
|
||||||
|
|
||||||
# new set window
|
# new set window
|
||||||
@@ -695,6 +697,8 @@ label:
|
|||||||
installer status: Status:
|
installer status: Status:
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
|
load image: Clique duas vezes para carregar uma imagem
|
||||||
|
|
||||||
# print dialog
|
# print dialog
|
||||||
put space between cards: Colocar um espaço entre os Cards?
|
put space between cards: Colocar um espaço entre os Cards?
|
||||||
spacing print: Espaçamento entre Cards em milímetros
|
spacing print: Espaçamento entre Cards em milímetros
|
||||||
@@ -763,6 +767,10 @@ button:
|
|||||||
if internet connection exists: Se a conexão da internet existir
|
if internet connection exists: Se a conexão da internet existir
|
||||||
never: Nunca
|
never: Nunca
|
||||||
internal image extension: Armazenar imagens internamente com extensão de arquivo
|
internal image extension: Armazenar imagens internamente com extensão de arquivo
|
||||||
|
allow image download:
|
||||||
|
Permita o download das imagens.
|
||||||
|
Isso pode aumentar significativamente
|
||||||
|
a duração das importações de JSON e CSV.
|
||||||
|
|
||||||
# column select
|
# column select
|
||||||
move up: Mover para &Cima
|
move up: Mover para &Cima
|
||||||
@@ -1053,6 +1061,12 @@ error:
|
|||||||
bulk modify nothing: Nenhum Card foi modificado.
|
bulk modify nothing: Nenhum Card foi modificado.
|
||||||
bulk modify success: Número de Cards modificados com sucesso: %s
|
bulk modify success: Número de Cards modificados com sucesso: %s
|
||||||
|
|
||||||
|
# web request
|
||||||
|
web request failed: Falha na solicitação da Web
|
||||||
|
web request cant create: Não foi possível criar o objeto de solicitação da Web
|
||||||
|
web request corrupted: Download concluído com sucesso, mas os dados estão corrompidos
|
||||||
|
web request unsupported format: Download concluído com sucesso, mas os dados estão em um formato não compatível
|
||||||
|
|
||||||
# stats panel
|
# stats panel
|
||||||
dimension not found: Não há estatísticas de dimensões '%s'
|
dimension not found: Não há estatísticas de dimensões '%s'
|
||||||
|
|
||||||
|
|||||||
@@ -128,6 +128,8 @@ menu:
|
|||||||
help: Помощь
|
help: Помощь
|
||||||
index: Основное... F1
|
index: Основное... F1
|
||||||
website: Сайт проекта MSE...
|
website: Сайт проекта MSE...
|
||||||
|
#TODO: Localize
|
||||||
|
documentation: &Documentation...
|
||||||
about: О Magic Set Editor...
|
about: О Magic Set Editor...
|
||||||
|
|
||||||
## symbol editor menus
|
## symbol editor menus
|
||||||
@@ -272,6 +274,8 @@ help:
|
|||||||
#TODO: Localize Section
|
#TODO: Localize Section
|
||||||
index: Open the index
|
index: Open the index
|
||||||
website: Open the MSE website
|
website: Open the MSE website
|
||||||
|
#TODO: Localize
|
||||||
|
documentation: Open the MSE documentation website
|
||||||
about: Show information about this app
|
about: Show information about this app
|
||||||
|
|
||||||
# new set window
|
# new set window
|
||||||
@@ -766,6 +770,9 @@ label:
|
|||||||
installer status: Статус:
|
installer status: Статус:
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
|
#TODO: Localize
|
||||||
|
load image: Double click to load image
|
||||||
|
|
||||||
# print dialog
|
# print dialog
|
||||||
#TODO: Localize section
|
#TODO: Localize section
|
||||||
put space between cards: Put space between cards?
|
put space between cards: Put space between cards?
|
||||||
@@ -843,6 +850,11 @@ button:
|
|||||||
never: Никогда
|
never: Никогда
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
internal image extension: Store images internally with file extension
|
internal image extension: Store images internally with file extension
|
||||||
|
#TODO: Localize
|
||||||
|
allow image download:
|
||||||
|
Allow downloading of images.
|
||||||
|
This may significantly increase the
|
||||||
|
duration of JSON and CSV imports.
|
||||||
|
|
||||||
# column select
|
# column select
|
||||||
move up: Выше
|
move up: Выше
|
||||||
|
|||||||
+14
-1
@@ -22,9 +22,13 @@ Font::Font()
|
|||||||
, scale_down_to(100000)
|
, scale_down_to(100000)
|
||||||
, max_stretch(1.0)
|
, max_stretch(1.0)
|
||||||
, color(Color(0,0,0))
|
, color(Color(0,0,0))
|
||||||
|
, shadow_color(Color(0,0,0))
|
||||||
, shadow_displacement_x(0)
|
, shadow_displacement_x(0)
|
||||||
, shadow_displacement_y(0)
|
, shadow_displacement_y(0)
|
||||||
, shadow_blur(0)
|
, shadow_blur(0)
|
||||||
|
, stroke_color(Color(0,0,0))
|
||||||
|
, stroke_radius(0)
|
||||||
|
, stroke_blur(0)
|
||||||
, separator_color(Color(0,0,0,128))
|
, separator_color(Color(0,0,0,128))
|
||||||
, flags(FONT_NORMAL)
|
, flags(FONT_NORMAL)
|
||||||
{}
|
{}
|
||||||
@@ -96,6 +100,9 @@ bool Font::update(Context& ctx) {
|
|||||||
changes |= shadow_displacement_x.update(ctx);
|
changes |= shadow_displacement_x.update(ctx);
|
||||||
changes |= shadow_displacement_y.update(ctx);
|
changes |= shadow_displacement_y.update(ctx);
|
||||||
changes |= shadow_blur .update(ctx);
|
changes |= shadow_blur .update(ctx);
|
||||||
|
changes |= stroke_color .update(ctx);
|
||||||
|
changes |= stroke_radius .update(ctx);
|
||||||
|
changes |= stroke_blur .update(ctx);
|
||||||
flags = (flags & ~FONT_BOLD & ~FONT_ITALIC)
|
flags = (flags & ~FONT_BOLD & ~FONT_ITALIC)
|
||||||
| (weight() == _("bold") ? FONT_BOLD : FONT_NORMAL)
|
| (weight() == _("bold") ? FONT_BOLD : FONT_NORMAL)
|
||||||
| (style() == _("italic") ? FONT_ITALIC : FONT_NORMAL);
|
| (style() == _("italic") ? FONT_ITALIC : FONT_NORMAL);
|
||||||
@@ -114,6 +121,9 @@ void Font::initDependencies(Context& ctx, const Dependency& dep) const {
|
|||||||
shadow_displacement_x.initDependencies(ctx, dep);
|
shadow_displacement_x.initDependencies(ctx, dep);
|
||||||
shadow_displacement_y.initDependencies(ctx, dep);
|
shadow_displacement_y.initDependencies(ctx, dep);
|
||||||
shadow_blur .initDependencies(ctx, dep);
|
shadow_blur .initDependencies(ctx, dep);
|
||||||
|
stroke_color .initDependencies(ctx, dep);
|
||||||
|
stroke_blur .initDependencies(ctx, dep);
|
||||||
|
stroke_radius .initDependencies(ctx, dep);
|
||||||
}
|
}
|
||||||
|
|
||||||
FontP Font::make(int add_flags, bool add_underline, bool add_strikethrough, String const* other_family, Color const* other_color, double const* other_size) const {
|
FontP Font::make(int add_flags, bool add_underline, bool add_strikethrough, String const* other_family, Color const* other_color, double const* other_size) const {
|
||||||
@@ -204,9 +214,12 @@ IMPLEMENT_REFLECTION_NO_SCRIPT(Font) {
|
|||||||
REFLECT(color);
|
REFLECT(color);
|
||||||
REFLECT(scale_down_to);
|
REFLECT(scale_down_to);
|
||||||
REFLECT(max_stretch);
|
REFLECT(max_stretch);
|
||||||
|
REFLECT(shadow_color);
|
||||||
REFLECT(shadow_displacement_x);
|
REFLECT(shadow_displacement_x);
|
||||||
REFLECT(shadow_displacement_y);
|
REFLECT(shadow_displacement_y);
|
||||||
REFLECT(shadow_color);
|
|
||||||
REFLECT(shadow_blur);
|
REFLECT(shadow_blur);
|
||||||
|
REFLECT(stroke_color);
|
||||||
|
REFLECT(stroke_radius);
|
||||||
|
REFLECT(stroke_blur);
|
||||||
REFLECT(separator_color);
|
REFLECT(separator_color);
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-12
@@ -29,11 +29,11 @@ enum FontFlags
|
|||||||
, FONT_CODE_OPER = 0x80 // syntax highlighting
|
, FONT_CODE_OPER = 0x80 // syntax highlighting
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A font for rendering text
|
/// A reference to a font for rendering text
|
||||||
/** Contains additional information about scaling, color and shadow */
|
/** Contains additional information about scaling, color and shadow */
|
||||||
class Font : public IntrusivePtrBase<Font> {
|
class Font : public IntrusivePtrBase<Font> {
|
||||||
public:
|
public:
|
||||||
Scriptable<String> name; ///< Name of the font
|
Scriptable<String> name; ///< Name of the referenced font
|
||||||
Scriptable<String> italic_name; ///< Font name for italic text (optional)
|
Scriptable<String> italic_name; ///< Font name for italic text (optional)
|
||||||
Scriptable<double> size; ///< Size of the font
|
Scriptable<double> size; ///< Size of the font
|
||||||
Scriptable<String> weight, style; ///< Weight and style of the font (bold/italic)
|
Scriptable<String> weight, style; ///< Weight and style of the font (bold/italic)
|
||||||
@@ -42,10 +42,13 @@ public:
|
|||||||
double scale_down_to; ///< Smallest size to scale down to
|
double scale_down_to; ///< Smallest size to scale down to
|
||||||
double max_stretch; ///< How much should the font be stretched before scaling down?
|
double max_stretch; ///< How much should the font be stretched before scaling down?
|
||||||
Scriptable<Color> color; ///< Color to use
|
Scriptable<Color> color; ///< Color to use
|
||||||
Scriptable<Color> shadow_color; ///< Color for shadow
|
Scriptable<Color> shadow_color; ///< Color for the shadow
|
||||||
Scriptable<double> shadow_displacement_x;///< Position of the shadow
|
Scriptable<double> shadow_displacement_x;///< Offset of the shadow in pixels, for a font size of 15
|
||||||
Scriptable<double> shadow_displacement_y;///< Position of the shadow
|
Scriptable<double> shadow_displacement_y;///< Offset of the shadow in pixels, for a font size of 15
|
||||||
Scriptable<double> shadow_blur; ///< Blur radius of the shadow
|
Scriptable<double> shadow_blur; ///< Blur radius of the shadow in pixels, for a font size of 15
|
||||||
|
Scriptable<Color> stroke_color; ///< Color for the stroke
|
||||||
|
Scriptable<double> stroke_radius; ///< Thickness of the stroke in pixels, for a font size of 15
|
||||||
|
Scriptable<double> stroke_blur; ///< Blur radius of the stroke in pixels, for a font size of 15
|
||||||
Color separator_color; ///< Color for <sep> text
|
Color separator_color; ///< Color for <sep> text
|
||||||
int flags; ///< FontFlags for this font
|
int flags; ///< FontFlags for this font
|
||||||
|
|
||||||
@@ -61,16 +64,20 @@ public:
|
|||||||
bool update(Context& ctx);
|
bool update(Context& ctx);
|
||||||
/// Add the given dependency to the dependent_scripts list for the variables this font depends on
|
/// Add the given dependency to the dependent_scripts list for the variables this font depends on
|
||||||
void initDependencies(Context&, const Dependency&) const;
|
void initDependencies(Context&, const Dependency&) const;
|
||||||
|
|
||||||
/// Does this font have a shadow?
|
/// Add a shadow under the text?
|
||||||
inline bool hasShadow() const {
|
inline bool hasShadow() const {
|
||||||
return shadow_displacement_x != 0.0 || shadow_displacement_y != 0.0;
|
return (!almost_equal(shadow_blur(), 0.0) || !almost_equal(shadow_displacement_x(), 0.0) || !almost_equal(shadow_displacement_y(), 0.0)) && shadow_color().Alpha() != 0;
|
||||||
}
|
}
|
||||||
|
/// Add a stroke effect around the text?
|
||||||
/// Add style to a font, and optionally change the font family, color and size
|
inline bool hasStroke() const {
|
||||||
|
return (!almost_equal(stroke_blur(), 0.0) || !almost_equal(stroke_radius(), 0.0)) && stroke_color().Alpha() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add style, and optionally change the font family, color and size
|
||||||
FontP make(int add_flags, bool add_underline, bool add_strikethrough, String const* other_family, Color const* other_color, double const* other_size) const;
|
FontP make(int add_flags, bool add_underline, bool add_strikethrough, String const* other_family, Color const* other_color, double const* other_size) const;
|
||||||
|
|
||||||
/// Convert this font to a wxFont
|
/// Convert this font reference to a wxFont
|
||||||
wxFont toWxFont(double scale) const;
|
wxFont toWxFont(double scale) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
+163
-26
@@ -7,6 +7,7 @@
|
|||||||
// ----------------------------------------------------------------------------- : Includes
|
// ----------------------------------------------------------------------------- : Includes
|
||||||
|
|
||||||
#include <util/prec.hpp>
|
#include <util/prec.hpp>
|
||||||
|
#include <gfx/gfx.hpp>
|
||||||
#include <data/symbol_font.hpp>
|
#include <data/symbol_font.hpp>
|
||||||
#include <data/stylesheet.hpp>
|
#include <data/stylesheet.hpp>
|
||||||
#include <util/dynamic_arg.hpp>
|
#include <util/dynamic_arg.hpp>
|
||||||
@@ -269,31 +270,131 @@ SymbolInFont* SymbolFont::defaultSymbol() const {
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : SymbolFont : drawing
|
// ----------------------------------------------------------------------------- : SymbolFont : drawing
|
||||||
|
|
||||||
void SymbolFont::draw(RotatedDC& dc, Context& ctx, const RealRect& rect, double font_size, const Alignment& align, const String& text) {
|
void SymbolFont::draw(RotatedDC& dc, Context& ctx, const RealRect& rect, double scale, const SymbolFontRef& font, const String& text) {
|
||||||
SplitSymbols symbols;
|
SplitSymbols symbols;
|
||||||
update(ctx);
|
update(ctx);
|
||||||
split(text, symbols);
|
split(text, symbols);
|
||||||
draw(dc, rect, font_size, align, symbols);
|
draw(dc, rect, scale, font, symbols);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolFont::draw(RotatedDC& dc, RealRect rect, double font_size, const Alignment& align, const SplitSymbols& text) {
|
void SymbolFont::draw(RotatedDC& dc, RealRect rect, double scale, const SymbolFontRef& font, const SplitSymbols& text) {
|
||||||
|
double stretch = dc.getStretch();
|
||||||
FOR_EACH_CONST(sym, text) {
|
FOR_EACH_CONST(sym, text) {
|
||||||
RealSize size = dc.trInvS(symbolSize(dc.trS(font_size), sym));
|
RealSize size = dc.trInvS(symbolSize(dc.trS(scale * font.size), sym));
|
||||||
RealRect sym_rect = split_left(rect, size);
|
size = RealSize(size.width*stretch, size.height);
|
||||||
drawSymbol(dc, sym_rect, font_size, align, *sym.symbol, sym.draw_text);
|
RealRect sym_rect = split_left(rect, size);
|
||||||
|
// TODO: draw all stroke effects and shadows first, then draw all symbols
|
||||||
|
drawSymbol(dc, sym_rect, scale, font, *sym.symbol, sym.draw_text, stretch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolFont::drawSymbol(RotatedDC& dc, RealRect sym_rect, double font_size, const Alignment& align, SymbolInFont& sym, const String& text) {
|
void SymbolFont::drawSymbol(RotatedDC& dc, RealRect sym_rect, double scale, const SymbolFontRef& font, SymbolInFont& sym, const String& text, double stretch) {
|
||||||
// 1. draw symbol
|
// 1. find bitmap and pos
|
||||||
// find bitmap
|
double font_size = scale * font.size();
|
||||||
Bitmap bmp = sym.getBitmap(*this, dc.trS(font_size));
|
double font_size_ext = dc.trS(scale * font.size());
|
||||||
// draw aligned in the rectangle
|
Bitmap bmp = sym.getBitmap(*this, font_size_ext);
|
||||||
|
if (!almost_equal(stretch, 1.0)) {
|
||||||
|
bmp = Bitmap(resample(bmp.ConvertToImage(), bmp.GetWidth() * stretch, bmp.GetHeight()));
|
||||||
|
}
|
||||||
RealSize bmp_size = dc.trInvS(RealSize(bmp));
|
RealSize bmp_size = dc.trInvS(RealSize(bmp));
|
||||||
RealPoint bmp_pos = align_in_rect(align, bmp_size, sym_rect);
|
RealPoint bmp_pos = align_in_rect(font.alignment(), bmp_size, sym_rect);
|
||||||
|
// 2. draw potential stroke or shadow
|
||||||
|
double s_scale = font_size_ext / 15.;
|
||||||
|
if (font.hasStroke()) {
|
||||||
|
// add margin
|
||||||
|
Image img = bmp.ConvertToImage();
|
||||||
|
if (!img.HasAlpha()) set_alpha(img, 0);
|
||||||
|
int blur_radius = lround(font.stroke_blur() * s_scale);
|
||||||
|
int stroke_radius = lround(font.stroke_radius() * s_scale);
|
||||||
|
int margin = blur_radius + stroke_radius;
|
||||||
|
int s_width = img.GetWidth() + 2 * margin, s_height = img.GetHeight() + 2 * margin;
|
||||||
|
int x_end = s_width - margin;
|
||||||
|
int y_end = s_height - margin;
|
||||||
|
wxImage s_img(s_width, s_height, false);
|
||||||
|
s_img.InitAlpha();
|
||||||
|
// convert to stroke color
|
||||||
|
Byte* s_data = s_img.GetData();
|
||||||
|
Byte* s_alpha = s_img.GetAlpha(), *alpha = img.GetAlpha();
|
||||||
|
Color color = font.stroke_color();
|
||||||
|
unsigned char r = color.Red();
|
||||||
|
unsigned char g = color.Green();
|
||||||
|
unsigned char b = color.Blue();
|
||||||
|
unsigned char a = color.Alpha();
|
||||||
|
for (int y = 0 ; y < s_height ; ++y) {
|
||||||
|
for (int x = 0 ; x < s_width ; ++x) {
|
||||||
|
s_data[0] = r;
|
||||||
|
s_data[1] = g;
|
||||||
|
s_data[2] = b;
|
||||||
|
s_data += 3;
|
||||||
|
if (margin <= x && x < x_end && margin <= y && y < y_end) {
|
||||||
|
s_alpha[0] = alpha[0] * a / 255;
|
||||||
|
alpha += 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s_alpha[0] = 0;
|
||||||
|
}
|
||||||
|
s_alpha += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add stroke effect
|
||||||
|
for (int i = 0 ; i < stroke_radius ; ++i) {
|
||||||
|
thicken_image_alpha(s_img, 1);
|
||||||
|
}
|
||||||
|
// add blur
|
||||||
|
for (int i = 0 ; i < blur_radius ; ++i) {
|
||||||
|
blur_image_alpha(s_img, 3);
|
||||||
|
}
|
||||||
|
// draw
|
||||||
|
RealSize s_size = dc.trInvS(RealSize(s_img));
|
||||||
|
RealPoint s_pos(bmp_pos.x - (s_size.width - bmp_size.width)/2, bmp_pos.y - (s_size.height - bmp_size.height)/2);
|
||||||
|
dc.DrawImage(s_img, s_pos);
|
||||||
|
}
|
||||||
|
else if (font.hasShadow()) {
|
||||||
|
// add margin
|
||||||
|
Image img = bmp.ConvertToImage();
|
||||||
|
if (!img.HasAlpha()) set_alpha(img, 0);
|
||||||
|
int margin = lround(font.shadow_blur() * s_scale);
|
||||||
|
int s_width = img.GetWidth() + 2 * margin, s_height = img.GetHeight() + 2 * margin;
|
||||||
|
int x_end = s_width - margin;
|
||||||
|
int y_end = s_height - margin;
|
||||||
|
wxImage s_img(s_width, s_height, false);
|
||||||
|
s_img.InitAlpha();
|
||||||
|
// convert to shadow color
|
||||||
|
Byte* s_data = s_img.GetData();
|
||||||
|
Byte* s_alpha = s_img.GetAlpha(), *alpha = img.GetAlpha();
|
||||||
|
Color color = font.shadow_color();
|
||||||
|
unsigned char r = color.Red();
|
||||||
|
unsigned char g = color.Green();
|
||||||
|
unsigned char b = color.Blue();
|
||||||
|
unsigned char a = color.Alpha();
|
||||||
|
for (int y = 0 ; y < s_height ; ++y) {
|
||||||
|
for (int x = 0 ; x < s_width ; ++x) {
|
||||||
|
s_data[0] = r;
|
||||||
|
s_data[1] = g;
|
||||||
|
s_data[2] = b;
|
||||||
|
s_data += 3;
|
||||||
|
if (margin <= x && x < x_end && margin <= y && y < y_end) {
|
||||||
|
s_alpha[0] = alpha[0] * a / 255;
|
||||||
|
alpha += 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s_alpha[0] = 0;
|
||||||
|
}
|
||||||
|
s_alpha += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add blur
|
||||||
|
for (int i = 0 ; i < margin ; ++i) {
|
||||||
|
blur_image_alpha(s_img, 3);
|
||||||
|
}
|
||||||
|
// draw
|
||||||
|
RealSize s_size = dc.trInvS(RealSize(s_img));
|
||||||
|
RealPoint s_pos(bmp_pos.x - (s_size.width - bmp_size.width)/2, bmp_pos.y - (s_size.height - bmp_size.height)/2);
|
||||||
|
dc.DrawImage(s_img, s_pos + RealPoint(font.shadow_displacement_x(), font.shadow_displacement_y()) * scale);
|
||||||
|
}
|
||||||
|
// 3. draw bitmap
|
||||||
dc.DrawBitmap(bmp, bmp_pos);
|
dc.DrawBitmap(bmp, bmp_pos);
|
||||||
|
// 4. draw text
|
||||||
// 2. draw text
|
|
||||||
if (text.empty() || !sym.text_font) return;
|
if (text.empty() || !sym.text_font) return;
|
||||||
// only use the bitmap rectangle
|
// only use the bitmap rectangle
|
||||||
sym_rect = RealRect(bmp_pos, bmp_size);
|
sym_rect = RealRect(bmp_pos, bmp_size);
|
||||||
@@ -304,7 +405,7 @@ void SymbolFont::drawSymbol(RotatedDC& dc, RealRect sym_rect, double font_size,
|
|||||||
sym_rect.height -= font_size * (sym.text_margin_top + sym.text_margin_bottom);
|
sym_rect.height -= font_size * (sym.text_margin_top + sym.text_margin_bottom);
|
||||||
// setup text, shrink it
|
// setup text, shrink it
|
||||||
double size = font_size * sym.text_font->size;
|
double size = font_size * sym.text_font->size;
|
||||||
double stretch = 1.0;
|
double text_stretch = 1.0;
|
||||||
RealSize ts;
|
RealSize ts;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (size <= 0) return; // text too small
|
if (size <= 0) return; // text too small
|
||||||
@@ -314,7 +415,7 @@ void SymbolFont::drawSymbol(RotatedDC& dc, RealRect sym_rect, double font_size,
|
|||||||
if (ts.width <= sym_rect.width) {
|
if (ts.width <= sym_rect.width) {
|
||||||
break; // text fits
|
break; // text fits
|
||||||
} else if (ts.width * sym.text_font->max_stretch <= sym_rect.width) {
|
} else if (ts.width * sym.text_font->max_stretch <= sym_rect.width) {
|
||||||
stretch = sym_rect.width / ts.width;
|
text_stretch = sym_rect.width / ts.width;
|
||||||
ts.width = sym_rect.width; // for alignment
|
ts.width = sym_rect.width; // for alignment
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -325,7 +426,7 @@ void SymbolFont::drawSymbol(RotatedDC& dc, RealRect sym_rect, double font_size,
|
|||||||
// align text
|
// align text
|
||||||
RealPoint text_pos = align_in_rect(sym.text_alignment, ts, sym_rect);
|
RealPoint text_pos = align_in_rect(sym.text_alignment, ts, sym_rect);
|
||||||
// draw text
|
// draw text
|
||||||
dc.DrawTextWithShadow(text, *sym.text_font, text_pos, font_size, stretch);
|
dc.DrawTextWithShadowOrStroke(text, *sym.text_font, text_pos, font_size, text_stretch);
|
||||||
}
|
}
|
||||||
|
|
||||||
Image SymbolFont::getImage(double font_size, const DrawableSymbol& sym) {
|
Image SymbolFont::getImage(double font_size, const DrawableSymbol& sym) {
|
||||||
@@ -345,7 +446,7 @@ Image SymbolFont::getImage(double font_size, const DrawableSymbol& sym) {
|
|||||||
sym_rect.height -= font_size * (sym.symbol->text_margin_top + sym.symbol->text_margin_bottom);
|
sym_rect.height -= font_size * (sym.symbol->text_margin_top + sym.symbol->text_margin_bottom);
|
||||||
// setup text, shrink it
|
// setup text, shrink it
|
||||||
double size = font_size * sym.symbol->text_font->size;
|
double size = font_size * sym.symbol->text_font->size;
|
||||||
double stretch = 1.0;
|
double text_stretch = 1.0;
|
||||||
RealSize ts;
|
RealSize ts;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (size <= 0) return sym.symbol->getImage(*this, font_size); // text too small
|
if (size <= 0) return sym.symbol->getImage(*this, font_size); // text too small
|
||||||
@@ -355,7 +456,7 @@ Image SymbolFont::getImage(double font_size, const DrawableSymbol& sym) {
|
|||||||
if (ts.width <= sym_rect.width) {
|
if (ts.width <= sym_rect.width) {
|
||||||
break; // text fits
|
break; // text fits
|
||||||
} else if (ts.width * sym.symbol->text_font->max_stretch <= sym_rect.width) {
|
} else if (ts.width * sym.symbol->text_font->max_stretch <= sym_rect.width) {
|
||||||
stretch = sym_rect.width / ts.width;
|
text_stretch = sym_rect.width / ts.width;
|
||||||
ts.width = sym_rect.width; // for alignment
|
ts.width = sym_rect.width; // for alignment
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -366,7 +467,7 @@ Image SymbolFont::getImage(double font_size, const DrawableSymbol& sym) {
|
|||||||
// align text
|
// align text
|
||||||
RealPoint text_pos = align_in_rect(sym.symbol->text_alignment, ts, sym_rect);
|
RealPoint text_pos = align_in_rect(sym.symbol->text_alignment, ts, sym_rect);
|
||||||
// draw text
|
// draw text
|
||||||
rdc.DrawTextWithShadow(sym.draw_text, *sym.symbol->text_font, text_pos, font_size, stretch);
|
rdc.DrawTextWithShadowOrStroke(sym.draw_text, *sym.symbol->text_font, text_pos, font_size, text_stretch);
|
||||||
// done
|
// done
|
||||||
dc.SelectObject(wxNullBitmap);
|
dc.SelectObject(wxNullBitmap);
|
||||||
return bmp.ConvertToImage();
|
return bmp.ConvertToImage();
|
||||||
@@ -568,8 +669,17 @@ void after_reading(InsertSymbolMenu& m, Version ver) {
|
|||||||
SymbolFontRef::SymbolFontRef()
|
SymbolFontRef::SymbolFontRef()
|
||||||
: size(12)
|
: size(12)
|
||||||
, scale_down_to(1)
|
, scale_down_to(1)
|
||||||
|
, underline(false)
|
||||||
|
, strikethrough(false)
|
||||||
, alignment(ALIGN_MIDDLE_CENTER)
|
, alignment(ALIGN_MIDDLE_CENTER)
|
||||||
{}
|
, shadow_color(Color(0,0,0))
|
||||||
|
, shadow_displacement_x(0)
|
||||||
|
, shadow_displacement_y(0)
|
||||||
|
, shadow_blur(0)
|
||||||
|
, stroke_color(Color(0,0,0))
|
||||||
|
, stroke_radius(0)
|
||||||
|
, stroke_blur(0)
|
||||||
|
{}
|
||||||
|
|
||||||
bool SymbolFontRef::valid() const {
|
bool SymbolFontRef::valid() const {
|
||||||
return !!font;
|
return !!font;
|
||||||
@@ -584,14 +694,32 @@ bool SymbolFontRef::update(Context& ctx) {
|
|||||||
} else if (!font) {
|
} else if (!font) {
|
||||||
loadFont(ctx);
|
loadFont(ctx);
|
||||||
}
|
}
|
||||||
changes |= size.update(ctx);
|
changes |= size .update(ctx);
|
||||||
changes |= alignment.update(ctx);
|
changes |= underline .update(ctx);
|
||||||
|
changes |= strikethrough .update(ctx);
|
||||||
|
changes |= alignment .update(ctx);
|
||||||
|
changes |= shadow_color .update(ctx);
|
||||||
|
changes |= shadow_displacement_x.update(ctx);
|
||||||
|
changes |= shadow_displacement_y.update(ctx);
|
||||||
|
changes |= shadow_blur .update(ctx);
|
||||||
|
changes |= stroke_color .update(ctx);
|
||||||
|
changes |= stroke_radius .update(ctx);
|
||||||
|
changes |= stroke_blur .update(ctx);
|
||||||
return changes;
|
return changes;
|
||||||
}
|
}
|
||||||
void SymbolFontRef::initDependencies(Context& ctx, const Dependency& dep) const {
|
void SymbolFontRef::initDependencies(Context& ctx, const Dependency& dep) const {
|
||||||
name.initDependencies(ctx, dep);
|
name .initDependencies(ctx, dep);
|
||||||
size.initDependencies(ctx, dep);
|
size .initDependencies(ctx, dep);
|
||||||
alignment.initDependencies(ctx, dep);
|
underline .initDependencies(ctx, dep);
|
||||||
|
strikethrough .initDependencies(ctx, dep);
|
||||||
|
alignment .initDependencies(ctx, dep);
|
||||||
|
shadow_color .initDependencies(ctx, dep);
|
||||||
|
shadow_displacement_x.initDependencies(ctx, dep);
|
||||||
|
shadow_displacement_y.initDependencies(ctx, dep);
|
||||||
|
shadow_blur .initDependencies(ctx, dep);
|
||||||
|
stroke_color .initDependencies(ctx, dep);
|
||||||
|
stroke_radius .initDependencies(ctx, dep);
|
||||||
|
stroke_blur .initDependencies(ctx, dep);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolFontRef::loadFont(Context& ctx) {
|
void SymbolFontRef::loadFont(Context& ctx) {
|
||||||
@@ -614,5 +742,14 @@ IMPLEMENT_REFLECTION(SymbolFontRef) {
|
|||||||
REFLECT(name);
|
REFLECT(name);
|
||||||
REFLECT(size);
|
REFLECT(size);
|
||||||
REFLECT(scale_down_to);
|
REFLECT(scale_down_to);
|
||||||
|
REFLECT(underline);
|
||||||
|
REFLECT(strikethrough);
|
||||||
REFLECT(alignment);
|
REFLECT(alignment);
|
||||||
|
REFLECT(shadow_color);
|
||||||
|
REFLECT(shadow_displacement_x);
|
||||||
|
REFLECT(shadow_displacement_y);
|
||||||
|
REFLECT(shadow_blur);
|
||||||
|
REFLECT(stroke_color);
|
||||||
|
REFLECT(stroke_radius);
|
||||||
|
REFLECT(stroke_blur);
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-11
@@ -19,7 +19,8 @@ DECLARE_POINTER_TYPE(Font);
|
|||||||
DECLARE_POINTER_TYPE(SymbolFont);
|
DECLARE_POINTER_TYPE(SymbolFont);
|
||||||
DECLARE_POINTER_TYPE(SymbolInFont);
|
DECLARE_POINTER_TYPE(SymbolInFont);
|
||||||
DECLARE_POINTER_TYPE(InsertSymbolMenu);
|
DECLARE_POINTER_TYPE(InsertSymbolMenu);
|
||||||
class RotatedDC;
|
class RotatedDC;
|
||||||
|
class SymbolFontRef;
|
||||||
struct CharInfo;
|
struct CharInfo;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : SymbolFont
|
// ----------------------------------------------------------------------------- : SymbolFont
|
||||||
@@ -56,12 +57,12 @@ public:
|
|||||||
size_t recognizePrefix(const String& text, size_t start) const;
|
size_t recognizePrefix(const String& text, size_t start) const;
|
||||||
|
|
||||||
/// Draw a piece of text
|
/// Draw a piece of text
|
||||||
void draw(RotatedDC& dc, Context& ctx, const RealRect& rect, double font_size, const Alignment& align, const String& text);
|
void draw(RotatedDC& dc, Context& ctx, const RealRect& rect, double scale, const SymbolFontRef& font, const String& text);
|
||||||
/// Get information on characters in a string
|
/// Get information on characters in a string
|
||||||
void getCharInfo(RotatedDC& dc, Context& ctx, double font_size, const String& text, vector<CharInfo>& out);
|
void getCharInfo(RotatedDC& dc, Context& ctx, double font_size, const String& text, vector<CharInfo>& out);
|
||||||
|
|
||||||
/// Draw a piece of text prepared using split
|
/// Draw a piece of text prepared using split
|
||||||
void draw(RotatedDC& dc, RealRect rect, double font_size, const Alignment& align, const SplitSymbols& text);
|
void draw(RotatedDC& dc, RealRect rect, double scale, const SymbolFontRef& font, const SplitSymbols& text);
|
||||||
/// Get information on characters in a string
|
/// Get information on characters in a string
|
||||||
void getCharInfo(RotatedDC& dc, double font_size, const SplitSymbols& text, vector<CharInfo>& out);
|
void getCharInfo(RotatedDC& dc, double font_size, const SplitSymbols& text, vector<CharInfo>& out);
|
||||||
|
|
||||||
@@ -99,7 +100,7 @@ private:
|
|||||||
SymbolInFont* defaultSymbol() const;
|
SymbolInFont* defaultSymbol() const;
|
||||||
|
|
||||||
/// Draws a single symbol inside the given rectangle
|
/// Draws a single symbol inside the given rectangle
|
||||||
void drawSymbol (RotatedDC& dc, RealRect sym_rect, double font_size, const Alignment& align, SymbolInFont& sym, const String& text);
|
void drawSymbol(RotatedDC& dc, RealRect sym_rect, double scale, const SymbolFontRef& font, SymbolInFont& sym, const String& text, double stretch);
|
||||||
|
|
||||||
/// Size of a single symbol, including spacing
|
/// Size of a single symbol, including spacing
|
||||||
RealSize symbolSize (double font_size, const DrawableSymbol& sym);
|
RealSize symbolSize (double font_size, const DrawableSymbol& sym);
|
||||||
@@ -158,15 +159,33 @@ public:
|
|||||||
bool update(Context& ctx);
|
bool update(Context& ctx);
|
||||||
void initDependencies(Context&, const Dependency&) const;
|
void initDependencies(Context&, const Dependency&) const;
|
||||||
|
|
||||||
/// Is a font loaded?
|
/// Is the referenced symbol font loaded?
|
||||||
bool valid() const;
|
bool valid() const;
|
||||||
|
|
||||||
Scriptable<String> name; ///< Font package name, can be changed with script
|
|
||||||
Scriptable<double> size; ///< Size of the font
|
|
||||||
double scale_down_to; ///< Mimumum size of the font
|
|
||||||
Scriptable<Alignment> alignment; ///< Alignment of symbols in a line of text
|
|
||||||
SymbolFontP font; ///< The font, if it is loaded
|
|
||||||
|
|
||||||
|
Scriptable<String> name; ///< The referenced symbol font's package name (folder name)
|
||||||
|
Scriptable<double> size; ///< Size of the font
|
||||||
|
double scale_down_to; ///< Minimum size of the font
|
||||||
|
Scriptable<bool> underline; ///< Underlined?
|
||||||
|
Scriptable<bool> strikethrough; ///< Struck through?
|
||||||
|
Scriptable<Alignment> alignment; ///< Alignment of symbols in a line of text
|
||||||
|
Scriptable<Color> shadow_color; ///< Color for the shadow
|
||||||
|
Scriptable<double> shadow_displacement_x;///< Offset of the shadow in pixels, for a font size of 15
|
||||||
|
Scriptable<double> shadow_displacement_y;///< Offset of the shadow in pixels, for a font size of 15
|
||||||
|
Scriptable<double> shadow_blur; ///< Blur radius of the shadow in pixels, for a font size of 15
|
||||||
|
Scriptable<Color> stroke_color; ///< Color for the stroke
|
||||||
|
Scriptable<double> stroke_radius; ///< Thickness of the stroke in pixels, for a font size of 15
|
||||||
|
Scriptable<double> stroke_blur; ///< Blur radius of the stroke in pixels, for a font size of 15
|
||||||
|
SymbolFontP font; ///< The symbol font this is referencing, if it is loaded
|
||||||
|
|
||||||
|
/// Add a shadow under symbols?
|
||||||
|
inline bool hasShadow() const {
|
||||||
|
return (!almost_equal(shadow_blur(), 0.0) || !almost_equal(shadow_displacement_x(), 0.0) || !almost_equal(shadow_displacement_y(), 0.0)) && shadow_color().Alpha() != 0;
|
||||||
|
}
|
||||||
|
/// Add a stroke effect around symbols?
|
||||||
|
inline bool hasStroke() const {
|
||||||
|
return (!almost_equal(stroke_blur(), 0.0) || !almost_equal(stroke_radius(), 0.0)) && stroke_color().Alpha() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DECLARE_REFLECTION();
|
DECLARE_REFLECTION();
|
||||||
|
|
||||||
|
|||||||
+17
-1
@@ -53,11 +53,15 @@ void sharp_resample_and_clip(const Image& img_in, Image& img_out, wxRect rect, i
|
|||||||
* rect = rectangle to draw in (a rectangle somewhere around pos)
|
* rect = rectangle to draw in (a rectangle somewhere around pos)
|
||||||
* stretch = amount to stretch in the direction of the text after drawing
|
* stretch = amount to stretch in the direction of the text after drawing
|
||||||
*/
|
*/
|
||||||
void draw_resampled_text(DC& dc, const RealPoint& pos, const RealRect& rect, double stretch, Radians angle, Color color, const String& text, int blur_radius = 0, int repeat = 1);
|
void draw_resampled_text(DC& dc, const String& text, const RealPoint& pos, const RealRect& rect, Radians angle, Color color, int blur_radius = 0, Color stroke_color = Color(0,0,0), int stroke_radius = 0, double stretch = 1.0);
|
||||||
|
|
||||||
// scaling factor to use when drawing resampled text
|
// scaling factor to use when drawing resampled text
|
||||||
extern const int text_scaling;
|
extern const int text_scaling;
|
||||||
|
|
||||||
|
// Downsamples the red channel of the input image to the alpha channel of the output image
|
||||||
|
// img_in must be text_scaling times as large as img_out
|
||||||
|
void downsample_to_alpha(Bitmap& bmp_in, Image& img_out);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Image rotation
|
// ----------------------------------------------------------------------------- : Image rotation
|
||||||
|
|
||||||
/// Rotates an image counter clockwise
|
/// Rotates an image counter clockwise
|
||||||
@@ -92,6 +96,18 @@ void saturate(Image& image, double amount);
|
|||||||
/// Invert the colors in an image
|
/// Invert the colors in an image
|
||||||
void invert(Image& img);
|
void invert(Image& img);
|
||||||
|
|
||||||
|
// Blur the alpha of a pixel
|
||||||
|
Byte blur_pixel_alpha(Byte* in, int x, int y, int width, int height, int center_weight = 2);
|
||||||
|
// Blur the alpha channel of an image
|
||||||
|
void blur_image_alpha(Image& img, int center_weight = 2);
|
||||||
|
|
||||||
|
// Thicken the alpha of a pixel
|
||||||
|
Byte thicken_pixel_alpha_3x3(std::vector<Byte> in, int i, int x, int y, int width, int height);
|
||||||
|
Byte thicken_pixel_alpha_5x5(std::vector<Byte> in, int i, int x, int y, int width, int height);
|
||||||
|
Byte thicken_pixel_alpha_7x7(std::vector<Byte> in, int i, int x, int y, int width, int height);
|
||||||
|
// Thicken the alpha channel of an image
|
||||||
|
void thicken_image_alpha(Image& img, int radius);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Combining
|
// ----------------------------------------------------------------------------- : Combining
|
||||||
|
|
||||||
/// Ways in which images can be combined, similair to what Photoshop supports
|
/// Ways in which images can be combined, similair to what Photoshop supports
|
||||||
|
|||||||
@@ -9,6 +9,9 @@
|
|||||||
#include <util/prec.hpp>
|
#include <util/prec.hpp>
|
||||||
#include <gfx/gfx.hpp>
|
#include <gfx/gfx.hpp>
|
||||||
#include <util/error.hpp>
|
#include <util/error.hpp>
|
||||||
|
#if defined(__WXMSW__) && wxUSE_WXDIB
|
||||||
|
#include <wx/msw/dib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Saturation
|
// ----------------------------------------------------------------------------- : Saturation
|
||||||
|
|
||||||
@@ -71,6 +74,294 @@ void invert(Image& img) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Blurring
|
||||||
|
|
||||||
|
Byte blur_pixel_alpha(Byte* in, int x, int y, int width, int height, int center_weight) {
|
||||||
|
return ( center_weight * in[0] + // center
|
||||||
|
(x == 0 ? in[0] : in[-1]) + // left
|
||||||
|
(y == 0 ? in[0] : in[-width]) + // up
|
||||||
|
(x == width - 1 ? in[0] : in[1]) + // right
|
||||||
|
(y == height - 1 ? in[0] : in[width]) // down
|
||||||
|
) / (4 + center_weight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void blur_image_alpha(Image& img, int center_weight) {
|
||||||
|
if (!img.HasAlpha()) return;
|
||||||
|
int width = img.GetWidth(), height = img.GetHeight();
|
||||||
|
Byte* data = img.GetAlpha();
|
||||||
|
for (int y = 0 ; y < height ; ++y) {
|
||||||
|
for (int x = 0 ; x < width ; ++x) {
|
||||||
|
*data = blur_pixel_alpha(data, x, y, width, height, center_weight);
|
||||||
|
++data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Thickening
|
||||||
|
|
||||||
|
Byte thicken_pixel_alpha_7x7(std::vector<unsigned char> in, int i, int x, int y, int width, int height) {
|
||||||
|
Byte result = in[i];
|
||||||
|
Byte diag = in[i];
|
||||||
|
Byte corner = in[i];
|
||||||
|
if (x > 2) {
|
||||||
|
if (y > 1) corner = max(corner, in[i -3 -2*width]);
|
||||||
|
if (y > 0) diag = max(diag , in[i -3 -1*width]);
|
||||||
|
result = max(result, in[i -3 ]);
|
||||||
|
if (y < height - 1) diag = max(diag , in[i -3 +1*width]);
|
||||||
|
if (y < height - 2) corner = max(corner, in[i -3 +2*width]);
|
||||||
|
}
|
||||||
|
if (x > 1) {
|
||||||
|
if (y > 2) corner = max(corner, in[i -2 -3*width]);
|
||||||
|
if (y > 1) result = max(result, in[i -2 -2*width]);
|
||||||
|
if (y > 0) result = max(result, in[i -2 -1*width]);
|
||||||
|
result = max(result, in[i -2 ]);
|
||||||
|
if (y < height - 1) result = max(result, in[i -2 +1*width]);
|
||||||
|
if (y < height - 2) result = max(result, in[i -2 +2*width]);
|
||||||
|
if (y < height - 3) corner = max(corner, in[i -2 +3*width]);
|
||||||
|
}
|
||||||
|
if (x > 0) {
|
||||||
|
if (y > 2) diag = max(diag , in[i -1 -3*width]);
|
||||||
|
if (y > 1) result = max(result, in[i -1 -2*width]);
|
||||||
|
if (y > 0) result = max(result, in[i -1 -1*width]);
|
||||||
|
result = max(result, in[i -1 ]);
|
||||||
|
if (y < height - 1) result = max(result, in[i -1 +1*width]);
|
||||||
|
if (y < height - 2) result = max(result, in[i -1 +2*width]);
|
||||||
|
if (y < height - 3) diag = max(diag , in[i -1 +3*width]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y > 2) result = max(result, in[i -3*width]);
|
||||||
|
if (y > 1) result = max(result, in[i -2*width]);
|
||||||
|
if (y > 0) result = max(result, in[i -1*width]);
|
||||||
|
|
||||||
|
if (y < height - 1) result = max(result, in[i +1*width]);
|
||||||
|
if (y < height - 2) result = max(result, in[i +2*width]);
|
||||||
|
if (y < height - 3) result = max(result, in[i +3*width]);
|
||||||
|
|
||||||
|
if (x < width - 1) {
|
||||||
|
if (y > 2) diag = max(diag , in[i +1 -3*width]);
|
||||||
|
if (y > 1) result = max(result, in[i +1 -2*width]);
|
||||||
|
if (y > 0) result = max(result, in[i +1 -1*width]);
|
||||||
|
result = max(result, in[i +1 ]);
|
||||||
|
if (y < height - 1) result = max(result, in[i +1 +1*width]);
|
||||||
|
if (y < height - 2) result = max(result, in[i +1 +2*width]);
|
||||||
|
if (y < height - 3) diag = max(diag , in[i +1 +3*width]);
|
||||||
|
}
|
||||||
|
if (x < width - 2) {
|
||||||
|
if (y > 2) corner = max(corner, in[i +2 -3*width]);
|
||||||
|
if (y > 1) result = max(result, in[i +2 -2*width]);
|
||||||
|
if (y > 0) result = max(result, in[i +2 -1*width]);
|
||||||
|
result = max(result, in[i +2 ]);
|
||||||
|
if (y < height - 1) result = max(result, in[i +2 +1*width]);
|
||||||
|
if (y < height - 2) result = max(result, in[i +2 +2*width]);
|
||||||
|
if (y < height - 3) corner = max(corner, in[i +2 +3*width]);
|
||||||
|
}
|
||||||
|
if (x < width - 3) {
|
||||||
|
if (y > 1) corner = max(corner, in[i +3 -2*width]);
|
||||||
|
if (y > 0) diag = max(diag , in[i +3 -1*width]);
|
||||||
|
result = max(result, in[i +3 ]);
|
||||||
|
if (y < height - 1) diag = max(diag , in[i +3 +1*width]);
|
||||||
|
if (y < height - 2) corner = max(corner, in[i +3 +2*width]);
|
||||||
|
}
|
||||||
|
if (diag > result) result = (Byte)((4 * (int)diag + (int)result) / 5);
|
||||||
|
if (corner > result) result = (Byte)((2 * (int)corner + 3 * (int)result) / 5);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Byte thicken_pixel_alpha_5x5(std::vector<unsigned char> in, int i, int x, int y, int width, int height) {
|
||||||
|
Byte result = in[i];
|
||||||
|
Byte diag = in[i];
|
||||||
|
if (x > 1) {
|
||||||
|
if (y > 0) diag = max(diag , in[i -2 -1*width]);
|
||||||
|
result = max(result, in[i -2 ]);
|
||||||
|
if (y < height - 1) diag = max(diag , in[i -2 +1*width]);
|
||||||
|
}
|
||||||
|
if (x > 0) {
|
||||||
|
if (y > 1) diag = max(diag , in[i -1 -2*width]);
|
||||||
|
if (y > 0) result = max(result, in[i -1 -1*width]);
|
||||||
|
result = max(result, in[i -1 ]);
|
||||||
|
if (y < height - 1) result = max(result, in[i -1 +1*width]);
|
||||||
|
if (y < height - 2) diag = max(diag , in[i -1 +2*width]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y > 1) result = max(result, in[i -2*width]);
|
||||||
|
if (y > 0) result = max(result, in[i -1*width]);
|
||||||
|
|
||||||
|
if (y < height - 1) result = max(result, in[i +1*width]);
|
||||||
|
if (y < height - 2) result = max(result, in[i +2*width]);
|
||||||
|
|
||||||
|
if (x < width - 1) {
|
||||||
|
if (y > 1) diag = max(diag , in[i +1 -2*width]);
|
||||||
|
if (y > 0) result = max(result, in[i +1 -1*width]);
|
||||||
|
result = max(result, in[i +1 ]);
|
||||||
|
if (y < height - 1) result = max(result, in[i +1 +1*width]);
|
||||||
|
if (y < height - 2) diag = max(diag , in[i +1 +2*width]);
|
||||||
|
}
|
||||||
|
if (x < width - 2) {
|
||||||
|
if (y > 0) diag = max(diag , in[i +2 -1*width]);
|
||||||
|
result = max(result, in[i +2 ]);
|
||||||
|
if (y < height - 1) diag = max(diag , in[i +2 +1*width]);
|
||||||
|
}
|
||||||
|
if (diag > result) result = (Byte)((3 * (int)diag + (int)result) / 4);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Byte thicken_pixel_alpha_3x3(std::vector<unsigned char> in, int i, int x, int y, int width, int height) {
|
||||||
|
Byte result = in[i];
|
||||||
|
Byte diag = in[i];
|
||||||
|
if (x > 0) {
|
||||||
|
if (y > 0) diag = max(diag, in[i -1 -width]);
|
||||||
|
result = max(result, in[i -1 ]);
|
||||||
|
if (y < height - 1) diag = max(diag, in[i -1 +width]);
|
||||||
|
}
|
||||||
|
if (y > 0) result = max(result, in[i -width]);
|
||||||
|
|
||||||
|
if (y < height - 1) result = max(result, in[i +width]);
|
||||||
|
if (x < width - 1) {
|
||||||
|
if (y > 0) diag = max(diag, in[i +1 -width]);
|
||||||
|
result = max(result, in[i +1 ]);
|
||||||
|
if (y < height - 1) diag = max(diag, in[i +1 +width]);
|
||||||
|
}
|
||||||
|
if (diag > result) result = (Byte)((3*(int)diag + 2*(int)result) / 5);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void thicken_image_alpha(Image& img, int radius) {
|
||||||
|
if (!img.HasAlpha()) return;
|
||||||
|
int width = img.GetWidth(), height = img.GetHeight();
|
||||||
|
Byte* data = img.GetAlpha();
|
||||||
|
std::vector<Byte> copy(data, data + width * height);
|
||||||
|
int i = 0;
|
||||||
|
for (int y = 0 ; y < height ; ++y) {
|
||||||
|
for (int x = 0 ; x < width ; ++x) {
|
||||||
|
*data = radius == 1 ? thicken_pixel_alpha_3x3(copy, i, x, y, width, height) :
|
||||||
|
radius == 2 ? thicken_pixel_alpha_5x5(copy, i, x, y, width, height) :
|
||||||
|
thicken_pixel_alpha_7x7(copy, i, x, y, width, height) ;
|
||||||
|
++data;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Resampled text
|
||||||
|
|
||||||
|
void downsample_to_alpha(Bitmap& bmp_in, Image& img_out) {
|
||||||
|
Byte* temp = nullptr;
|
||||||
|
#if defined(__WXMSW__) && wxUSE_WXDIB
|
||||||
|
wxDIB img_in(bmp_in);
|
||||||
|
if (!img_in.IsOk()) return;
|
||||||
|
// if text_scaling = 4, then the line always is dword aligned, so we need no adjusting
|
||||||
|
// we created a bitmap with depth 24, so that is what we should have here
|
||||||
|
if (img_in.GetDepth() != 24) throw InternalError(_("DIB has wrong bit depth"));
|
||||||
|
#else
|
||||||
|
Image img_in = bmp_in.ConvertToImage();
|
||||||
|
#endif
|
||||||
|
Byte* in = img_in.GetData();
|
||||||
|
Byte* out = img_in.GetData();
|
||||||
|
// scale in the x direction, this overwrites parts of the input image
|
||||||
|
if (img_in.GetWidth() == img_out.GetWidth() * text_scaling) {
|
||||||
|
// no stretching
|
||||||
|
int count = img_out.GetWidth() * img_in.GetHeight();
|
||||||
|
for (int i = 0 ; i < count ; ++i) {
|
||||||
|
int total = 0;
|
||||||
|
for (int j = 0 ; j < text_scaling ; ++j) {
|
||||||
|
total += in[3 * (j + text_scaling * i)];
|
||||||
|
}
|
||||||
|
out[i] = total / text_scaling;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// resample to buffer
|
||||||
|
temp = new Byte[img_out.GetWidth() * img_in.GetHeight()];
|
||||||
|
out = temp;
|
||||||
|
// custom stretch, see resample_image.cpp
|
||||||
|
const int shift = 32-12-8; // => max size = 4096, max alpha = 255
|
||||||
|
int w1 = img_in.GetWidth(), w2 = img_out.GetWidth(), h = img_in.GetHeight();
|
||||||
|
int out_fact = (w2 << shift) / w1; // how much to output for 256 input = 1 pixel
|
||||||
|
int out_rest = (w2 << shift) % w1;
|
||||||
|
// make the image 'bolder' to compensate for compressing it
|
||||||
|
int mul = 128 + min(256, 128*w1/(text_scaling*w2));
|
||||||
|
for (int y = 0 ; y < h ; ++y) {
|
||||||
|
int in_rem = out_fact + out_rest;
|
||||||
|
for (int x = 0 ; x < w2 ; ++x) {
|
||||||
|
int out_rem = 1 << shift;
|
||||||
|
int tot = 0;
|
||||||
|
while (out_rem >= in_rem) {
|
||||||
|
// eat a whole input pixel
|
||||||
|
tot += *in * in_rem;
|
||||||
|
out_rem -= in_rem;
|
||||||
|
in_rem = out_fact;
|
||||||
|
in += 3;
|
||||||
|
}
|
||||||
|
if (out_rem > 0) {
|
||||||
|
// eat a partial input pixel
|
||||||
|
tot += *in * out_rem;
|
||||||
|
in_rem -= out_rem;
|
||||||
|
}
|
||||||
|
// store
|
||||||
|
*out = top(((tot >> shift) * mul) >> 8);
|
||||||
|
out += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now scale in the y direction, and write to the output alpha
|
||||||
|
img_out.InitAlpha();
|
||||||
|
int line_size_in = img_out.GetWidth();
|
||||||
|
#if defined(__WXMSW__) && wxUSE_WXDIB
|
||||||
|
// DIBs are upside down
|
||||||
|
out = img_out.GetAlpha() + (img_out.GetHeight() - 1) * line_size_in;
|
||||||
|
int line_size_out = -line_size_in;
|
||||||
|
#else
|
||||||
|
out = img_out.GetAlpha();
|
||||||
|
int line_size_out = line_size_in;
|
||||||
|
#endif
|
||||||
|
int h = img_out.GetHeight();
|
||||||
|
if (img_in.GetHeight() == h * text_scaling) {
|
||||||
|
// no stretching
|
||||||
|
for (int y = 0 ; y < h ; ++y) {
|
||||||
|
for (int x = 0 ; x < line_size_in ; ++x) {
|
||||||
|
int total = 0;
|
||||||
|
for (int j = 0 ; j < text_scaling ; ++j) {
|
||||||
|
total += in[x + line_size_in * (j + text_scaling * y)];
|
||||||
|
}
|
||||||
|
out[x + line_size_out * y] = total / text_scaling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const int shift = 32-12-8; // => max size = 4096, max alpha = 255
|
||||||
|
int h1 = img_in.GetHeight(), w = img_out.GetWidth();
|
||||||
|
int out_fact = (h << shift) / h1; // how much to output for 256 input = 1 pixel
|
||||||
|
int out_rest = (h << shift) % h1;
|
||||||
|
int mul = 128 + min(256, 128*h1/(text_scaling*h));
|
||||||
|
for (int x = 0 ; x < w ; ++x) {
|
||||||
|
int in_rem = out_fact + out_rest;
|
||||||
|
for (int y = 0 ; y < h ; ++y) {
|
||||||
|
int out_rem = 1 << shift;
|
||||||
|
int tot = 0;
|
||||||
|
while (out_rem >= in_rem) {
|
||||||
|
// eat a whole input pixel
|
||||||
|
tot += *in * in_rem;
|
||||||
|
out_rem -= in_rem;
|
||||||
|
in_rem = out_fact;
|
||||||
|
in += line_size_in;
|
||||||
|
}
|
||||||
|
if (out_rem > 0) {
|
||||||
|
// eat a partial input pixel
|
||||||
|
tot += *in * out_rem;
|
||||||
|
in_rem -= out_rem;
|
||||||
|
}
|
||||||
|
// store
|
||||||
|
*out = top(((tot >> shift) * mul) >> 8);
|
||||||
|
out += line_size_out;
|
||||||
|
}
|
||||||
|
in = in - h1 * line_size_in + 1;
|
||||||
|
out = out - h * line_size_out + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] temp;
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Coloring symbol images
|
// ----------------------------------------------------------------------------- : Coloring symbol images
|
||||||
|
|
||||||
RGB recolor(RGB x, RGB cr, RGB cg, RGB cb, RGB cw) {
|
RGB recolor(RGB x, RGB cr, RGB cg, RGB cb, RGB cw) {
|
||||||
|
|||||||
+53
-168
@@ -10,9 +10,6 @@
|
|||||||
#include <gfx/gfx.hpp>
|
#include <gfx/gfx.hpp>
|
||||||
#include <util/error.hpp>
|
#include <util/error.hpp>
|
||||||
#include <gui/util.hpp> // clearDC_black
|
#include <gui/util.hpp> // clearDC_black
|
||||||
#if defined(__WXMSW__) && wxUSE_WXDIB
|
|
||||||
#include <wx/msw/dib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void blur_image(const Image& img_in, Image& img_out);
|
void blur_image(const Image& img_in, Image& img_out);
|
||||||
|
|
||||||
@@ -21,189 +18,77 @@ void blur_image(const Image& img_in, Image& img_out);
|
|||||||
// scaling factor to use when drawing resampled text
|
// scaling factor to use when drawing resampled text
|
||||||
const int text_scaling = 4;
|
const int text_scaling = 4;
|
||||||
|
|
||||||
// Downsamples the red channel of the input image to the alpha channel of the output image
|
|
||||||
// img_in must be text_scaling times as large as img_out
|
|
||||||
void downsample_to_alpha(Bitmap& bmp_in, Image& img_out) {
|
|
||||||
Byte* temp = nullptr;
|
|
||||||
#if defined(__WXMSW__) && wxUSE_WXDIB
|
|
||||||
wxDIB img_in(bmp_in);
|
|
||||||
if (!img_in.IsOk()) return;
|
|
||||||
// if text_scaling = 4, then the line always is dword aligned, so we need no adjusting
|
|
||||||
// we created a bitmap with depth 24, so that is what we should have here
|
|
||||||
if (img_in.GetDepth() != 24) throw InternalError(_("DIB has wrong bit depth"));
|
|
||||||
#else
|
|
||||||
Image img_in = bmp_in.ConvertToImage();
|
|
||||||
#endif
|
|
||||||
Byte* in = img_in.GetData();
|
|
||||||
Byte* out = img_in.GetData();
|
|
||||||
// scale in the x direction, this overwrites parts of the input image
|
|
||||||
if (img_in.GetWidth() == img_out.GetWidth() * text_scaling) {
|
|
||||||
// no stretching
|
|
||||||
int count = img_out.GetWidth() * img_in.GetHeight();
|
|
||||||
for (int i = 0 ; i < count ; ++i) {
|
|
||||||
int total = 0;
|
|
||||||
for (int j = 0 ; j < text_scaling ; ++j) {
|
|
||||||
total += in[3 * (j + text_scaling * i)];
|
|
||||||
}
|
|
||||||
out[i] = total / text_scaling;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// resample to buffer
|
|
||||||
temp = new Byte[img_out.GetWidth() * img_in.GetHeight()];
|
|
||||||
out = temp;
|
|
||||||
// custom stretch, see resample_image.cpp
|
|
||||||
const int shift = 32-12-8; // => max size = 4096, max alpha = 255
|
|
||||||
int w1 = img_in.GetWidth(), w2 = img_out.GetWidth(), h = img_in.GetHeight();
|
|
||||||
int out_fact = (w2 << shift) / w1; // how much to output for 256 input = 1 pixel
|
|
||||||
int out_rest = (w2 << shift) % w1;
|
|
||||||
// make the image 'bolder' to compensate for compressing it
|
|
||||||
int mul = 128 + min(256, 128*w1/(text_scaling*w2));
|
|
||||||
for (int y = 0 ; y < h ; ++y) {
|
|
||||||
int in_rem = out_fact + out_rest;
|
|
||||||
for (int x = 0 ; x < w2 ; ++x) {
|
|
||||||
int out_rem = 1 << shift;
|
|
||||||
int tot = 0;
|
|
||||||
while (out_rem >= in_rem) {
|
|
||||||
// eat a whole input pixel
|
|
||||||
tot += *in * in_rem;
|
|
||||||
out_rem -= in_rem;
|
|
||||||
in_rem = out_fact;
|
|
||||||
in += 3;
|
|
||||||
}
|
|
||||||
if (out_rem > 0) {
|
|
||||||
// eat a partial input pixel
|
|
||||||
tot += *in * out_rem;
|
|
||||||
in_rem -= out_rem;
|
|
||||||
}
|
|
||||||
// store
|
|
||||||
*out = top(((tot >> shift) * mul) >> 8);
|
|
||||||
out += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
in = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now scale in the y direction, and write to the output alpha
|
|
||||||
img_out.InitAlpha();
|
|
||||||
int line_size_in = img_out.GetWidth();
|
|
||||||
#if defined(__WXMSW__) && wxUSE_WXDIB
|
|
||||||
// DIBs are upside down
|
|
||||||
out = img_out.GetAlpha() + (img_out.GetHeight() - 1) * line_size_in;
|
|
||||||
int line_size_out = -line_size_in;
|
|
||||||
#else
|
|
||||||
out = img_out.GetAlpha();
|
|
||||||
int line_size_out = line_size_in;
|
|
||||||
#endif
|
|
||||||
int h = img_out.GetHeight();
|
|
||||||
if (img_in.GetHeight() == h * text_scaling) {
|
|
||||||
// no stretching
|
|
||||||
for (int y = 0 ; y < h ; ++y) {
|
|
||||||
for (int x = 0 ; x < line_size_in ; ++x) {
|
|
||||||
int total = 0;
|
|
||||||
for (int j = 0 ; j < text_scaling ; ++j) {
|
|
||||||
total += in[x + line_size_in * (j + text_scaling * y)];
|
|
||||||
}
|
|
||||||
out[x + line_size_out * y] = total / text_scaling;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const int shift = 32-12-8; // => max size = 4096, max alpha = 255
|
|
||||||
int h1 = img_in.GetHeight(), w = img_out.GetWidth();
|
|
||||||
int out_fact = (h << shift) / h1; // how much to output for 256 input = 1 pixel
|
|
||||||
int out_rest = (h << shift) % h1;
|
|
||||||
int mul = 128 + min(256, 128*h1/(text_scaling*h));
|
|
||||||
for (int x = 0 ; x < w ; ++x) {
|
|
||||||
int in_rem = out_fact + out_rest;
|
|
||||||
for (int y = 0 ; y < h ; ++y) {
|
|
||||||
int out_rem = 1 << shift;
|
|
||||||
int tot = 0;
|
|
||||||
while (out_rem >= in_rem) {
|
|
||||||
// eat a whole input pixel
|
|
||||||
tot += *in * in_rem;
|
|
||||||
out_rem -= in_rem;
|
|
||||||
in_rem = out_fact;
|
|
||||||
in += line_size_in;
|
|
||||||
}
|
|
||||||
if (out_rem > 0) {
|
|
||||||
// eat a partial input pixel
|
|
||||||
tot += *in * out_rem;
|
|
||||||
in_rem -= out_rem;
|
|
||||||
}
|
|
||||||
// store
|
|
||||||
*out = top(((tot >> shift) * mul) >> 8);
|
|
||||||
out += line_size_out;
|
|
||||||
}
|
|
||||||
in = in - h1 * line_size_in + 1;
|
|
||||||
out = out - h * line_size_out + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// simple blur
|
|
||||||
int blur_alpha_pixel(Byte* in, int x, int y, int width, int height) {
|
|
||||||
return (2 * ( in[0]) + // center
|
|
||||||
(x == 0 ? in[0] : in[-1]) + // left
|
|
||||||
(y == 0 ? in[0] : in[-width]) + // up
|
|
||||||
(x == width - 1 ? in[0] : in[1]) + // right
|
|
||||||
(y == height - 1 ? in[0] : in[width]) // down
|
|
||||||
) / 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: move me?
|
|
||||||
void blur_image_alpha(Image& img) {
|
|
||||||
int width = img.GetWidth(), height = img.GetHeight();
|
|
||||||
Byte* data = img.GetAlpha();
|
|
||||||
for (int y = 0 ; y < height ; ++y) {
|
|
||||||
for (int x = 0 ; x < width ; ++x) {
|
|
||||||
*data = blur_alpha_pixel(data, x, y, width, height);
|
|
||||||
++data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw text by first drawing it using a larger font and then downsampling it
|
// Draw text by first drawing it using a larger font and then downsampling it
|
||||||
// optionally rotated by an angle
|
// optionally rotated by an angle
|
||||||
void draw_resampled_text(DC& dc, const RealPoint& pos, const RealRect& rect, double stretch, Radians angle, Color color, const String& text, int blur_radius, int repeat) {
|
void draw_resampled_text(DC& dc, const String& text, const RealPoint& pos, const RealRect& rect, Radians angle, Color color, int blur_radius, Color stroke_color, int stroke_radius, double stretch) {
|
||||||
// transparent text can be ignored
|
// transparent text can be ignored
|
||||||
if (color.Alpha() == 0) return;
|
if (color.Alpha() == 0) return;
|
||||||
// enlarge slightly; some fonts are larger then the GetTextExtent tells us (especially italic fonts)
|
// enlarge slightly; some fonts are larger then the GetTextExtent tells us (especially italic fonts)
|
||||||
int w = static_cast<int>(rect.width) + 3 + 2 * blur_radius, h = static_cast<int>(rect.height) + 1 + 2 * blur_radius;
|
int w = static_cast<int>(rect.width) + 4, h = static_cast<int>(rect.height) + 2;
|
||||||
// determine sub-pixel position
|
// determine sub-pixel position
|
||||||
int xi = static_cast<int>(rect.x) - blur_radius / text_scaling,
|
int xi = static_cast<int>(rect.x),
|
||||||
yi = static_cast<int>(rect.y) - blur_radius / text_scaling;
|
yi = static_cast<int>(rect.y);
|
||||||
int xsub = static_cast<int>(text_scaling * (pos.x - xi)),
|
int xsub = static_cast<int>(text_scaling * (pos.x - xi)),
|
||||||
ysub = static_cast<int>(text_scaling * (pos.y - yi));
|
ysub = static_cast<int>(text_scaling * (pos.y - yi));
|
||||||
// draw text
|
// draw text as mask (white text on black background)
|
||||||
Bitmap buffer(w * text_scaling, h * text_scaling, 24); // should be initialized to black
|
Bitmap buffer(w * text_scaling, h * text_scaling, 24);
|
||||||
wxMemoryDC mdc;
|
wxMemoryDC mdc;
|
||||||
mdc.SelectObject(buffer);
|
mdc.SelectObject(buffer);
|
||||||
clearDC_black(mdc);
|
clearDC_black(mdc);
|
||||||
// now draw the text
|
|
||||||
mdc.SetFont(dc.GetFont());
|
mdc.SetFont(dc.GetFont());
|
||||||
mdc.SetTextForeground(*wxWHITE);
|
mdc.SetTextForeground(*wxWHITE);
|
||||||
mdc.DrawRotatedText(text, xsub, ysub, rad_to_deg(angle));
|
mdc.DrawRotatedText(text, xsub, ysub, rad_to_deg(angle));
|
||||||
// get image
|
|
||||||
mdc.SelectObject(wxNullBitmap);
|
mdc.SelectObject(wxNullBitmap);
|
||||||
// step 2. sample down
|
// downsample
|
||||||
double ca = fabs(cos(angle)), sa = fabs(sin(angle));
|
double ca = fabs(cos(angle)), sa = fabs(sin(angle));
|
||||||
w += int(w * (stretch - 1) * ca); // GCC makes annoying conversion warnings if *= is used here.
|
w += int(w * (stretch - 1) * ca); // GCC makes annoying conversion warnings if *= is used here.
|
||||||
h += int(h * (stretch - 1) * sa);
|
h += int(h * (stretch - 1) * sa);
|
||||||
Image img_small(w, h, false);
|
Image img(w, h, false);
|
||||||
fill_image(img_small, color);
|
downsample_to_alpha(buffer, img);
|
||||||
downsample_to_alpha(buffer, img_small);
|
// if there is no stroke effect, just add blur and draw
|
||||||
// multiply alpha
|
if (stroke_radius == 0) {
|
||||||
if (color.Alpha() != 255) {
|
if (color.Alpha() != 255) {
|
||||||
set_alpha(img_small, color.Alpha() / 255.);
|
set_alpha(img, color.Alpha() / 255.);
|
||||||
}
|
}
|
||||||
// blur
|
if (blur_radius > 0) {
|
||||||
for (int i = 0 ; i < blur_radius ; ++i) {
|
Image s_img(w + 2*blur_radius, h + 2*blur_radius);
|
||||||
blur_image_alpha(img_small);
|
set_alpha(s_img, 0);
|
||||||
}
|
s_img.Paste(img, blur_radius, blur_radius, wxIMAGE_ALPHA_BLEND_COMPOSE);
|
||||||
// step 3. draw to dc
|
for (int i = 0 ; i < blur_radius ; ++i) {
|
||||||
for (int i = 0 ; i < repeat ; ++i) {
|
blur_image_alpha(s_img, 3);
|
||||||
dc.DrawBitmap(img_small, xi, yi);
|
}
|
||||||
|
fill_image(s_img, color);
|
||||||
|
dc.DrawBitmap(s_img, xi-blur_radius, yi-blur_radius);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fill_image(img, color);
|
||||||
|
dc.DrawBitmap(img, xi, yi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// otherwise add stroke effect
|
||||||
|
else {
|
||||||
|
int radius = blur_radius + stroke_radius;
|
||||||
|
Image s_img(w + 2*radius, h + 2*radius);
|
||||||
|
set_alpha(s_img, 0);
|
||||||
|
s_img.Paste(img, radius, radius, wxIMAGE_ALPHA_BLEND_COMPOSE);
|
||||||
|
for (int i = 0 ; i < stroke_radius ; ++i) {
|
||||||
|
thicken_image_alpha(s_img, 1);
|
||||||
|
}
|
||||||
|
for (int i = 0 ; i < blur_radius ; ++i) {
|
||||||
|
blur_image_alpha(s_img, 3);
|
||||||
|
}
|
||||||
|
if (stroke_color.Alpha() != 255) {
|
||||||
|
set_alpha(s_img, stroke_color.Alpha() / 255.);
|
||||||
|
}
|
||||||
|
fill_image(s_img, stroke_color);
|
||||||
|
if (stroke_color != color) {
|
||||||
|
fill_image(img, color);
|
||||||
|
if (color.Alpha() != 255) {
|
||||||
|
set_alpha(img, color.Alpha() / 255.);
|
||||||
|
}
|
||||||
|
s_img.Paste(img, radius, radius, wxIMAGE_ALPHA_BLEND_COMPOSE);
|
||||||
|
}
|
||||||
|
dc.DrawBitmap(s_img, xi-radius, yi-radius);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ void FontTextElement::draw(RotatedDC& dc, double scale, const RealRect& rect, co
|
|||||||
margin = RealSize(1., 0);
|
margin = RealSize(1., 0);
|
||||||
}
|
}
|
||||||
dc.SetFont(*font, scale);
|
dc.SetFont(*font, scale);
|
||||||
dc.DrawTextWithShadow(text, *font, rect.position() + margin);
|
dc.DrawTextWithShadowOrStroke(text, *font, rect.position() + margin);
|
||||||
if (native_look) font->color = font_color;
|
if (native_look) font->color = font_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
void SymbolTextElement::draw(RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end, bool native_look) const {
|
void SymbolTextElement::draw(RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end, bool native_look) const {
|
||||||
if (!(what & DRAW_NORMAL)) return;
|
if (!(what & DRAW_NORMAL)) return;
|
||||||
if (font.font) {
|
if (font.font) {
|
||||||
font.font->draw(dc, ctx, rect, font.size * scale, font.alignment, content.substr(start - this->start, end-start));
|
font.font->draw(dc, ctx, rect, scale, font, content.substr(start - this->start, end-start));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ void draw_choice_viewer(RotatedDC& dc, ValueViewer& viewer, ChoiceStyle& style,
|
|||||||
dc.SetFont(font, 1.0);
|
dc.SetFont(font, 1.0);
|
||||||
RealSize size = dc.GetTextExtent(text);
|
RealSize size = dc.GetTextExtent(text);
|
||||||
RealPoint text_pos = align_in_rect(text_align, size, dc.getInternalRect()) + RealSize(margin, 0);
|
RealPoint text_pos = align_in_rect(text_align, size, dc.getInternalRect()) + RealSize(margin, 0);
|
||||||
dc.DrawTextWithShadow(text, font, text_pos);
|
dc.DrawTextWithShadowOrStroke(text, font, text_pos);
|
||||||
if (viewer.nativeLook()) font.color = font_color;
|
if (viewer.nativeLook()) font.color = font_color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,15 +119,11 @@ Bitmap ImageValueViewer::imagePlaceholder(const Rotation& rot, UInt w, UInt h, c
|
|||||||
// only when in editor mode
|
// only when in editor mode
|
||||||
for (UInt size = 12 ; size > 2 ; --size) {
|
for (UInt size = 12 ; size > 2 ; --size) {
|
||||||
dc.SetFont(wxFont(size, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
|
dc.SetFont(wxFont(size, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
|
||||||
RealSize rs = dc.GetTextExtent(_("double click to load image"));
|
RealSize rs = dc.GetTextExtent(_LABEL_("load image"));
|
||||||
if (rs.width <= w - 10 && rs.height < h - 10) {
|
if (rs.width <= w - 10 && rs.height < h - 10) {
|
||||||
// text fits
|
// text fits
|
||||||
RealPoint pos = align_in_rect(ALIGN_MIDDLE_CENTER, rs, rect);
|
RealPoint pos = align_in_rect(ALIGN_MIDDLE_CENTER, rs, rect);
|
||||||
bool black_on_white = !default_image.Ok() || very_light(default_image);
|
dc.DrawText(_LABEL_("load image"), pos, Color(255,255,255), 2, Color(0,0,0), 3); // stroked
|
||||||
dc.SetTextForeground(black_on_white ? *wxWHITE : *wxBLACK);
|
|
||||||
dc.DrawText(_("double click to load image"), pos, 2, 4); // blurred
|
|
||||||
dc.SetTextForeground(black_on_white ? *wxBLACK : *wxWHITE);
|
|
||||||
dc.DrawText(_("double click to load image"), pos);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ void MultipleChoiceValueViewer::drawChoice(RotatedDC& dc, RealPoint& pos, const
|
|||||||
dc.SetFont(font,1);
|
dc.SetFont(font,1);
|
||||||
RealSize text_size = dc.GetTextExtent(text);
|
RealSize text_size = dc.GetTextExtent(text);
|
||||||
RealPoint text_pos = align_in_rect(ALIGN_MIDDLE_LEFT, text_size, RealRect(pos.x + size.width + 1, pos.y, 0,size.height)) + margin;
|
RealPoint text_pos = align_in_rect(ALIGN_MIDDLE_LEFT, text_size, RealRect(pos.x + size.width + 1, pos.y, 0,size.height)) + margin;
|
||||||
dc.DrawTextWithShadow(text, font, text_pos);
|
dc.DrawTextWithShadowOrStroke(text, font, text_pos);
|
||||||
size = add_horizontal(size, text_size);
|
size = add_horizontal(size, text_size);
|
||||||
if (nativeLook()) font.color = font_color;
|
if (nativeLook()) font.color = font_color;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,6 @@ void PackageChoiceValueViewer::draw(RotatedDC& dc) {
|
|||||||
}
|
}
|
||||||
dc.SetFont(font, 1.0);
|
dc.SetFont(font, 1.0);
|
||||||
RealPoint pos = align_in_rect(ALIGN_MIDDLE_LEFT, RealSize(0, dc.GetCharHeight()), dc.getInternalRect()) + RealSize(17., 0) + margin;
|
RealPoint pos = align_in_rect(ALIGN_MIDDLE_LEFT, RealSize(0, dc.GetCharHeight()), dc.getInternalRect()) + RealSize(17., 0) + margin;
|
||||||
dc.DrawTextWithShadow(text, font, pos);
|
dc.DrawTextWithShadowOrStroke(text, font, pos);
|
||||||
if (nativeLook()) font.color = font_color;
|
if (nativeLook()) font.color = font_color;
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-11
@@ -182,27 +182,27 @@ RotatedDC::RotatedDC(DC& dc, const Rotation& rotation, RenderQuality quality)
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : RotatedDC : Drawing
|
// ----------------------------------------------------------------------------- : RotatedDC : Drawing
|
||||||
|
|
||||||
void RotatedDC::DrawText(const String& text, const RealPoint& pos, int blur_radius, int boldness, double stretch_) {
|
void RotatedDC::DrawText(const String& text, const RealPoint& pos, int blur_radius, Color stroke_color, int stroke_radius, double stretch) {
|
||||||
DrawText(text, pos, dc.GetTextForeground(), blur_radius, boldness, stretch_);
|
DrawText(text, pos, dc.GetTextForeground(), blur_radius, stroke_color, stroke_radius, stretch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RotatedDC::DrawText(const String& text, const RealPoint& pos, Color color, int blur_radius, int boldness, double stretch_) {
|
void RotatedDC::DrawText(const String& text, const RealPoint& pos, Color color, int blur_radius, Color stroke_color, int stroke_radius, double stretch) {
|
||||||
if (text.empty()) return;
|
if (text.empty()) return;
|
||||||
if (color.Alpha() == 0) return;
|
if (color.Alpha() == 0) return;
|
||||||
if (quality >= QUALITY_AA) {
|
if (quality >= QUALITY_AA) {
|
||||||
RealRect r(pos, GetTextExtent(text));
|
RealRect r(pos, GetTextExtent(text));
|
||||||
RealRect r_ext = trRectToBB(r);
|
RealRect r_ext = trRectToBB(r);
|
||||||
RealPoint pos2 = tr(pos);
|
RealPoint pos2 = tr(pos);
|
||||||
stretch_ *= getStretch();
|
stretch *= getStretch();
|
||||||
if (fabs(stretch_ - 1) > 1e-6) {
|
if (fabs(stretch - 1) > 1e-6) {
|
||||||
r.width *= stretch_;
|
r.width *= stretch;
|
||||||
RealRect r_ext2 = trRectToBB(r);
|
RealRect r_ext2 = trRectToBB(r);
|
||||||
pos2.x += r_ext2.x - r_ext.x;
|
pos2.x += r_ext2.x - r_ext.x;
|
||||||
pos2.y += r_ext2.y - r_ext.y;
|
pos2.y += r_ext2.y - r_ext.y;
|
||||||
r_ext.x = r_ext2.x;
|
r_ext.x = r_ext2.x;
|
||||||
r_ext.y = r_ext2.y;
|
r_ext.y = r_ext2.y;
|
||||||
}
|
}
|
||||||
draw_resampled_text(dc, pos2, r_ext, stretch_, angle, color, text, blur_radius, boldness);
|
draw_resampled_text(dc, text, pos2, r_ext, angle, color, blur_radius, stroke_color, stroke_radius, stretch);
|
||||||
} else if (quality >= QUALITY_SUB_PIXEL) {
|
} else if (quality >= QUALITY_SUB_PIXEL) {
|
||||||
RealPoint p_ext = tr(pos)*text_scaling;
|
RealPoint p_ext = tr(pos)*text_scaling;
|
||||||
double usx,usy;
|
double usx,usy;
|
||||||
@@ -216,11 +216,14 @@ void RotatedDC::DrawText(const String& text, const RealPoint& pos, Color color,
|
|||||||
dc.SetTextForeground(color);
|
dc.SetTextForeground(color);
|
||||||
dc.DrawRotatedText(text, (int) p_ext.x, (int) p_ext.y, rad_to_deg(angle));
|
dc.DrawRotatedText(text, (int) p_ext.x, (int) p_ext.y, rad_to_deg(angle));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RotatedDC::DrawTextWithShadow(const String& text, const Font& font, const RealPoint& pos, double scale, double stretch) {
|
void RotatedDC::DrawTextWithShadowOrStroke(const String& text, const Font& font, const RealPoint& pos, double scale, double stretch) {
|
||||||
DrawText(text, pos + RealSize(font.shadow_displacement_x, font.shadow_displacement_y) * scale, font.shadow_color, font.shadow_blur * scale, 1, stretch);
|
double s_scale = scale * dc.GetFont().GetPointSize() / text_scaling / 15.;
|
||||||
DrawText(text, pos, font.color, 0, 1, stretch);
|
if (font.hasShadow() && !font.hasStroke()) {
|
||||||
|
DrawText(text, pos + RealSize(font.shadow_displacement_x, font.shadow_displacement_y) * scale, font.shadow_color, lround(font.shadow_blur * s_scale), Color(0,0,0), 0, stretch);
|
||||||
|
}
|
||||||
|
DrawText(text, pos, font.color, lround(font.stroke_blur * s_scale), font.stroke_color, lround(font.stroke_radius * s_scale), stretch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RotatedDC::DrawBitmap(const Bitmap& bitmap, const RealPoint& pos) {
|
void RotatedDC::DrawBitmap(const Bitmap& bitmap, const RealPoint& pos) {
|
||||||
|
|||||||
@@ -157,10 +157,10 @@ public:
|
|||||||
// --------------------------------------------------- : Drawing
|
// --------------------------------------------------- : Drawing
|
||||||
|
|
||||||
/// Draw text
|
/// Draw text
|
||||||
void DrawText (const String& text, const RealPoint& pos, int blur_radius = 0, int boldness = 1, double stretch = 1.0);
|
void DrawText (const String& text, const RealPoint& pos, int blur_radius = 0, Color stroke_color = Color(0,0,0), int stroke_radius = 0, double stretch = 1.0);
|
||||||
void DrawText (const String& text, const RealPoint& pos, Color color, int blur_radius = 0, int boldness = 1, double stretch = 1.0);
|
void DrawText (const String& text, const RealPoint& pos, Color color, int blur_radius = 0, Color stroke_color = Color(0,0,0), int stroke_radius = 0, double stretch = 1.0);
|
||||||
/// Draw text with the shadow and color settings of the given font
|
/// Draw text with a shadow or stroke, and color settings of the given font
|
||||||
void DrawTextWithShadow(const String& text, const Font& font, const RealPoint& pos, double scale = 1.0, double stretch = 1.0);
|
void DrawTextWithShadowOrStroke(const String& text, const Font& font, const RealPoint& pos, double scale = 1.0, double stretch = 1.0);
|
||||||
/// Draw abitmap, it must already be zoomed!
|
/// Draw abitmap, it must already be zoomed!
|
||||||
void DrawBitmap(const Bitmap& bitmap, const RealPoint& pos);
|
void DrawBitmap(const Bitmap& bitmap, const RealPoint& pos);
|
||||||
/// Draw an image using the given combining mode, the image must already be zoomed!
|
/// Draw an image using the given combining mode, the image must already be zoomed!
|
||||||
|
|||||||
Reference in New Issue
Block a user