Fonte Comum no Linux e Windows

67 respostas
J

Gostaria de uma fonte que tivesse em todas as versões do windows como tb no Linux ??
Tava utilizando Courier no Linux, no entanto, ao passar pro windows tava dando problemas no tamanho !!!

valeu !!

67 Respostas

M

Você precisa usar as fontes “simbólicas” do sistema, usar cálculos complexos com FontMetrics ou utilizar fontes que você possa distribuir com a sua aplicação.

J

Cara vc poderia ser um pouco mais específico ??

valeu pela ajuda !

M

Na verdade, você precisa ser mais específico :slight_smile:

Qual desses 3 caminhos você quer seguir:

  1. Simplesmente usar fontes que existam em qualquer SO (que não são nem 6 dúzia e não tem exatamente o mesmo formato/aparência/tamanho em todos eles);
  2. Não ter problemas de “estouro” de layour, mas “sofrer” fazendo diversos cálculos complexos;
  3. Ter exatamente a mesma fonte em todos os SOs, sendo que fontes conhecidas, como Times New Roman, por exemplo, você não vai poder usar.
J

Cara vou dá uma explicada melhor no meu problema. Estou desenvolvendo relatórios, utilzando o jasperreport, no Linux. O tamanho da fonte que eu estou utilizando é 10 e o campo onde essa fonte estar tem também tamanho 10.No linux , essa configuração dá beleza. Agora, quando eu executo a minha aplicação no windows o campo não aparece nada. É como se no windows a fonte aumentasse de tamanho e passasse do tamanho reservado a ela, que no caso eh 10. Estou utlizando a Courier.

valeu pela ajuda !!

M

Se eu entendi, você quer usar a opção 3 das alternativas que eu propus, correto?

J

Exato !!

M

Bem, não querendo te desanimar, você só tem então três opções:

  1. Garantir a instalação das fontes junto com a instalação da aplicação. Sim, fontes de mesmo nome têm tamanhos diferentes em SOs diferentes e será necessário sobrescrever o arquivo de fontes pelo jeito que o Jasper é escrito;
  2. Modificar o código do Jasper de modo a carregar as fontes programaticamente e, assim, permitindo que você possa carregar uma fonte específica;
  3. Usar AOP para fazer o que foi mencionado no item 2.

De qualquer forma, você precisará distribuir os arquivos que contém suas fontes com a aplicação se quiser ter certeza que seu texto terá exatamente o mesmo tamanho em todas as plataformas.

J

Então que dizer que se eu setar a fonte pra courier e colocar o tamanho 10. No linux, vai aparecer num determinado tamanho, agora no windows, apesar de ser as mesmas configurações, courier e tamanho 10, não será mostrado do mesmo tamanho !! Eh isso ??

Vc poderia explicar essa opção 1 ou me indicar algum local onde eu possa estudar essa solução ??

valeu cara !!

M

Exato, porque a fonte pode não existir ou não ser exatamente a mesma.

Você tem que descobrir como instalar fontes em cada SO. Diga-se de passagem, provavelmente isso vai exigir que o usuário tenha permissões administrativas na máquina.

T

Curiosidade. Há algumas fontes que são distribuídas no JRE em jre\lib\fonts ( LucidaBrightDemiBold.ttf, LucidaBrightDemiItalic.ttf, LucidaBrightItalic.ttf, LucidaBrightRegular.ttf, LucidaSansDemiBold.ttf, LucidaSansRegular.ttf, LucidaTypewriterBold.ttf, LucidaTypewriterRegular.ttf ), será que não daria para usá-las de alguma maneira em todos os SOs? LucidaTypewriterRegular seria uma fonte monoespaçada quase equivalente à Courier (só que sem as serifas).

M

thingol:
Curiosidade. Há algumas fontes que são distribuídas no JRE em jre\lib\fonts ( LucidaBrightDemiBold.ttf, LucidaBrightDemiItalic.ttf, LucidaBrightItalic.ttf, LucidaBrightRegular.ttf, LucidaSansDemiBold.ttf, LucidaSansRegular.ttf, LucidaTypewriterBold.ttf, LucidaTypewriterRegular.ttf ), será que não daria para usá-las de alguma maneira em todos os SOs? LucidaTypewriterRegular seria uma fonte monoespaçada quase equivalente à Courier (só que sem as serifas).

