Nova logo oficial: o guará com o anel laranja
A arte do usuário (assets/logo/*-fonte.png) passa a ser a logo do projeto. scripts/processar-logo.py tira o fundo (só o que toca a borda e os bolsões internos, com a faixa da borda refeita pela cor real do desenho, sem halo) e gera as variantes clara e escura (768 e 128 px) e o ícone do app. O app escolhe a variante pelo tema (barra lateral, topo e tela inicial), o favicon e o servidor do guara ui passam a PNG, os ícones do Tauri são regenerados e o README usa <picture> para claro e escuro. A logo SVG antiga e o gerador dela saem. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
No files matched your search
@@ -1,4 +1,4 @@
|
|||||||
<p align="center"><img src="apps/gui/ui/guara-logo.svg" width="360" alt="Guará"></p>
|
<p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="apps/gui/ui/guara-dark.png"><img src="apps/gui/ui/guara-light.png" width="300" alt="Guará"></picture></p>
|
||||||
<h1 align="center">Guará</h1>
|
<h1 align="center">Guará</h1>
|
||||||
<p align="center">Free file recovery for hard drives, SSDs and USB sticks.<br>Terminal and graphical interface · Windows, Linux and macOS · read-only on the source.</p>
|
<p align="center">Free file recovery for hard drives, SSDs and USB sticks.<br>Terminal and graphical interface · Windows, Linux and macOS · read-only on the source.</p>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<p align="center"><img src="apps/gui/ui/guara-logo.svg" width="360" alt="Guará"></p>
|
<p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="apps/gui/ui/guara-dark.png"><img src="apps/gui/ui/guara-light.png" width="300" alt="Guará"></picture></p>
|
||||||
<h1 align="center">Guará</h1>
|
<h1 align="center">Guará</h1>
|
||||||
<p align="center">Recuperação de arquivos livre e gratuita para HD, SSD e pendrive.<br>Terminal e interface gráfica · Windows, Linux e macOS · somente leitura na origem.</p>
|
<p align="center">Recuperação de arquivos livre e gratuita para HD, SSD e pendrive.<br>Terminal e interface gráfica · Windows, Linux e macOS · somente leitura na origem.</p>
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 103 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 835 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 403 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 387 KiB |
@@ -332,7 +332,7 @@ dialog.lightbox[open] { display: grid; }
|
|||||||
.lb-head .ttl { flex: 1; min-width: 0; } .lb-head .ttl b { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .lb-head .ttl small { color: var(--text-2); }
|
.lb-head .ttl { flex: 1; min-width: 0; } .lb-head .ttl b { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .lb-head .ttl small { color: var(--text-2); }
|
||||||
.lb-body { padding: 12px; min-height: 0; }
|
.lb-body { padding: 12px; min-height: 0; }
|
||||||
|
|
||||||
.hero-logo { width: min(440px, 80%); height: auto; display: block; margin: 0 0 22px -4px; }
|
.hero-logo { width: min(340px, 70%); height: auto; margin: 0 0 14px -6px; }
|
||||||
.pill.accent { background: var(--accent-soft); color: var(--accent); }
|
.pill.accent { background: var(--accent-soft); color: var(--accent); }
|
||||||
|
|
||||||
/* ------------------------------------------------------------ explorador de arquivos */
|
/* ------------------------------------------------------------ explorador de arquivos */
|
||||||
@@ -516,8 +516,15 @@ dialog.lightbox[open] { display: grid; }
|
|||||||
.h-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; background: var(--ok); }
|
.h-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; background: var(--ok); }
|
||||||
.h-dot.warning { background: var(--warn); } .h-dot.failing { background: var(--bad); }
|
.h-dot.warning { background: var(--warn); } .h-dot.failing { background: var(--bad); }
|
||||||
|
|
||||||
/* logo inline: segue o tema escolhido no app, não o do sistema */
|
/* logo: a variante clara ou a escura, conforme o tema escolhido no app (não só o do sistema) */
|
||||||
.logo .a { stroke: var(--accent); } .logo .b { stroke: var(--accent-2); } .logo .t { fill: var(--text); }
|
.logo-img { display: none; flex: none; }
|
||||||
|
.logo-img.light { display: block; }
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root:not([data-theme="light"]) .logo-img.light { display: none; }
|
||||||
|
:root:not([data-theme="light"]) .logo-img.dark { display: block; }
|
||||||
|
}
|
||||||
|
:root[data-theme="dark"] .logo-img.light { display: none; }
|
||||||
|
:root[data-theme="dark"] .logo-img.dark { display: block; }
|
||||||
|
|
||||||
/* atualização do app */
|
/* atualização do app */
|
||||||
.update-card { position: fixed; right: 18px; bottom: 18px; z-index: 60; width: min(400px, calc(100vw - 36px)); display: grid; gap: 10px; padding: 16px 18px; border-radius: 18px; background: var(--surface); box-shadow: var(--shadow); border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent); }
|
.update-card { position: fixed; right: 18px; bottom: 18px; z-index: 60; width: min(400px, calc(100vw - 36px)); display: grid; gap: 10px; padding: 16px 18px; border-radius: 18px; background: var(--surface); box-shadow: var(--shadow); border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent); }
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ function renderHome() {
|
|||||||
S.device = null; S.job = null;
|
S.device = null; S.job = null;
|
||||||
renderSide();
|
renderSide();
|
||||||
main.innerHTML = `<div class="page">
|
main.innerHTML = `<div class="page">
|
||||||
<section class="hero"><img class="hero-logo" src="guara-logo.svg" alt="Guará"><h1>Encontre o que você achou que tinha perdido.</h1>
|
<section class="hero"><img class="logo-img hero-logo dark" src="guara-dark.png" alt="Guará"><img class="logo-img hero-logo light" src="guara-light.png" alt="Guará"><h1>Encontre o que você achou que tinha perdido.</h1>
|
||||||
<p>Escolha um disco, SSD ou pendrive ao lado. O Guará lê tudo: arquivos apagados, partições perdidas e espaço não particionado, sem escrever nada no disco de origem.</p></section>
|
<p>Escolha um disco, SSD ou pendrive ao lado. O Guará lê tudo: arquivos apagados, partições perdidas e espaço não particionado, sem escrever nada no disco de origem.</p></section>
|
||||||
<div class="cards">
|
<div class="cards">
|
||||||
<div class="card"><h3>Uma varredura, tudo junto</h3><p>Metadados do sistema de arquivos e busca por assinatura na mesma passada, sem duplicatas.</p></div>
|
<div class="card"><h3>Uma varredura, tudo junto</h3><p>Metadados do sistema de arquivos e busca por assinatura na mesma passada, sem duplicatas.</p></div>
|
||||||
|
|||||||
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 339 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 346 KiB |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" role="img" aria-label="Guará"><style>.a{stroke:#0f766e}.b{stroke:#14b8a6}.t{fill:#1d1d1f}@media (prefers-color-scheme:dark){.a{stroke:#2dd4bf}.b{stroke:#5eead4}.t{fill:#f5f5f7}}</style><defs><clipPath id="g-head"><path d="M50 95 C46 88 43 80 40 74 C33 70 25 64 22 56 L14 6 L36 30 C40 28 45 27 50 27 C55 27 60 28 64 30 L86 6 L78 56 C75 64 67 70 60 74 C57 80 54 88 50 95 Z"/></clipPath></defs><g clip-path="url(#g-head)" fill="none" stroke-width="4.2"><path class="a" d="M50 93A7 7 0 0 1 50 107"/><path class="b" d="M50 93A7 7 0 0 0 50 107" stroke-dasharray="3 3" stroke-dashoffset="0"/><path class="a" d="M50 86A14 14 0 0 1 50 114"/><path class="b" d="M50 86A14 14 0 0 0 50 114" stroke-dasharray="6 4" stroke-dashoffset="3"/><path class="a" d="M50 79A21 21 0 0 1 50 121"/><path class="b" d="M50 79A21 21 0 0 0 50 121" stroke-dasharray="9 5" stroke-dashoffset="6"/><path class="a" d="M50 72A28 28 0 0 1 50 128"/><path class="b" d="M50 72A28 28 0 0 0 50 128" stroke-dasharray="3 6" stroke-dashoffset="9"/><path class="a" d="M50 65A35 35 0 0 1 50 135"/><path class="b" d="M50 65A35 35 0 0 0 50 135" stroke-dasharray="6 3" stroke-dashoffset="12"/><path class="a" d="M50 58A42 42 0 0 1 50 142"/><path class="b" d="M50 58A42 42 0 0 0 50 142" stroke-dasharray="9 4" stroke-dashoffset="15"/><path class="a" d="M50 51A49 49 0 0 1 50 149"/><path class="b" d="M50 51A49 49 0 0 0 50 149" stroke-dasharray="3 5" stroke-dashoffset="18"/><path class="a" d="M50 44A56 56 0 0 1 50 156"/><path class="b" d="M50 44A56 56 0 0 0 50 156" stroke-dasharray="6 6" stroke-dashoffset="21"/><path class="a" d="M50 37A63 63 0 0 1 50 163"/><path class="b" d="M50 37A63 63 0 0 0 50 163" stroke-dasharray="9 3" stroke-dashoffset="24"/><path class="a" d="M50 30A70 70 0 0 1 50 170"/><path class="b" d="M50 30A70 70 0 0 0 50 170" stroke-dasharray="3 4" stroke-dashoffset="27"/><path class="a" d="M50 23A77 77 0 0 1 50 177"/><path class="b" d="M50 23A77 77 0 0 0 50 177" stroke-dasharray="6 5" stroke-dashoffset="30"/><path class="a" d="M50 16A84 84 0 0 1 50 184"/><path class="b" d="M50 16A84 84 0 0 0 50 184" stroke-dasharray="9 6" stroke-dashoffset="33"/><path class="a" d="M50 9A91 91 0 0 1 50 191"/><path class="b" d="M50 9A91 91 0 0 0 50 191" stroke-dasharray="3 3" stroke-dashoffset="36"/><path class="a" d="M50 2A98 98 0 0 1 50 198"/><path class="b" d="M50 2A98 98 0 0 0 50 198" stroke-dasharray="6 4" stroke-dashoffset="39"/><rect class="t" stroke="none" x="0" y="74" width="100" height="30"/></g><path class="t" d="M37 50Q42 47 46 52Q41 53 37 50ZM63 50Q58 47 54 52Q59 53 63 50Z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 2.6 KiB |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" role="img" aria-label="Guará"><style>.a{stroke:#0f766e}.b{stroke:#14b8a6}.t{fill:#1d1d1f}@media (prefers-color-scheme:dark){.a{stroke:#2dd4bf}.b{stroke:#5eead4}.t{fill:#f5f5f7}}</style><defs><clipPath id="g-head"><path d="M50 95 C46 88 43 80 40 74 C33 70 25 64 22 56 L14 6 L36 30 C40 28 45 27 50 27 C55 27 60 28 64 30 L86 6 L78 56 C75 64 67 70 60 74 C57 80 54 88 50 95 Z"/></clipPath></defs><g clip-path="url(#g-head)" fill="none" stroke-width="4.2"><path class="a" d="M50 93A7 7 0 0 1 50 107"/><path class="b" d="M50 93A7 7 0 0 0 50 107" stroke-dasharray="3 3" stroke-dashoffset="0"/><path class="a" d="M50 86A14 14 0 0 1 50 114"/><path class="b" d="M50 86A14 14 0 0 0 50 114" stroke-dasharray="6 4" stroke-dashoffset="3"/><path class="a" d="M50 79A21 21 0 0 1 50 121"/><path class="b" d="M50 79A21 21 0 0 0 50 121" stroke-dasharray="9 5" stroke-dashoffset="6"/><path class="a" d="M50 72A28 28 0 0 1 50 128"/><path class="b" d="M50 72A28 28 0 0 0 50 128" stroke-dasharray="3 6" stroke-dashoffset="9"/><path class="a" d="M50 65A35 35 0 0 1 50 135"/><path class="b" d="M50 65A35 35 0 0 0 50 135" stroke-dasharray="6 3" stroke-dashoffset="12"/><path class="a" d="M50 58A42 42 0 0 1 50 142"/><path class="b" d="M50 58A42 42 0 0 0 50 142" stroke-dasharray="9 4" stroke-dashoffset="15"/><path class="a" d="M50 51A49 49 0 0 1 50 149"/><path class="b" d="M50 51A49 49 0 0 0 50 149" stroke-dasharray="3 5" stroke-dashoffset="18"/><path class="a" d="M50 44A56 56 0 0 1 50 156"/><path class="b" d="M50 44A56 56 0 0 0 50 156" stroke-dasharray="6 6" stroke-dashoffset="21"/><path class="a" d="M50 37A63 63 0 0 1 50 163"/><path class="b" d="M50 37A63 63 0 0 0 50 163" stroke-dasharray="9 3" stroke-dashoffset="24"/><path class="a" d="M50 30A70 70 0 0 1 50 170"/><path class="b" d="M50 30A70 70 0 0 0 50 170" stroke-dasharray="3 4" stroke-dashoffset="27"/><path class="a" d="M50 23A77 77 0 0 1 50 177"/><path class="b" d="M50 23A77 77 0 0 0 50 177" stroke-dasharray="6 5" stroke-dashoffset="30"/><path class="a" d="M50 16A84 84 0 0 1 50 184"/><path class="b" d="M50 16A84 84 0 0 0 50 184" stroke-dasharray="9 6" stroke-dashoffset="33"/><path class="a" d="M50 9A91 91 0 0 1 50 191"/><path class="b" d="M50 9A91 91 0 0 0 50 191" stroke-dasharray="3 3" stroke-dashoffset="36"/><path class="a" d="M50 2A98 98 0 0 1 50 198"/><path class="b" d="M50 2A98 98 0 0 0 50 198" stroke-dasharray="6 4" stroke-dashoffset="39"/><rect class="t" stroke="none" x="0" y="74" width="100" height="30"/></g><path class="t" d="M37 50Q42 47 46 52Q41 53 37 50ZM63 50Q58 47 54 52Q59 53 63 50Z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 2.6 KiB |
@@ -5,7 +5,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||||
<meta name="color-scheme" content="light dark">
|
<meta name="color-scheme" content="light dark">
|
||||||
<title>Guará</title>
|
<title>Guará</title>
|
||||||
<link rel="icon" href="guara.svg" type="image/svg+xml">
|
<link rel="icon" href="guara-dark-s.png" type="image/png">
|
||||||
<link rel="stylesheet" href="app.css">
|
<link rel="stylesheet" href="app.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -14,10 +14,10 @@
|
|||||||
<button class="icon-btn" id="menuBtn" aria-label="Abrir menu" aria-expanded="false">
|
<button class="icon-btn" id="menuBtn" aria-label="Abrir menu" aria-expanded="false">
|
||||||
<svg viewBox="0 0 24 24" width="22" height="22"><path d="M4 7h16M4 12h16M4 17h16" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="none"/></svg>
|
<svg viewBox="0 0 24 24" width="22" height="22"><path d="M4 7h16M4 12h16M4 17h16" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="none"/></svg>
|
||||||
</button>
|
</button>
|
||||||
<svg class="logo" width="24" height="24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><clipPath id="g-head-top"><path d="M50 95 C46 88 43 80 40 74 C33 70 25 64 22 56 L14 6 L36 30 C40 28 45 27 50 27 C55 27 60 28 64 30 L86 6 L78 56 C75 64 67 70 60 74 C57 80 54 88 50 95 Z"/></clipPath></defs><g clip-path="url(#g-head-top)" fill="none" stroke-width="4.2"><path class="a" d="M50 93A7 7 0 0 1 50 107"/><path class="b" d="M50 93A7 7 0 0 0 50 107" stroke-dasharray="3 3" stroke-dashoffset="0"/><path class="a" d="M50 86A14 14 0 0 1 50 114"/><path class="b" d="M50 86A14 14 0 0 0 50 114" stroke-dasharray="6 4" stroke-dashoffset="3"/><path class="a" d="M50 79A21 21 0 0 1 50 121"/><path class="b" d="M50 79A21 21 0 0 0 50 121" stroke-dasharray="9 5" stroke-dashoffset="6"/><path class="a" d="M50 72A28 28 0 0 1 50 128"/><path class="b" d="M50 72A28 28 0 0 0 50 128" stroke-dasharray="3 6" stroke-dashoffset="9"/><path class="a" d="M50 65A35 35 0 0 1 50 135"/><path class="b" d="M50 65A35 35 0 0 0 50 135" stroke-dasharray="6 3" stroke-dashoffset="12"/><path class="a" d="M50 58A42 42 0 0 1 50 142"/><path class="b" d="M50 58A42 42 0 0 0 50 142" stroke-dasharray="9 4" stroke-dashoffset="15"/><path class="a" d="M50 51A49 49 0 0 1 50 149"/><path class="b" d="M50 51A49 49 0 0 0 50 149" stroke-dasharray="3 5" stroke-dashoffset="18"/><path class="a" d="M50 44A56 56 0 0 1 50 156"/><path class="b" d="M50 44A56 56 0 0 0 50 156" stroke-dasharray="6 6" stroke-dashoffset="21"/><path class="a" d="M50 37A63 63 0 0 1 50 163"/><path class="b" d="M50 37A63 63 0 0 0 50 163" stroke-dasharray="9 3" stroke-dashoffset="24"/><path class="a" d="M50 30A70 70 0 0 1 50 170"/><path class="b" d="M50 30A70 70 0 0 0 50 170" stroke-dasharray="3 4" stroke-dashoffset="27"/><path class="a" d="M50 23A77 77 0 0 1 50 177"/><path class="b" d="M50 23A77 77 0 0 0 50 177" stroke-dasharray="6 5" stroke-dashoffset="30"/><path class="a" d="M50 16A84 84 0 0 1 50 184"/><path class="b" d="M50 16A84 84 0 0 0 50 184" stroke-dasharray="9 6" stroke-dashoffset="33"/><path class="a" d="M50 9A91 91 0 0 1 50 191"/><path class="b" d="M50 9A91 91 0 0 0 50 191" stroke-dasharray="3 3" stroke-dashoffset="36"/><path class="a" d="M50 2A98 98 0 0 1 50 198"/><path class="b" d="M50 2A98 98 0 0 0 50 198" stroke-dasharray="6 4" stroke-dashoffset="39"/><rect class="t" stroke="none" x="0" y="74" width="100" height="30"/></g><path class="t" d="M37 50Q42 47 46 52Q41 53 37 50ZM63 50Q58 47 54 52Q59 53 63 50Z"/></svg><strong>Guará</strong>
|
<img class="logo-img dark" src="guara-dark-s.png" width="24" height="24" alt=""><img class="logo-img light" src="guara-light-s.png" width="24" height="24" alt=""><strong>Guará</strong>
|
||||||
</header>
|
</header>
|
||||||
<aside class="sidebar" id="sidebar" aria-label="Dispositivos e sessões">
|
<aside class="sidebar" id="sidebar" aria-label="Dispositivos e sessões">
|
||||||
<div class="brand"><svg class="logo" width="30" height="30" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><clipPath id="g-head-side"><path d="M50 95 C46 88 43 80 40 74 C33 70 25 64 22 56 L14 6 L36 30 C40 28 45 27 50 27 C55 27 60 28 64 30 L86 6 L78 56 C75 64 67 70 60 74 C57 80 54 88 50 95 Z"/></clipPath></defs><g clip-path="url(#g-head-side)" fill="none" stroke-width="4.2"><path class="a" d="M50 93A7 7 0 0 1 50 107"/><path class="b" d="M50 93A7 7 0 0 0 50 107" stroke-dasharray="3 3" stroke-dashoffset="0"/><path class="a" d="M50 86A14 14 0 0 1 50 114"/><path class="b" d="M50 86A14 14 0 0 0 50 114" stroke-dasharray="6 4" stroke-dashoffset="3"/><path class="a" d="M50 79A21 21 0 0 1 50 121"/><path class="b" d="M50 79A21 21 0 0 0 50 121" stroke-dasharray="9 5" stroke-dashoffset="6"/><path class="a" d="M50 72A28 28 0 0 1 50 128"/><path class="b" d="M50 72A28 28 0 0 0 50 128" stroke-dasharray="3 6" stroke-dashoffset="9"/><path class="a" d="M50 65A35 35 0 0 1 50 135"/><path class="b" d="M50 65A35 35 0 0 0 50 135" stroke-dasharray="6 3" stroke-dashoffset="12"/><path class="a" d="M50 58A42 42 0 0 1 50 142"/><path class="b" d="M50 58A42 42 0 0 0 50 142" stroke-dasharray="9 4" stroke-dashoffset="15"/><path class="a" d="M50 51A49 49 0 0 1 50 149"/><path class="b" d="M50 51A49 49 0 0 0 50 149" stroke-dasharray="3 5" stroke-dashoffset="18"/><path class="a" d="M50 44A56 56 0 0 1 50 156"/><path class="b" d="M50 44A56 56 0 0 0 50 156" stroke-dasharray="6 6" stroke-dashoffset="21"/><path class="a" d="M50 37A63 63 0 0 1 50 163"/><path class="b" d="M50 37A63 63 0 0 0 50 163" stroke-dasharray="9 3" stroke-dashoffset="24"/><path class="a" d="M50 30A70 70 0 0 1 50 170"/><path class="b" d="M50 30A70 70 0 0 0 50 170" stroke-dasharray="3 4" stroke-dashoffset="27"/><path class="a" d="M50 23A77 77 0 0 1 50 177"/><path class="b" d="M50 23A77 77 0 0 0 50 177" stroke-dasharray="6 5" stroke-dashoffset="30"/><path class="a" d="M50 16A84 84 0 0 1 50 184"/><path class="b" d="M50 16A84 84 0 0 0 50 184" stroke-dasharray="9 6" stroke-dashoffset="33"/><path class="a" d="M50 9A91 91 0 0 1 50 191"/><path class="b" d="M50 9A91 91 0 0 0 50 191" stroke-dasharray="3 3" stroke-dashoffset="36"/><path class="a" d="M50 2A98 98 0 0 1 50 198"/><path class="b" d="M50 2A98 98 0 0 0 50 198" stroke-dasharray="6 4" stroke-dashoffset="39"/><rect class="t" stroke="none" x="0" y="74" width="100" height="30"/></g><path class="t" d="M37 50Q42 47 46 52Q41 53 37 50ZM63 50Q58 47 54 52Q59 53 63 50Z"/></svg><div><strong>Guará</strong><small>Recuperação de arquivos</small></div></div>
|
<div class="brand"><img class="logo-img dark" src="guara-dark-s.png" width="30" height="30" alt=""><img class="logo-img light" src="guara-light-s.png" width="30" height="30" alt=""><div><strong>Guará</strong><small>Recuperação de arquivos</small></div></div>
|
||||||
<nav>
|
<nav>
|
||||||
<div class="side-title">Dispositivos <button class="icon-btn small" id="refreshBtn" title="Atualizar lista" aria-label="Atualizar lista"><svg viewBox="0 0 24 24" width="16" height="16"><path d="M20 12a8 8 0 1 1-2.5-5.8M20 4v5h-5" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg></button></div>
|
<div class="side-title">Dispositivos <button class="icon-btn small" id="refreshBtn" title="Atualizar lista" aria-label="Atualizar lista"><svg viewBox="0 0 24 24" width="16" height="16"><path d="M20 12a8 8 0 1 1-2.5-5.8M20 4v5h-5" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg></button></div>
|
||||||
<ul id="deviceList" class="list"></ul>
|
<ul id="deviceList" class="list"></ul>
|
||||||
|
|||||||
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
@@ -12,9 +12,11 @@ const JS: &str = include_str!("../../../apps/gui/ui/app.js");
|
|||||||
const PREVIEW_JS: &str = include_str!("../../../apps/gui/ui/preview.js");
|
const PREVIEW_JS: &str = include_str!("../../../apps/gui/ui/preview.js");
|
||||||
const I18N_JS: &str = include_str!("../../../apps/gui/ui/i18n.js");
|
const I18N_JS: &str = include_str!("../../../apps/gui/ui/i18n.js");
|
||||||
const I18N_EN_JS: &str = include_str!("../../../apps/gui/ui/i18n-en.js");
|
const I18N_EN_JS: &str = include_str!("../../../apps/gui/ui/i18n-en.js");
|
||||||
const LOGO: &str = include_str!("../../../apps/gui/ui/guara-logo.svg");
|
|
||||||
const EXPLORER_JS: &str = include_str!("../../../apps/gui/ui/explorer.js");
|
const EXPLORER_JS: &str = include_str!("../../../apps/gui/ui/explorer.js");
|
||||||
const ICON: &str = include_str!("../../../apps/gui/ui/guara.svg");
|
const LOGO_DARK: &[u8] = include_bytes!("../../../apps/gui/ui/guara-dark.png");
|
||||||
|
const LOGO_LIGHT: &[u8] = include_bytes!("../../../apps/gui/ui/guara-light.png");
|
||||||
|
const LOGO_DARK_S: &[u8] = include_bytes!("../../../apps/gui/ui/guara-dark-s.png");
|
||||||
|
const LOGO_LIGHT_S: &[u8] = include_bytes!("../../../apps/gui/ui/guara-light-s.png");
|
||||||
const PDF_JS: &str = include_str!("../../../apps/gui/ui/vendor/pdf.min.mjs");
|
const PDF_JS: &str = include_str!("../../../apps/gui/ui/vendor/pdf.min.mjs");
|
||||||
const PDF_WORKER: &str = include_str!("../../../apps/gui/ui/vendor/pdf.worker.min.mjs");
|
const PDF_WORKER: &str = include_str!("../../../apps/gui/ui/vendor/pdf.worker.min.mjs");
|
||||||
|
|
||||||
@@ -98,8 +100,17 @@ fn handle(req: Request, eng: &Engine, token: &str, hosts: &[String]) {
|
|||||||
Response::from_string(I18N_EN_JS).with_header(ct("text/javascript; charset=utf-8")),
|
Response::from_string(I18N_EN_JS).with_header(ct("text/javascript; charset=utf-8")),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
(Method::Get, "/guara-logo.svg") => {
|
(Method::Get, "/guara-dark.png") => {
|
||||||
let _ = req.respond(Response::from_string(LOGO).with_header(ct("image/svg+xml")));
|
let _ = req.respond(Response::from_data(LOGO_DARK).with_header(ct("image/png")));
|
||||||
|
}
|
||||||
|
(Method::Get, "/guara-light.png") => {
|
||||||
|
let _ = req.respond(Response::from_data(LOGO_LIGHT).with_header(ct("image/png")));
|
||||||
|
}
|
||||||
|
(Method::Get, "/guara-dark-s.png") => {
|
||||||
|
let _ = req.respond(Response::from_data(LOGO_DARK_S).with_header(ct("image/png")));
|
||||||
|
}
|
||||||
|
(Method::Get, "/guara-light-s.png") => {
|
||||||
|
let _ = req.respond(Response::from_data(LOGO_LIGHT_S).with_header(ct("image/png")));
|
||||||
}
|
}
|
||||||
(Method::Get, "/explorer.js") => {
|
(Method::Get, "/explorer.js") => {
|
||||||
let _ = req.respond(
|
let _ = req.respond(
|
||||||
@@ -107,9 +118,6 @@ fn handle(req: Request, eng: &Engine, token: &str, hosts: &[String]) {
|
|||||||
.with_header(ct("text/javascript; charset=utf-8")),
|
.with_header(ct("text/javascript; charset=utf-8")),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
(Method::Get, "/guara.svg") => {
|
|
||||||
let _ = req.respond(Response::from_string(ICON).with_header(ct("image/svg+xml")));
|
|
||||||
}
|
|
||||||
(Method::Get, "/vendor/pdf.min.mjs") => {
|
(Method::Get, "/vendor/pdf.min.mjs") => {
|
||||||
let _ = req.respond(
|
let _ = req.respond(
|
||||||
Response::from_string(PDF_JS).with_header(ct("text/javascript; charset=utf-8")),
|
Response::from_string(PDF_JS).with_header(ct("text/javascript; charset=utf-8")),
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""Gera a logo do Guará: a cabeça do lobo-guará, de frente, recortada das
|
|
||||||
trilhas de um disco.
|
|
||||||
|
|
||||||
As trilhas são arcos concêntricos com centro abaixo do focinho. Na metade
|
|
||||||
direita estão inteiras (dados recuperados) e na esquerda quebradas em
|
|
||||||
fragmentos (dados perdidos). Focinho e olhos usam a cor do texto. As cores
|
|
||||||
são as do app (apps/gui/ui/app.css): --accent e --accent-2 no tema claro e
|
|
||||||
seus equivalentes no escuro, trocados por prefers-color-scheme.
|
|
||||||
|
|
||||||
Uso: python3 scripts/make-logo.py [pasta] (padrão: apps/gui/ui)
|
|
||||||
Grava guara-logo.svg e guara.svg (mesma arte; o segundo é o ícone).
|
|
||||||
O PNG para os ícones do app (src-tauri/icons/source.png) sai desta arte
|
|
||||||
renderizada em 1024x1024.
|
|
||||||
"""
|
|
||||||
import os, sys
|
|
||||||
|
|
||||||
HEAD = ("M50 95 C46 88 43 80 40 74 C33 70 25 64 22 56 L14 6 L36 30 "
|
|
||||||
"C40 28 45 27 50 27 C55 27 60 28 64 30 L86 6 L78 56 "
|
|
||||||
"C75 64 67 70 60 74 C57 80 54 88 50 95 Z")
|
|
||||||
STYLE = (".a{stroke:#0f766e}.b{stroke:#14b8a6}.t{fill:#1d1d1f}"
|
|
||||||
"@media (prefers-color-scheme:dark){.a{stroke:#2dd4bf}.b{stroke:#5eead4}.t{fill:#f5f5f7}}")
|
|
||||||
|
|
||||||
|
|
||||||
def tracks():
|
|
||||||
out = []
|
|
||||||
for i, r in enumerate(range(7, 104, 7)):
|
|
||||||
top, bot = 100 - r, 100 + r
|
|
||||||
out.append(f'<path class="a" d="M50 {top}A{r} {r} 0 0 1 50 {bot}"/>')
|
|
||||||
dash = f"{3 + i % 3 * 3} {3 + (i * 5) % 4}"
|
|
||||||
out.append(f'<path class="b" d="M50 {top}A{r} {r} 0 0 0 50 {bot}" '
|
|
||||||
f'stroke-dasharray="{dash}" stroke-dashoffset="{i * 3}"/>')
|
|
||||||
return "".join(out)
|
|
||||||
|
|
||||||
|
|
||||||
def svg():
|
|
||||||
return (
|
|
||||||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" role="img" aria-label="Guará">'
|
|
||||||
f'<style>{STYLE}</style>'
|
|
||||||
f'<defs><clipPath id="g-head"><path d="{HEAD}"/></clipPath></defs>'
|
|
||||||
f'<g clip-path="url(#g-head)" fill="none" stroke-width="4.2">{tracks()}'
|
|
||||||
# o focinho é a ponta da própria cabeça (recortada pelo mesmo contorno),
|
|
||||||
# então nenhuma trilha escapa pelas laterais
|
|
||||||
'<rect class="t" stroke="none" x="0" y="74" width="100" height="30"/></g>'
|
|
||||||
'<path class="t" d="M37 50Q42 47 46 52Q41 53 37 50ZM63 50Q58 47 54 52Q59 53 63 50Z"/>'
|
|
||||||
'</svg>\n'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
out = sys.argv[1] if len(sys.argv) > 1 else "apps/gui/ui"
|
|
||||||
for name in ("guara-logo.svg", "guara.svg"):
|
|
||||||
with open(os.path.join(out, name), "w") as f:
|
|
||||||
f.write(svg())
|
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Tira o fundo das logos do Guará e gera as variantes usadas no app, no README e nos ícones.
|
||||||
|
|
||||||
|
Entrada (arte original, fundo sólido): assets/logo/guara-dark-fonte.png e guara-light-fonte.png.
|
||||||
|
Saída: apps/gui/ui/guara-dark.png e guara-light.png (768 px, fundo transparente, recortadas e
|
||||||
|
quadradas), guara-dark-s.png e guara-light-s.png (128 px, para barra lateral e favicon) e
|
||||||
|
apps/gui/src-tauri/icons/source.png (ícone do app, sobre o fundo escuro da arte; o CI gera o
|
||||||
|
resto com `tauri icon`).
|
||||||
|
|
||||||
|
O fundo é uma cor sólida: sai o que é parecido com ela e está ligado à borda da imagem (sombras
|
||||||
|
escuras dentro do desenho ficam). Na faixa de 3 px ao redor, a cor do desenho é estimada pelos
|
||||||
|
vizinhos internos e a transparência vem de onde o pixel cai entre o fundo e essa cor, o que evita
|
||||||
|
halo escuro ou claro.
|
||||||
|
|
||||||
|
Uso: python3 scripts/processar-logo.py
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
RAIZ = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
|
||||||
|
UI = os.path.join(RAIZ, "apps/gui/ui")
|
||||||
|
ICONES = os.path.join(RAIZ, "apps/gui/src-tauri/icons")
|
||||||
|
# (arquivo de origem, cor do fundo, distância que ainda conta como fundo certo, não usado)
|
||||||
|
VARIANTES = {
|
||||||
|
"dark": ("assets/logo/guara-dark-fonte.png", (10, 16, 28), 9.0, None),
|
||||||
|
"light": ("assets/logo/guara-light-fonte.png", (254, 249, 240), 7.0, None),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def tirar_fundo(path, bg, d0, _d1=None):
|
||||||
|
"""Remove o fundo conectado à borda e refina a faixa de 3 px ao redor do desenho.
|
||||||
|
|
||||||
|
1. Fundo certo: pixels a menos de `d0` da cor do fundo, ligados à borda da imagem ou formando
|
||||||
|
um bolsão grande (as frestas entre as pernas). Sombras escuras do desenho, que passam de
|
||||||
|
`d0`, não são tocadas.
|
||||||
|
2. Faixa de 3 px ao redor do fundo (a borda suavizada da arte): a cor verdadeira do desenho é
|
||||||
|
estimada pelos vizinhos internos mais próximos, e a opacidade sai da projeção do pixel
|
||||||
|
entre a cor do fundo e essa cor. Sem halo escuro ou claro.
|
||||||
|
3. O resto fica como está, opaco.
|
||||||
|
"""
|
||||||
|
from collections import deque
|
||||||
|
|
||||||
|
im = Image.open(path).convert("RGB")
|
||||||
|
w, h = im.size
|
||||||
|
px = im.load()
|
||||||
|
br, bgc, bb = bg
|
||||||
|
d0sq = d0 * d0
|
||||||
|
|
||||||
|
def perto(x, y):
|
||||||
|
r, g, b = px[x, y]
|
||||||
|
return (r - br) ** 2 + (g - bgc) ** 2 + (b - bb) ** 2 < d0sq
|
||||||
|
|
||||||
|
# 1) fundo certo: flood fill a partir da borda
|
||||||
|
fundo = bytearray(w * h)
|
||||||
|
visto = bytearray(w * h)
|
||||||
|
fila = deque()
|
||||||
|
for x in range(w):
|
||||||
|
for y in (0, h - 1):
|
||||||
|
if perto(x, y) and not fundo[y * w + x]:
|
||||||
|
fundo[y * w + x] = 1
|
||||||
|
fila.append((x, y))
|
||||||
|
for y in range(h):
|
||||||
|
for x in (0, w - 1):
|
||||||
|
if perto(x, y) and not fundo[y * w + x]:
|
||||||
|
fundo[y * w + x] = 1
|
||||||
|
fila.append((x, y))
|
||||||
|
while fila:
|
||||||
|
x, y = fila.popleft()
|
||||||
|
for nx, ny in ((x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)):
|
||||||
|
if 0 <= nx < w and 0 <= ny < h and not fundo[ny * w + nx] and perto(nx, ny):
|
||||||
|
fundo[ny * w + nx] = 1
|
||||||
|
fila.append((nx, ny))
|
||||||
|
|
||||||
|
# 1b) bolsões de fundo dentro do desenho (frestas entre as pernas, por exemplo): regiões grandes
|
||||||
|
# com a cor do fundo que não tocam a borda. Manchas pequenas (brilho do olho) ficam.
|
||||||
|
for i0 in range(w * h):
|
||||||
|
if fundo[i0] or visto[i0]:
|
||||||
|
continue
|
||||||
|
x0, y0 = i0 % w, i0 // w
|
||||||
|
if not perto(x0, y0):
|
||||||
|
continue
|
||||||
|
comp = [(x0, y0)]
|
||||||
|
visto[i0] = 1
|
||||||
|
k = 0
|
||||||
|
while k < len(comp):
|
||||||
|
x, y = comp[k]
|
||||||
|
k += 1
|
||||||
|
for nx, ny in ((x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)):
|
||||||
|
if 0 <= nx < w and 0 <= ny < h and not visto[ny * w + nx] and not fundo[ny * w + nx] and perto(nx, ny):
|
||||||
|
visto[ny * w + nx] = 1
|
||||||
|
comp.append((nx, ny))
|
||||||
|
if len(comp) >= 60:
|
||||||
|
for x, y in comp:
|
||||||
|
fundo[y * w + x] = 1
|
||||||
|
|
||||||
|
# 2) distância (em passos de 8 vizinhos) até o fundo, só até 3
|
||||||
|
dist = bytearray([255]) * (w * h)
|
||||||
|
fila = deque()
|
||||||
|
for i in range(w * h):
|
||||||
|
if fundo[i]:
|
||||||
|
dist[i] = 0
|
||||||
|
fila.append((i % w, i // w))
|
||||||
|
while fila:
|
||||||
|
x, y = fila.popleft()
|
||||||
|
d = dist[y * w + x]
|
||||||
|
if d >= 3:
|
||||||
|
continue
|
||||||
|
for dx in (-1, 0, 1):
|
||||||
|
for dy in (-1, 0, 1):
|
||||||
|
nx, ny = x + dx, y + dy
|
||||||
|
if 0 <= nx < w and 0 <= ny < h and dist[ny * w + nx] == 255:
|
||||||
|
dist[ny * w + nx] = d + 1
|
||||||
|
fila.append((nx, ny))
|
||||||
|
|
||||||
|
out = Image.new("RGBA", (w, h))
|
||||||
|
po = out.load()
|
||||||
|
R = 6
|
||||||
|
for y in range(h):
|
||||||
|
for x in range(w):
|
||||||
|
d = dist[y * w + x]
|
||||||
|
if d == 0:
|
||||||
|
po[x, y] = (0, 0, 0, 0)
|
||||||
|
elif d == 255:
|
||||||
|
r, g, b = px[x, y]
|
||||||
|
po[x, y] = (r, g, b, 255)
|
||||||
|
else: # faixa da borda
|
||||||
|
soma = [0, 0, 0]
|
||||||
|
n = 0
|
||||||
|
melhor = 99
|
||||||
|
for yy in range(max(0, y - R), min(h, y + R + 1)):
|
||||||
|
for xx in range(max(0, x - R), min(w, x + R + 1)):
|
||||||
|
if dist[yy * w + xx] == 255:
|
||||||
|
q = (xx - x) ** 2 + (yy - y) ** 2
|
||||||
|
if q < melhor:
|
||||||
|
melhor, soma, n = q, list(px[xx, yy]), 1
|
||||||
|
elif q == melhor:
|
||||||
|
c = px[xx, yy]
|
||||||
|
soma = [soma[0] + c[0], soma[1] + c[1], soma[2] + c[2]]
|
||||||
|
n += 1
|
||||||
|
r, g, b = px[x, y]
|
||||||
|
if n == 0:
|
||||||
|
po[x, y] = (r, g, b, 255)
|
||||||
|
continue
|
||||||
|
f = (soma[0] / n, soma[1] / n, soma[2] / n)
|
||||||
|
vx, vy, vz = f[0] - br, f[1] - bgc, f[2] - bb
|
||||||
|
nn = vx * vx + vy * vy + vz * vz
|
||||||
|
a = ((r - br) * vx + (g - bgc) * vy + (b - bb) * vz) / nn if nn else 1.0
|
||||||
|
a = 0.0 if a < 0.02 else 1.0 if a > 0.98 else a
|
||||||
|
po[x, y] = (round(f[0]), round(f[1]), round(f[2]), round(a * 255))
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def recortar_quadrado(im, margem=0.04, lado=1024):
|
||||||
|
box = im.getchannel("A").point(lambda v: 255 if v > 8 else 0).getbbox()
|
||||||
|
im = im.crop(box)
|
||||||
|
w, h = im.size
|
||||||
|
s = round(max(w, h) * (1 + 2 * margem))
|
||||||
|
quadro = Image.new("RGBA", (s, s), (0, 0, 0, 0))
|
||||||
|
quadro.paste(im, ((s - w) // 2, (s - h) // 2), im)
|
||||||
|
return quadro.resize((lado, lado), Image.LANCZOS)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
feitas = {}
|
||||||
|
for nome, (src, bg, d0, _) in VARIANTES.items():
|
||||||
|
im = recortar_quadrado(tirar_fundo(os.path.join(RAIZ, src), bg, d0))
|
||||||
|
feitas[nome] = im
|
||||||
|
for sufixo, lado in (("", 768), ("-s", 128)):
|
||||||
|
im.resize((lado, lado), Image.LANCZOS).save(
|
||||||
|
os.path.join(UI, f"guara-{nome}{sufixo}.png"), optimize=True
|
||||||
|
)
|
||||||
|
print(f"guara-{nome}.png e guara-{nome}-s.png")
|
||||||
|
# ícone do app: a arte escura sobre o fundo escuro da própria arte, com cantos arredondados
|
||||||
|
lado = 1024
|
||||||
|
fundo = Image.new("RGBA", (lado, lado), VARIANTES["dark"][1] + (255,))
|
||||||
|
arte = feitas["dark"].resize((round(lado * 0.82),) * 2, Image.LANCZOS)
|
||||||
|
fundo.paste(arte, ((lado - arte.width) // 2, (lado - arte.height) // 2), arte)
|
||||||
|
mascara = Image.new("L", (lado, lado), 0)
|
||||||
|
from PIL import ImageDraw
|
||||||
|
ImageDraw.Draw(mascara).rounded_rectangle((0, 0, lado - 1, lado - 1), radius=round(lado * 0.2237), fill=255)
|
||||||
|
icone = Image.new("RGBA", (lado, lado), (0, 0, 0, 0))
|
||||||
|
icone.paste(fundo, (0, 0), mascara)
|
||||||
|
icone.save(os.path.join(ICONES, "source.png"), optimize=True)
|
||||||
|
print("icons/source.png", icone.size)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||