Textové styly: zachovat jména ze zdroje a opravit MTEXT
Š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>
This commit is contained in:
@@ -0,0 +1,102 @@
|
|||||||
|
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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -166,8 +166,12 @@ public sealed partial class DxfTemplate
|
|||||||
case MText mt:
|
case MText mt:
|
||||||
{
|
{
|
||||||
var (h, v) = MapMTextAlign(mt.AttachmentPoint);
|
var (h, v) = MapMTextAlign(mt.AttachmentPoint);
|
||||||
g.Text(mt.InsertPoint.X, mt.InsertPoint.Y, mt.PlainText, mt.Height, h, v, mt.Rotation * RadToDeg,
|
// MTEXT nemá šířkový faktor jako vlastnost entity – nese ho buď kód \W
|
||||||
StyleOf(mt.Style), 1, mt.RectangleWidth);
|
// na začátku hodnoty, nebo (jinak) styl textu.
|
||||||
|
var (text, wfKod) = MTextSirka(mt.Value, mt.PlainText);
|
||||||
|
double wf = wfKod ?? (mt.Style?.Width > 0 ? mt.Style.Width : 1);
|
||||||
|
g.Text(mt.InsertPoint.X, mt.InsertPoint.Y, text, mt.Height, h, v, mt.Rotation * RadToDeg,
|
||||||
|
StyleOf(mt.Style), wf, mt.RectangleWidth);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,6 +223,25 @@ public sealed partial class DxfTemplate
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Odloupne z MTEXTu úvodní kód šířkového faktoru <c>\W1.2;</c>. ACadSharp ho
|
||||||
|
/// v <c>PlainText</c> nechává (jen bez zpětného lomítka), takže by se jinak vykreslil jako
|
||||||
|
/// text. Vrací čistý text a faktor, když tam byl.</summary>
|
||||||
|
internal static (string Text, double? WidthFactor) MTextSirka(string? hodnota, string? plainText)
|
||||||
|
{
|
||||||
|
string plain = plainText ?? "";
|
||||||
|
if (hodnota is null || !hodnota.StartsWith(@"\W", StringComparison.Ordinal)) return (plain, null);
|
||||||
|
int strednik = hodnota.IndexOf(';', 2);
|
||||||
|
if (strednik < 0) return (plain, null);
|
||||||
|
if (!double.TryParse(hodnota[2..strednik], System.Globalization.NumberStyles.Float,
|
||||||
|
System.Globalization.CultureInfo.InvariantCulture, out double wf) || wf <= 0)
|
||||||
|
return (plain, null);
|
||||||
|
|
||||||
|
// Z PlainText ubyla jen zpětná lomítka, tedy „W1.2;" bez prvního znaku kódu.
|
||||||
|
string predpona = hodnota[1..(strednik + 1)];
|
||||||
|
if (plain.StartsWith(predpona, StringComparison.Ordinal)) plain = plain[predpona.Length..];
|
||||||
|
return (plain, wf);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Popis hladiny pro kreslítko – celý, ať se dá ve výstupu postavit znovu
|
/// <summary>Popis hladiny pro kreslítko – celý, ať se dá ve výstupu postavit znovu
|
||||||
/// (barva z tabulky hladin, tloušťka, typ čáry, příznak tisku).</summary>
|
/// (barva z tabulky hladin, tloušťka, typ čáry, příznak tisku).</summary>
|
||||||
private static HladinaStav HladinaZ(ACadSharp.Tables.Layer? layer)
|
private static HladinaStav HladinaZ(ACadSharp.Tables.Layer? layer)
|
||||||
@@ -275,13 +298,14 @@ public sealed partial class DxfTemplate
|
|||||||
{
|
{
|
||||||
double obliqueRad = entityObliqueRad != 0 ? entityObliqueRad : s?.ObliqueAngle ?? 0;
|
double obliqueRad = entityObliqueRad != 0 ? entityObliqueRad : s?.ObliqueAngle ?? 0;
|
||||||
if (s is null) return new(ObliqueDeg: obliqueRad * RadToDeg);
|
if (s is null) return new(ObliqueDeg: obliqueRad * RadToDeg);
|
||||||
string? file = s.IsShapeFile || string.IsNullOrWhiteSpace(s.Filename) ? null : s.Filename;
|
string? file = string.IsNullOrWhiteSpace(s.Filename) ? null : s.Filename;
|
||||||
|
string? ttf = s.IsShapeFile ? null : file;
|
||||||
bool bold = s.TrueType.HasFlag(FontFlags.Bold);
|
bool bold = s.TrueType.HasFlag(FontFlags.Bold);
|
||||||
bool italic = s.TrueType.HasFlag(FontFlags.Italic);
|
bool italic = s.TrueType.HasFlag(FontFlags.Italic);
|
||||||
// Rodina písma: z .ttf souboru; když styl soubor nemá (TTF zadané jen jménem), vezmi
|
// Rodina písma: z .ttf souboru; když styl soubor nemá (TTF zadané jen jménem), vezmi
|
||||||
// název typu písma z XData(ACAD) – tam AutoCAD ukládá rodinu (např. „Arial Black").
|
// název typu písma z XData(ACAD) – tam AutoCAD ukládá rodinu (např. „Arial Black").
|
||||||
string? family = file is not null ? Path.GetFileNameWithoutExtension(file) : FontRodinaZeXData(s);
|
string? family = ttf is not null ? Path.GetFileNameWithoutExtension(ttf) : FontRodinaZeXData(s);
|
||||||
return new(family, bold, italic, file, obliqueRad * RadToDeg);
|
return new(family, bold, italic, file, obliqueRad * RadToDeg, s.Name, s.IsShapeFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Název rodiny TrueType písma uložený ve stylu jako XData appid „ACAD" (první ASCII
|
/// <summary>Název rodiny TrueType písma uložený ve stylu jako XData appid „ACAD" (první ASCII
|
||||||
|
|||||||
@@ -124,9 +124,11 @@ public sealed class DxfProfileRenderer : IProfileRenderer
|
|||||||
{
|
{
|
||||||
var mtext = new MText
|
var mtext = new MText
|
||||||
{
|
{
|
||||||
Value = text.Replace("\r\n", "\\P").Replace("\n", "\\P"),
|
Value = MTextHodnota(text, widthFactor),
|
||||||
InsertPoint = new XYZ(x, y, 0),
|
InsertPoint = new XYZ(x, y, 0),
|
||||||
Height = heightMm,
|
Height = heightMm,
|
||||||
|
// MTEXT nemá zapisovatelné natočení – nese ho směrový vektor osy X (group 11).
|
||||||
|
AlignmentPoint = SmerOsyX(rotationDeg),
|
||||||
RectangleWidth = maxWidthMm,
|
RectangleWidth = maxWidthMm,
|
||||||
AttachmentPoint = MapAttach(h, v),
|
AttachmentPoint = MapAttach(h, v),
|
||||||
};
|
};
|
||||||
@@ -185,6 +187,40 @@ public sealed class DxfProfileRenderer : IProfileRenderer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Směrový vektor osy X textu pro dané natočení – tím se natáčí MTEXT.</summary>
|
||||||
|
private static XYZ SmerOsyX(double rotationDeg)
|
||||||
|
{
|
||||||
|
double rad = rotationDeg * Math.PI / 180.0;
|
||||||
|
return new XYZ(Math.Cos(rad), Math.Sin(rad), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Text pro MTEXT. Escapuje znaky, které jsou v MTEXTu řídicí (zpětné lomítko a
|
||||||
|
/// složené závorky) – bez toho by uživatelova hodnota se zpětným lomítkem rozbila formátování –,
|
||||||
|
/// zlomy řádků převede na <c>\P</c> a šířkový faktor doplní kódem <c>\W</c>: MTEXT ho na rozdíl
|
||||||
|
/// od TEXTu nemá jako vlastnost entity, takže jinak by se ztratil.</summary>
|
||||||
|
private static string MTextHodnota(string text, double widthFactor)
|
||||||
|
{
|
||||||
|
var sb = new System.Text.StringBuilder();
|
||||||
|
if (widthFactor > 0 && Math.Abs(widthFactor - 1) > 1e-9)
|
||||||
|
sb.Append(@"\W")
|
||||||
|
.Append(widthFactor.ToString("0.####", System.Globalization.CultureInfo.InvariantCulture))
|
||||||
|
.Append(';');
|
||||||
|
|
||||||
|
foreach (var znak in text)
|
||||||
|
{
|
||||||
|
switch (znak)
|
||||||
|
{
|
||||||
|
case '\\': sb.Append(@"\\"); break;
|
||||||
|
case '{': sb.Append(@"\{"); break;
|
||||||
|
case '}': sb.Append(@"\}"); break;
|
||||||
|
case '\n': sb.Append(@"\P"); break;
|
||||||
|
case '\r': break;
|
||||||
|
default: sb.Append(znak); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Převede analytickou hranu obrysu na DXF hraniční edge šrafy (úsečka / kruhový oblouk).
|
/// <summary>Převede analytickou hranu obrysu na DXF hraniční edge šrafy (úsečka / kruhový oblouk).
|
||||||
/// U oblouku: záporný rozsah (CW) se v DXF vyjádří <c>CounterClockWise=false</c>, kde čtečka úhly
|
/// U oblouku: záporný rozsah (CW) se v DXF vyjádří <c>CounterClockWise=false</c>, kde čtečka úhly
|
||||||
/// zrcadlí přes osu X – proto pro CW meze <c>−A0</c> / <c>−(A0+Sweep)</c>, znormalizované do [0,2π).</summary>
|
/// zrcadlí přes osu X – proto pro CW meze <c>−A0</c> / <c>−(A0+Sweep)</c>, znormalizované do [0,2π).</summary>
|
||||||
@@ -227,20 +263,41 @@ public sealed class DxfProfileRenderer : IProfileRenderer
|
|||||||
/// stylu (použije se výchozí styl dokumentu).</summary>
|
/// stylu (použije se výchozí styl dokumentu).</summary>
|
||||||
private AcTextStyle? StylProEntitu(TextStyle s)
|
private AcTextStyle? StylProEntitu(TextStyle s)
|
||||||
{
|
{
|
||||||
// Soubor fontu: přednostně .ttf z předlohy, jinak odvozeno z rodiny písma.
|
// Soubor fontu: přednostně ten z předlohy (.ttf i .shx), jinak odvozeno z rodiny písma.
|
||||||
string? file = s.FontFile ?? (string.IsNullOrWhiteSpace(s.FontFamily) ? null : s.FontFamily + ".ttf");
|
string? file = s.FontFile ?? (string.IsNullOrWhiteSpace(s.FontFamily) ? null : s.FontFamily + ".ttf");
|
||||||
if (file is null && string.IsNullOrWhiteSpace(s.FontFamily)) return null;
|
if (file is null && string.IsNullOrWhiteSpace(s.FontFamily) && string.IsNullOrWhiteSpace(s.Nazev))
|
||||||
|
return null;
|
||||||
|
|
||||||
string klic = $"{file}|{s.FontFamily}|{(s.Bold ? "B" : "")}{(s.Italic ? "I" : "")}|{s.ObliqueDeg}";
|
// Klíčem je jméno stylu ze zdroje, pokud ho zná – jeden zdrojový styl = jeden styl ve
|
||||||
|
// výstupu. Bez toho vznikal styl pro každou kombinaci fontu a sklonu a jména se
|
||||||
|
// vymýšlela (Verdana_1, Arial_2), takže se ve správci stylů nedalo nic najít.
|
||||||
|
string klic = string.IsNullOrWhiteSpace(s.Nazev)
|
||||||
|
? $"\0odvozeny|{file}|{s.FontFamily}|{(s.Bold ? "B" : "")}{(s.Italic ? "I" : "")}|{s.ObliqueDeg}"
|
||||||
|
: s.Nazev!;
|
||||||
if (_styly.TryGetValue(klic, out var styl)) return styl;
|
if (_styly.TryGetValue(klic, out var styl)) return styl;
|
||||||
|
|
||||||
var ff = FontFlags.Regular;
|
var ff = FontFlags.Regular;
|
||||||
if (s.Bold) ff |= FontFlags.Bold;
|
if (s.Bold) ff |= FontFlags.Bold;
|
||||||
if (s.Italic) ff |= FontFlags.Italic;
|
if (s.Italic) ff |= FontFlags.Italic;
|
||||||
|
|
||||||
string nazev = UnikatniNazevStylu(s.FontFamily ?? Path.GetFileNameWithoutExtension(file) ?? "Styl", s.Bold, s.Italic);
|
string nazev = string.IsNullOrWhiteSpace(s.Nazev)
|
||||||
|
? UnikatniNazevStylu(s.FontFamily ?? Path.GetFileNameWithoutExtension(file) ?? "Styl", s.Bold, s.Italic)
|
||||||
|
: s.Nazev!;
|
||||||
|
|
||||||
|
if (_doc.TextStyles.TryGetValue(nazev, out var existujici))
|
||||||
|
{
|
||||||
|
_styly[klic] = existujici;
|
||||||
|
return existujici;
|
||||||
|
}
|
||||||
|
|
||||||
// Oblique i na stylu – TEXT ho nese sám (group 51), ale MTEXT sklon přebírá jen ze stylu.
|
// Oblique i na stylu – TEXT ho nese sám (group 51), ale MTEXT sklon přebírá jen ze stylu.
|
||||||
styl = new AcTextStyle(nazev) { Filename = file ?? "", TrueType = ff, ObliqueAngle = s.ObliqueDeg * Math.PI / 180.0 };
|
styl = new AcTextStyle(nazev)
|
||||||
|
{
|
||||||
|
Filename = file ?? "",
|
||||||
|
TrueType = ff,
|
||||||
|
ObliqueAngle = s.ObliqueDeg * Math.PI / 180.0,
|
||||||
|
Flags = s.JeShx ? ACadSharp.Tables.StyleFlags.IsShape : ACadSharp.Tables.StyleFlags.None,
|
||||||
|
};
|
||||||
_doc.TextStyles.Add(styl);
|
_doc.TextStyles.Add(styl);
|
||||||
_styly[klic] = styl;
|
_styly[klic] = styl;
|
||||||
return styl;
|
return styl;
|
||||||
|
|||||||
@@ -8,12 +8,18 @@ public enum VAlign { Baseline, Bottom, Middle, Top }
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Vzhled písma přenesený z DXF textového stylu (ROZPISKY.md §3): rodina fontu + řez,
|
/// Vzhled písma přenesený z DXF textového stylu (ROZPISKY.md §3): rodina fontu + řez,
|
||||||
/// volitelně přímo soubor fontu (.ttf) pro věrný řez. <c>default</c> = fallback font rendereru.
|
/// volitelně přímo soubor fontu pro věrný řez. <c>default</c> = fallback font rendereru.
|
||||||
/// <paramref name="ObliqueDeg"/> = sklon znaků ve stupních (DXF oblique angle, group 51 entity /
|
/// <paramref name="ObliqueDeg"/> = sklon znaků ve stupních (DXF oblique angle, group 51 entity /
|
||||||
/// group 50 stylu); kladný = naklonění doprava, 0 = vzpřímeně.
|
/// group 50 stylu); kladný = naklonění doprava, 0 = vzpřímeně.
|
||||||
|
/// <para><paramref name="Nazev"/> = jméno stylu ve zdrojovém výkresu („Popis základní",
|
||||||
|
/// „Název stavby"). Nese se dál, aby ho DXF export zapsal beze změny – dřív se zahazovalo
|
||||||
|
/// a v exportu vznikala náhradní jména typu <c>Verdana_1</c>. <paramref name="JeShx"/> = styl
|
||||||
|
/// odkazuje na vektorový font AutoCADu (.shx); ten se nedá načíst jako TrueType, takže se
|
||||||
|
/// kreslí náhradním fontem, ale do DXF se zapíše původní.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly record struct TextStyle(string? FontFamily = null, bool Bold = false, bool Italic = false,
|
public readonly record struct TextStyle(string? FontFamily = null, bool Bold = false, bool Italic = false,
|
||||||
string? FontFile = null, double ObliqueDeg = 0);
|
string? FontFile = null, double ObliqueDeg = 0,
|
||||||
|
string? Nazev = null, bool JeShx = false);
|
||||||
|
|
||||||
/// <summary>Druh hrany obrysu: úsečka nebo kruhový oblouk. Elipsy a spliny se do obrysu vkládají
|
/// <summary>Druh hrany obrysu: úsečka nebo kruhový oblouk. Elipsy a spliny se do obrysu vkládají
|
||||||
/// jako jemná řada úseček (viz <see cref="Edge"/>), takže renderery vystačí se dvěma případy.</summary>
|
/// jako jemná řada úseček (viz <see cref="Edge"/>), takže renderery vystačí se dvěma případy.</summary>
|
||||||
|
|||||||
@@ -66,7 +66,8 @@ public sealed class SkiaProfileRenderer : IProfileRenderer, IDisposable
|
|||||||
private SKTypeface Typeface(TextStyle style)
|
private SKTypeface Typeface(TextStyle style)
|
||||||
{
|
{
|
||||||
// 1) Přesný font ze souboru, na který odkazuje DXF styl (.ttf v systémové složce Fonts).
|
// 1) Přesný font ze souboru, na který odkazuje DXF styl (.ttf v systémové složce Fonts).
|
||||||
if (!string.IsNullOrWhiteSpace(style.FontFile))
|
// SHX (vektorový font AutoCADu) se takhle načíst nedá – jde rovnou na náhradu.
|
||||||
|
if (!style.JeShx && !string.IsNullOrWhiteSpace(style.FontFile))
|
||||||
{
|
{
|
||||||
var fileKey = ("\0file:" + style.FontFile, 0, false);
|
var fileKey = ("\0file:" + style.FontFile, 0, false);
|
||||||
if (_typefaces.TryGetValue(fileKey, out var tff)) return tff;
|
if (_typefaces.TryGetValue(fileKey, out var tff)) return tff;
|
||||||
|
|||||||
Reference in New Issue
Block a user