As fontes mudam de acordo com a versão do JDK :frowning:

J

Mister_m,

Como eu vou descobri uma fonte que tenha o mesmo comportamento em qualquer sistema operacional ??

valeu !!

M

Exatamente igual, não existe. Você precisa fornecê-la com sua aplicação e forcar a aplicação a utilizá-la.

J

Mas ai eh q ta cara !! Se eu pegar a courier no linux e instalar no windows elas não terão comportamento diferente ??

valeu !!

M

Se sua fonte for *.TTF, teoricamente não. O problema é que nada impede o usuário ou outro software de sobrescrever o arquivo novamente e por isso que distribuir a fonte com a aplicação é a melhor saída.

No entanto, acho que a licença da Courier não permite esse tipo de distribuição que você está propondo.

J

Eu quero eh fazer isso mesmo !!! Mas de qq forma eu num teria de instalar a fonte no outro sistema não ?? Tipo assim, se eu vou levar essa minha aplicação para rodar em um outro sistema operacional, eu vou ter que ir lá nesse outro sistema operacional e instalar essa minha fonte, ou não ?

valeu !!

M

É possível carregar dinamicamente uma fonte em Java usando a API, mas o Jasper não está preparado para usar este mecanismo de carregamento de fontes e acho que você está usando Jasper, não?

J

Estou usando jasper !!! E ai, o q eu faço ??

M

Aí, você tem as três opções que eu citei no início: ou instala fisicamente a fonte, ou modifica os fontes do Jasper ou usa aspectos :slight_smile:

J

mister__m:

Aí, você tem as três opções que eu citei no início: ou instala fisicamente a fonte, ou modifica os fontes do Jasper ou usa aspectos :-)

1 - instala fisicamente a fonte - Essa opção seria pra eu pegar os fontes que estão na pasta fonts do iReport e instalar no windows ?? A extensão .ttf funciona tanto no linux quanto no windows ?

2 - modifica os fontes do Jasper. Como seria essa opçao ??

valeu pela ajuda !!!

M

Bem, tem que instalar a fonte de onde quer que o software esteja lendo. Não sei dizer de cabeça onde isso fica no Linux, mas creio que não tem nada a ver com as fontes que vêm com iReport. Se não me engano, elas só são usadas com PDF.

Sim, mas a licença de diversas fontes não permite essa distribuição.

Você vai ter que mudar o código do Jasper que carrega fontes por nome para delegar para uma classe sua, que será um registro de nomes de fontes e implementações a serem utilizadas.

J

Essa primeira opção não seria muito interesante, pois como vc mesmo falou um software poderia sobrescrever a fonte.

Vc não teria exemplo dessa segunda opção não ?? Uma classe java que faça algo parecido ?

valeu !!

M

Pra carregar uma fonte, basta fazer:

Font font = Font.createFont(Font.TRUETYPE_FONT,  fontStream);

Agora, pra modificar o tamanho da fonte e colocar negrito e itálico, basta usar o método deriveFont.

J

Passei horas pesquisando na Internet pra descobrir que a fonte mais comum em ambos sistemas operacionais , windows e linux, é a True Type. Pelo q pode perceber, essa fonte é a que dá menos “descrepância” de um S.O para outro !!! Eh isso mesmo ? Por enquanto só não to encontrando um site pra baixar ela !!!

valeu !!

J

Qual a True Type mais comum ??

valeu !!

M

TrueType é somente o formato da fonte. Existem diversas fontes TrueType, mas a forma como elas são carregadas na maioria dos softwares (como no Jasper) exigiria uma coincidência literal do nome da fonte, o que não ocorre para nenhuma delas dependendo do SO.

Para que a nossa conversa pare de andar em círculos, eu queria entender o seguinte: você não pode gerar seu relatório como PDF? Se puder, utilizando as fontes do PDF você deveria (teoricamente) ter o mesmo resultado em todas as plataformas.

J

Cara brigdadão pela ajuda !!! Sei que as vezes ando em circulo, mas eh pq eu tento uma solução e volto pra outra e por ai vai… A verdade eh que eu ja to ficando meio doido com esse problema !! heheh

