diff --git a/NFe.Danfe.PdfClown/Blocos/TabelaProdutoServicos.cs b/NFe.Danfe.PdfClown/Blocos/TabelaProdutoServicos.cs
index 1e27d2660..67557c0d7 100644
--- a/NFe.Danfe.PdfClown/Blocos/TabelaProdutoServicos.cs
+++ b/NFe.Danfe.PdfClown/Blocos/TabelaProdutoServicos.cs
@@ -34,14 +34,14 @@ public TabelaProdutosServicos(DanfeViewModel viewModel, Estilo estilo) : base(es
.ComColuna(3.9F, ac, cabecalho4)
.ComColuna(3.5F, ac, "CFOP")
.ComColuna(3.25F, ac, "UN")
- .ComColuna(6F, ad, "QUANTI.")
- .ComColuna(6F, ad, "VALOR", "UNIT.")
- .ComColuna(6F, ad, "VALOR", "TOTAL")
- .ComColuna(6F, ad, "B CÁLC", "ICMS")
- .ComColuna(5, ad, "VALOR", "ICMS")
- .ComColuna(5, ad, "VALOR", "IPI")
- .ComColuna(3.5F, ad, "ALIQ.", "ICMS")
- .ComColuna(3.5F, ad, "ALIQ.", "IPI");
+ .ComColunaDeValor(6F, ad, "QUANTI.")
+ .ComColunaDeValor(6F, ad, "VALOR", "UNIT.")
+ .ComColunaDeValor(6F, ad, "VALOR", "TOTAL")
+ .ComColunaDeValor(6F, ad, "B CÁLC", "ICMS")
+ .ComColunaDeValor(5, ad, "VALOR", "ICMS")
+ .ComColunaDeValor(5, ad, "VALOR", "IPI")
+ .ComColunaDeValor(3.5F, ad, "ALIQ.", "ICMS")
+ .ComColunaDeValor(3.5F, ad, "ALIQ.", "IPI");
}
if (ViewModel.Orientacao == Orientacao.Paisagem)
{
@@ -52,14 +52,14 @@ public TabelaProdutosServicos(DanfeViewModel viewModel, Estilo estilo) : base(es
.ComColuna(3.1F, ac, cabecalho4)
.ComColuna(3.1F, ac, "CFOP")
.ComColuna(3F, ac, "UN")
- .ComColuna(5.25F, ad, "QUANTI.")
- .ComColuna(5.6F, ad, "VALOR UNIT.")
- .ComColuna(5.6F, ad, "VALOR TOTAL")
- .ComColuna(5.6F, ad, "B CÁLC ICMS")
- .ComColuna(5.6F, ad, "VALOR ICMS")
- .ComColuna(5.6F, ad, "VALOR IPI")
- .ComColuna(3F, ad, "ALIQ.", "ICMS")
- .ComColuna(3F, ad, "ALIQ.", "IPI");
+ .ComColunaDeValor(5.25F, ad, "QUANTI.")
+ .ComColunaDeValor(5.6F, ad, "VALOR UNIT.")
+ .ComColunaDeValor(5.6F, ad, "VALOR TOTAL")
+ .ComColunaDeValor(5.6F, ad, "B CÁLC ICMS")
+ .ComColunaDeValor(5.6F, ad, "VALOR ICMS")
+ .ComColunaDeValor(5.6F, ad, "VALOR IPI")
+ .ComColunaDeValor(3F, ad, "ALIQ.", "ICMS")
+ .ComColunaDeValor(3F, ad, "ALIQ.", "IPI");
}
Tabela.AjustarLarguraColunas();
diff --git a/NFe.Danfe.PdfClown/Elementos/Tabela.cs b/NFe.Danfe.PdfClown/Elementos/Tabela.cs
index 0b8d6128d..f847c3aae 100644
--- a/NFe.Danfe.PdfClown/Elementos/Tabela.cs
+++ b/NFe.Danfe.PdfClown/Elementos/Tabela.cs
@@ -41,12 +41,29 @@ public Tabela(Estilo estilo) : base(estilo)
FonteCabecalho = estilo.CriarFonteRegular(6F);
}
+ ///
+ /// Menor corpo de fonte aceito pelo ajuste automático das colunas de valor. Abaixo dele
+ /// o número deixaria de ser legível no impresso, e o comportamento anterior (quebra de
+ /// linha) é preservado.
+ ///
+ private const float TamanhoMinimoDaCelulaAjustada = 4F;
+
public Tabela ComColuna(float larguraP, AlinhamentoHorizontal ah, params string[] cabecalho)
{
Colunas.Add(new TabelaColuna(cabecalho, larguraP, ah));
return this;
}
+ ///
+ /// Acrescenta uma coluna de valor: o conteúdo é indivisível e, se não couber na célula,
+ /// encolhe para caber em uma única linha. Ver .
+ ///
+ public Tabela ComColunaDeValor(float larguraP, AlinhamentoHorizontal ah, params string[] cabecalho)
+ {
+ Colunas.Add(new TabelaColuna(cabecalho, larguraP, ah, ajustarFonteParaCaber: true));
+ return this;
+ }
+
public void AdicionarLinha(List linha)
{
if (linha.Count != Colunas.Count) throw new ArgumentException(nameof(linha));
@@ -66,6 +83,37 @@ public void AjustarLarguraColunas()
}
+ ///
+ /// Fonte de uma célula. Por padrão, a fonte do corpo da tabela. Numa coluna de valor
+ /// () cujo conteúdo é indivisível — sem
+ /// espaços — e mais largo que a célula, o corpo da fonte é reduzido o suficiente para o
+ /// conteúdo caber em uma única linha, respeitando
+ /// .
+ ///
+ /// Coluna da célula.
+ /// Conteúdo da célula.
+ /// Largura disponível da célula, em milímetros.
+ private Fonte FonteDaCelula(TabelaColuna coluna, string valor, float larguraUtil)
+ {
+ if (!coluna.AjustarFonteParaCaber || larguraUtil <= 0) return FonteCorpo;
+
+ foreach (var caractere in valor)
+ {
+ if (char.IsWhiteSpace(caractere)) return FonteCorpo;
+ }
+
+ float largura = FonteCorpo.MedirLarguraTexto(valor);
+
+ if (largura <= larguraUtil || largura <= 0) return FonteCorpo;
+
+ // A folga de 0.5% evita que o arredondamento da medição encoste o valor na borda.
+ float tamanho = FonteCorpo.Tamanho * (larguraUtil / largura) * 0.995F;
+
+ return tamanho < TamanhoMinimoDaCelulaAjustada
+ ? FonteCorpo
+ : new Fonte(FonteCorpo.FonteInterna, tamanho);
+ }
+
private Boolean DesenharLinha(Gfx gfx)
{
float x = X;
@@ -82,10 +130,11 @@ private Boolean DesenharLinha(Gfx gfx)
if (!string.IsNullOrWhiteSpace(v))
{
+ float larguraUtil = w - 2F * Estilo.PaddingHorizontal;
- tb[i] = new TextBlock(v, FonteCorpo)
+ tb[i] = new TextBlock(v, FonteDaCelula(c, v, larguraUtil))
{
- Width = w - 2F * Estilo.PaddingHorizontal,
+ Width = larguraUtil,
X = x + PaddingHorizontal,
Y = _DY + PaddingSuperior,
AlinhamentoHorizontal = c.AlinhamentoHorizontal
diff --git a/NFe.Danfe.PdfClown/Elementos/TabelaColuna.cs b/NFe.Danfe.PdfClown/Elementos/TabelaColuna.cs
index cf1f82c81..9a1c5c981 100644
--- a/NFe.Danfe.PdfClown/Elementos/TabelaColuna.cs
+++ b/NFe.Danfe.PdfClown/Elementos/TabelaColuna.cs
@@ -8,11 +8,19 @@ internal class TabelaColuna
public float PorcentagemLargura { get; set; }
public AlinhamentoHorizontal AlinhamentoHorizontal { get; private set; }
- public TabelaColuna(string[] cabecalho, float porcentagemLargura, AlinhamentoHorizontal alinhamentoHorizontal = AlinhamentoHorizontal.Esquerda)
+ ///
+ /// Indica que o conteúdo desta coluna é indivisível — um valor formatado, sem espaços.
+ /// Quando true, um conteúdo mais largo que a célula é impresso em fonte reduzida
+ /// em vez de ser quebrado no meio dos caracteres.
+ ///
+ public bool AjustarFonteParaCaber { get; private set; }
+
+ public TabelaColuna(string[] cabecalho, float porcentagemLargura, AlinhamentoHorizontal alinhamentoHorizontal = AlinhamentoHorizontal.Esquerda, bool ajustarFonteParaCaber = false)
{
Cabecalho = cabecalho ?? throw new ArgumentNullException(nameof(cabecalho));
PorcentagemLargura = porcentagemLargura;
AlinhamentoHorizontal = alinhamentoHorizontal;
+ AjustarFonteParaCaber = ajustarFonteParaCaber;
}
public override string ToString()