Šablona má styly pojmenované česky („Popis základní", „Název stavby"), export je zahazoval a vyráběl náhradní jména podle fontu (Verdana, Verdana_B, Arial_1) – pro každou kombinaci fontu a sklonu nový záznam. Ve správci stylů v CADu pak nešlo nic najít ani hromadně změnit. Jméno stylu se teď nese v `TextStyle.Nazev` až do zápisu; jeden zdrojový styl = jeden styl ve výstupu. Dál: - SHX styly (vektorové fonty AutoCADu) se přenášejí i s odkazem na soubor a příznakem `IsShape`. Kreslí se pořád náhradním fontem – SHX se jako TrueType načíst nedá –, ale v exportu zůstane původní styl, ne Standard. - MTEXT si drží natočení. Nešlo přiřadit `Rotation` (v ACadSharp je jen ke čtení), takže se nastavuje směrovým vektorem osy X; natočený víceřádkový atribut dřív vycházel vodorovně. - MTEXT si drží šířkový faktor přes kód \W. Jako vlastnost entity ho nemá. Čtečka ho zase odloupne – ACadSharp ho v PlainText nechává, takže bez toho by se „W0.8;" vykreslilo jako text. - Hodnota MTEXTu se escapuje celá (zpětné lomítko, složené závorky), ne jen zlomy řádků. Cesta typu C:\projekt v poli dřív rozbila formátování. 99 testů zelených. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
103 lines
3.8 KiB
C#
103 lines
3.8 KiB
C#
using System.IO;
|
|
using ACadSharp.Entities;
|
|
using ACadSharp.IO;
|
|
using Rozpisky.Dxf;
|
|
using Rozpisky.Rendering;
|
|
using Xunit;
|
|
|
|
namespace Rozpisky.Tests;
|
|
|
|
/// <summary>
|
|
/// Textové styly a MTEXT tam a zpět. Šablona má styly pojmenované česky („Popis základní",
|
|
/// „Název stavby"); export je dřív zahodil a vyrobil náhradní jména podle fontu (Verdana_1),
|
|
/// takže ve správci stylů v CADu nešlo nic najít ani hromadně změnit.
|
|
/// </summary>
|
|
public class TextStylyRoundTripTesty : IDisposable
|
|
{
|
|
private readonly string _soubor = Path.Combine(Path.GetTempPath(), "rozpisky-styly-" + Guid.NewGuid().ToString("N") + ".dxf");
|
|
|
|
public void Dispose()
|
|
{
|
|
try { File.Delete(_soubor); } catch (IOException) { }
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
private ACadSharp.CadDocument Kolecko(Action<IProfileRenderer> kresba)
|
|
{
|
|
var dxf = new DxfProfileRenderer();
|
|
kresba(dxf);
|
|
DxfWriter.Write(_soubor, dxf.Document, binary: true);
|
|
return DxfReader.Read(_soubor);
|
|
}
|
|
|
|
[Fact]
|
|
public void StylySiDrziJmenaZeZdroje()
|
|
{
|
|
var doc = Kolecko(g => new DxfTemplate(TestData.Sablona).Replay(g));
|
|
var jmena = doc.TextStyles.Select(s => s.Name).ToList();
|
|
|
|
Assert.Contains("Popis základní", jmena);
|
|
Assert.Contains("Název stavby", jmena);
|
|
// Náhradní jména podle fontu nesmí vzniknout, když zdroj styl pojmenovaný má.
|
|
Assert.DoesNotContain(jmena, j => j.StartsWith("Verdana", StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
|
|
[Fact]
|
|
public void JedenZdrojovyStylDaJedenStylVeVystupu()
|
|
{
|
|
// Dřív vznikal nový styl pro každou kombinaci fontu a sklonu, takže jich ve výstupu
|
|
// bylo víc než ve zdroji a texty se rozpadly mezi ně.
|
|
var zdroj = DxfReader.Read(TestData.Sablona);
|
|
var doc = Kolecko(g => new DxfTemplate(TestData.Sablona).Replay(g));
|
|
|
|
var pouzite = doc.Entities.OfType<TextEntity>().Select(t => t.Style?.Name)
|
|
.Concat(doc.Entities.OfType<MText>().Select(m => m.Style?.Name))
|
|
.Where(n => n is not null).Distinct().ToList();
|
|
|
|
Assert.NotEmpty(pouzite);
|
|
foreach (var n in pouzite)
|
|
Assert.True(zdroj.TextStyles.Contains(n!), $"styl {n} ve zdroji není");
|
|
}
|
|
|
|
[Fact]
|
|
public void MtextSiDrziNatoceni()
|
|
{
|
|
var doc = Kolecko(g => g.Text(0, 0, "dva\nřádky", 3, maxWidthMm: 40, rotationDeg: 30));
|
|
var mt = Assert.Single(doc.Entities.OfType<MText>());
|
|
Assert.Equal(30, mt.Rotation * 180 / Math.PI, 3);
|
|
}
|
|
|
|
[Fact]
|
|
public void MtextSiDrziSirkovyFaktor()
|
|
{
|
|
var doc = Kolecko(g => g.Text(0, 0, "text", 3, maxWidthMm: 40, widthFactor: 0.8));
|
|
var mt = Assert.Single(doc.Entities.OfType<MText>());
|
|
Assert.StartsWith(@"\W0.8;", mt.Value);
|
|
|
|
// A vlastní čtečka ho musí zase odloupnout, jinak by se „W0.8;" vykreslilo jako text.
|
|
var (cisty, wf) = DxfTemplate.MTextSirka(mt.Value, mt.PlainText);
|
|
Assert.Equal("text", cisty);
|
|
Assert.Equal(0.8, wf!.Value, 3);
|
|
}
|
|
|
|
[Fact]
|
|
public void ZpetneLomitkoAZavorkyNerozbijiMtext()
|
|
{
|
|
// Reálná hodnota z pole: cesta nebo poznámka se zpětným lomítkem. Bez escapování
|
|
// by ji CAD přečetl jako formátovací kód a část textu by zmizela.
|
|
const string hodnota = @"C:\projekt {2025} \P";
|
|
var doc = Kolecko(g => g.Text(0, 0, hodnota, 3, maxWidthMm: 60));
|
|
var mt = Assert.Single(doc.Entities.OfType<MText>());
|
|
Assert.Equal(hodnota, mt.PlainText);
|
|
}
|
|
|
|
[Fact]
|
|
public void ZlomRadkuSePreloziNaMtextovyKod()
|
|
{
|
|
var doc = Kolecko(g => g.Text(0, 0, "první\ndruhý", 3, maxWidthMm: 60));
|
|
var mt = Assert.Single(doc.Entities.OfType<MText>());
|
|
Assert.Contains(@"\P", mt.Value);
|
|
Assert.Equal("první\ndruhý", mt.PlainText.Replace("\r\n", "\n"));
|
|
}
|
|
}
|