Vc tem razão, quando eu gero um PDF tanto no linux quanto no windows eles têm o mesmo comportamento. O problema de fonte so acontece mesmo quando eu mostro meu relatorio num JRViewer !!! No entanto, eu preciso que seja mostrado de forma correta também no JRViewer, pois o usuário poderá pedir pra ser impresso a partir dessa JRViewer.

Na verdade, vou tentar mudar a classe JRFont, para ver se eu consigo carregar uma fonte específica !!

valeu !

M

Se não mudaram ainda, o lugar onde você precisa mexer é:

net.sf.jasperreports.engine.util.JRStyledText.addRun(Run r)

Nesse método a instância de r contém um Map attributes que contém as instâncias de java.awt.font.TextAttribute que você deve utilizar para determinar qual fonte utilizar. Para forçar a troca da fonte, basta por nesse Map a instância de fonte utilizando como chave TextAttribute.FONT.

Sim, é complicado e eu disse isso no início :slight_smile: Estou tentando resolver este problema para o Mustang de forma mais limpa.

J

mister_m,
Dei uma olhada lá na classe, porém não consigo visualisar no método addRun(Run run) a instância de run possuindo um Map attributes, que contém as instâncias de java.awt.font.TextAttribute. Na classe Run não possui nada !!

Cara dá uma ajuda ai !!!

package net.sf.jasperreports.engine.util;

import java.text.AttributedString;
import java.util.ArrayList;
import java.util.List;

public class JRStyledText
{
    /* member class not found */
    class Run {}

    private StringBuffer sbuffer;
    private List runs;
    private AttributedString attributedString;

    public JRStyledText()
    {
        sbuffer = new StringBuffer();
        runs = new ArrayList();
        attributedString = null;
    }

    public void append(String text)
    {
        sbuffer.append(text);
        attributedString = null;
    }

    public void addRun(Run run)
    {
        runs.add(run);
        attributedString = null;
    }

    public int length()
    {
        return sbuffer.length();
    }

    public String getText()
    {
        return sbuffer.toString();
    }

    public AttributedString getAttributedString()
    {
        if(attributedString == null)
        {
            attributedString = new AttributedString(sbuffer.toString());
            for(int i = runs.size() - 1; i >= 0; i--)
            {
                Run run = (Run)runs.get(i);
                attributedString.addAttributes(run.attributes, run.startIndex, run.endIndex);
            }

        }
        return attributedString;
    }

    public List getRuns()
    {
        return runs;
    }
}
M

Peraí… Você está usando os fontes do jasper ou decompilou/abriu com um plugin de decompilação?

J

Eu descompilei , pq a versão que eu tô utilizando, jasperreport 0.6.1, não tem mais os fontes pra download !! Parece q deu problema na hora de descompilar a classe Run !!

M

Deve ter os fontes pra download no site sim, Javax. Se não tiver, você vai ter que fazer upgrade de versão.

J

mister_m,

Consegui !!! :smiley: Olha ia como ficou meu método addRun !! É isso mesmo ?? Quando eu atribuo ao Map uma fonte, através da chave TextAttribute.FONT, toda vez que minha aplicação rodar, apesar de possuir nesse Map varias outras fontes, será setado obrigatoriamente a fonte pra qual eu to apontando, no caso myfont.ttf, eh isso ??

Font font;

public void addRun(Run run)
	{
		
	    try{
		font =   Font.createFont(Font.TRUETYPE_FONT,this.getClass().getResourceAsStream("myfont.ttf"));
		}
		catch(FontFormatException e){
		    e.printStackTrace();
		    
		}
		catch(IOException e){
		    e.printStackTrace();
		    
		}
		run.attributes.put(TextAttribute.FONT,font);  
	       runs.add(run);
		attributedString = null;
	}
M

O que você fez funciona sim :slight_smile:

No entanto, algumas dicas pra melhorar sua solução: leia a fonte somente uma vez num método estático e utiliza a mesma instância todas as vezes.

Relance as exceções, não as engula. Se ter uma fonte exata é tão importante pra você, é melhor não gerar o relatório com a fonte errada e exibir um erro para o usuário.

Outra coisa é que este Map contém informações como o nome da fonte desejada. Isso significa que você poderia melhorar sua solução pra carregar instâncias específicas de fonte de acordo com o nome e suportar diversas fontes ao mesmo tempo.

J

Criei um método para que retorna a fonte (ver codigo lá em baixo ). Existe a necessidade desse método ser estático ?? Como ler o método somente uma vez ?? Ao meu ver, esse método ficará sendo chamado todavida pra poder setar a fonte !!!

Vc está sugerindo que eu crie uma classe, por exemplo FormatFonteException, e faça um throw new FormatFonteException(). Mas como ficaria ??

public void addRun(Run run)
    {
        run.attributes.put(TextAttribute.FONT, getFont());
        runs.add(run);
        attributedString = null;
    }

  
    public Font getFont()
    {
        try
        {
            font = Font.createFont(Font.TRUETYPE_FONT, this.getClass().getResourceAsStream("myfont.ttf"));
        }
        catch (FontFormatException e)
        {
            e.printStackTrace();

        }
        catch (IOException e)
        {
            e.printStackTrace();

        }
        return font;
    }
M

Reescrevendo seu código abaixo: (mostrar às vezes é mais fácil que explicar :-))

private static Font font;

   public void addRun(Run run) {
      run.attributes.put(TextAttribute.FONT, getFont());
      super.add(run);
   }

   public Font getFont() {
        if (font == null) {
           try {
               font = Font.createFont(Font.TRUETYPE_FONT, this.getClass().getResourceAsStream("myfont.ttf"));
           } catch (FontFormatException e) {
               throw new RuntimeException(e);
           } catch (IOException e) {
               throw new RuntimeException(e);
           }
        }

        return font;
    }

Note que eu ainda não implementei minha sugestão de algo genérico, i.e., levando em conta o nome da fonte para carregar a instância correta. Fica de lição de casa :wink:

C

O método getFont() não deveria ser static? :stuck_out_tongue:

[]'s

M

Sim, e private também. Isso que dá copiar código :slight_smile:

F

Por que você não usa as fontes Bitstream Vera? São fontes grátis, de licença livre, que permite a utilização em software comercial e são distribuídas com o Gnome.
Elas contém os formatos serifado, sans-serif e mono-espaçado, e são razoavelmente bonitas.
Mais informações:
:arrow: Bitstream Vera
:arrow: Bitstream Vera Fonts

M

O problema é que você teria que instalar as fontes no sistema operacional, o que varia para cada um deles e ainda pode exigir privilégios que o usuário não possui. Isso se forem TrueType (não olhei), se não, nem servem.

J

Cara fiz do jeito que vc me disse, baixei os fontes da API jasperreport-0.6.4 e fiz aquela alteração que vc me falou ! No entanto, estou com um problema : Como setar o tamanho da fonte ?? Estava tentando algo do tipo :

font = Font.createFont(Font.TRUETYPE_FONT, this.getClass().getResourceAsStream("/skins/LucidaTypewriterRegular.ttf"));
font1 = new Font(null, Font.TRUETYPE_FONT, 10);
font1 = font.deriveFont(10);

Esse font não deveria possuir um setSize() ou algo do tipo não ??

valeu !!

M

Você deve usar o deriveFont mesmo, inclusive para aplicar estilos como negrito e itálico. Vale a pena utilizar um cache para isso, por sinal.

J

Blz então. Agora, outra dúvida : No ireport eu setei dois campos com fontes diferentes, um com Courier e outra com Utopia. Quando eu rodo o relatorio a partir da minha aplicação, com o jaspereport-0.6.4 que eu alterei, não seria para o jasperreport alterar as fontes que eu setei no iReport e sobrescrever para a fonte que eu estou apontando agora ?? No entanto, ele não faz isso !! Ele ainda mostra os campos com Courier e Utopia !!! Eh como se a alteração que eu fiz não tivesse “forçando” a apontar para a minha nova fonte !!

public Font getFont()
    {
        if (font == null)
            try
            {

                font = Font.createFont(Font.TRUETYPE_FONT, this.getClass().getResourceAsStream("/skins/LucidaTypewriterRegular.ttf"));
                font1 = new Font(font.getName(), Font.TRUETYPE_FONT, 10);
                font1 = font.deriveFont(10);

            }
            catch (FontFormatException e)
            {

                throw new RuntimeException("Erro no formato da fonte", e);

            }
            catch (IOException e)
            {
                throw new RuntimeException("Erro ao carregar fonte", e);

            }
        return font1;
    }
M

O addRun(…) ainda está chamando esse seu método? Você já tentou depurá-lo?

J

Sim. Tudo está compilando e rodando sem erro !!! No entanto, minha fonte não está sendo setada !!

public void addRun(Run run)
    {
        run.attributes.put(TextAttribute.FONT, getFont());
        runs.add(run);
        attributedString = null;
    }
M

A última vez que testei isso foi com o 0.6.3, portanto, como você falou do 0.6.4, esse código pode não ter mais nada a ver :frowning:

Tente usar o 0.6.3 e diga o que acontece.

J

Não é possível baixar os fontes da versão 0.6.3 !! No site só é possível pegar da 0.6.4 pra cima !! :frowning:

M

Pegue direto do CVS.

J

Baixei lá do CVS a versão 0.6.3 e fiz as mesmas alterações, resultado : Deu certo !!! :smiley:
heheh . O chato é que, por exemplo, se eu for atualizar a versão do jasperreport não vou conseguir setar a minha fonte, fazendo a mesma alteração na API !!! :frowning: . No entanto, por enquanto vou deixar assim mesmo !!!

mister_m, num post passada vc citou a possiblidade de criar uma lista de fontes. Bem , na minha aplicação seria interessante ter duas fontes !! Como poderei adcionar mais uma fonte e ainda poder setá-la ??

valeu !!

M

A idéia seria você manter um Map relacionando o nome da fonte que é usado no relatório com a sua instância específica. Um dos atributos contidos em r.attributes é o nome da fonte usado no relatório, que você pode usar como chave para obter a instância da sua própria fonte.

J

Opa !! No meu caso não precisarei de duas fontes não !!! Mas sim de duas instâncias da mesma fonte, em tamanho diferentes !!! Preciso que essa minha fonte especifica tenha tamanho 18 no título e em todos os outros campos tenha tamanho 10 !!! Ou seja, preciso da mesma fonte em tamanhos diferentes !!!

A sua solução seria algo do tipo :

run.attributes.put("NomeDaFonte", getFont());

E lá no .jrxml eu colocaria assim :

<font fontName="NomeDaFonte"  .......

valeu !!

M

Não é necessário fazer isso. No r.attributes estão contidas informações como tamanho da fonte e estilo. Basta usar o deriveFont(…) na instância da fonte e eventualmente fazer cache.

J

Ao criar a fonte :

font = Font.createFont(Font.TRUETYPE_FONT, this.getClass().getResourceAsStream("BitstreamVeraSans.ttf"));
font = font.deriveFont(Font.TRUETYPE_FONT, 10);

E ao setá-la como padrão :

run.attributes.put(TextAttribute.FONT, font);

Todos os campos no meu relatorio vão ter tamanho 10 !!! Note que eu naõ tenho como mudar o tamanho da font, pois mudará para todos os campos !!!

M

Não, você não captou bem a mensagem :slight_smile:

Você pode fazer algo como (não testado):

Font f = getFont();
Number size = r.attributes.get(TextAttribute.SIZE);

if (size != null && size.intValue() != 10) {
   f = f.deriveFont(size.intValue());
}

r.attributes.put(TextAttribute.FONT, f)
J
mister__m:
Font f = getFont();
Number size = r.attributes.get(TextAttribute.SIZE);

if (size != null && size.intValue() != 10) {
   f = f.deriveFont(size.intValue());
}

r.attributes.put(TextAttribute.FONT, f)

Cara sinceramente não entendo uma coisa : Ao fazer "r.attributes.put(TextAttribute.FONT, f)" no Map será adcionado f não eh ?? E sse f possui apenas um tamanho não eh ?? Como então vou conseguir tamanhos diferentes dessa instancia f no meu relatorio ?? Do jeito que vc fez ai, todos os campos do meu relatorio ficaram no mesmo tamanho !!!

M
Javax:
mister__m:
Font f = getFont();
Number size = r.attributes.get(TextAttribute.SIZE);

if (size != null && size.intValue() != 10) {
   f = f.deriveFont(size.intValue());
}

r.attributes.put(TextAttribute.FONT, f)

Cara sinceramente não entendo uma coisa : Ao fazer "r.attributes.put(TextAttribute.FONT, f)" no Map será adcionado f não eh ?? E sse f possui apenas um tamanho não eh ?? Como então vou conseguir tamanhos diferentes dessa instancia f no meu relatorio ?? Do jeito que vc fez ai, todos os campos do meu relatorio ficaram no mesmo tamanho !!!

Você está meio perdido :-) Você testou meu código? Eu estou modificando a instância de f no exemplo que coloquei. Não tem razão pra não funcionar.

J

Agora eu entendi !!! :lol: O método addRun é executado para cada campo do meu .jrxml. E cada instãncia de run possui um Map, que contém o tamanho e estilo da fonte associada a um campo !!
Ao fazer :

Number size = (Number)run.attributes.get(TextAttribute.SIZE);

Vc estaria recuperando o tamanho da fonte corrente associada a um campo específico !!

Testei seu código ele executa sem erro, no entanto ele não está conservando o tamanho da fonte. Por exemplo, no meu relatorio existe um campo que tem tamanho 18. Ele deveria conservar o tamanho 18 e aplicar a minha fonte, no entanto ele está aplicando minha fonte com o tamanho 10. Ou seja, o campo não aparce no tamanho 18 , mas sim no tamanho 10 !! Segue abaixo o trecho de código.

public void addRun(Run run)
    {
        Font f = getFont();
        Number size = (Number)run.attributes.get(TextAttribute.SIZE);
        if (size != null && size.intValue() != 10) {
           f = f.deriveFont(size.intValue());
        } 
        run.attributes.put(TextAttribute.FONT, f);
        runs.add(run);
        attributedString = null;
    }
J

Descobri o erro !!! :smiley: Na linha que tinha :

f = f.deriveFont(size.intValue());

Eu troquei por :

f = f.deriveFont(size.floatValue());

Do jeito que estava, ele tava setando era o estilo !!

valeu cara pela ajuda !!!

M

Javax:
Descobri o erro !!! :smiley: Na linha que tinha :

f = f.deriveFont(size.intValue());

Eu troquei por :

f = f.deriveFont(size.floatValue());

Do jeito que estava, ele tava setando era o estilo !!

Verdade, o método é sobrecarregado. Por sinal. perigosíssimo isso de ter métodos que recebem tipos primitivos com semânticas totalmente diferentes.

J

Uma última dúvida …

Como setar a fonte PDF name ?? Seria interessante que a fonte no .pdf fosse a mesma que eu estou mostrando no JRViewer !!! Dá pra fazer isso ??

valeu !!!

M

Não lembro exatamente o nome do atributo, mas existe um dos atributos relacionadas a fonte e ao pdf no qual você pode colocar o nome do arquivo .TTF (com a extensão, inclusive), forçando a fonte a ser incluída no documento).

J

Seria algo desse tipo :

run.attributes.put(TextAttribute.PDF, f);

Não existe key relacionada ao PDF !!! :frowning:

M

Não, isso é parte “standard” do JasperReports e é um atributo da tag xml mesmo. Lembro que não dava pra editar no iReport diretamente :-/

Acho que o nome do atributo talvez seja pdfFontName ou algo assim.

J

mister__m:
Não, isso é parte “standard” do JasperReports e é um atributo da tag xml mesmo. Lembro que não dava pra editar no iReport diretamente :-/
Acho que o nome do atributo talvez seja pdfFontName ou algo assim.

Sim tudo bem … Mas onde vou colocar minha fonte pra ele poder carregar ??

M

Desde que o arquivo .TTF esteja visível no classpath da classe que vai gerar o PDF, tudo funciona :slight_smile:

J

Vixe … Eh mesmo !! :oops: Tb poderia colocar no mesmo diretorio da classe que vai gerar o PDF !!!

valeu …

A

Ola, estou com o mesmo problema, mas não em relatorios!
Minha aplicação é desktop. No windows ta beleza, ae quando rodo no linux a layout fica todo errado, acho que é pela fonte!
A fonte utilizada é a padrao: Tahoma. Instalei essa fonte no ubunto e mesmo assim continua todo errada a janela!
Alguem sabe como me ajudar em relação a isso?

Criado 12 de abril de 2005
Ultima resposta 26 de mar. de 2014
Respostas 67
Participantes 6