29 de agosto de 2011

Trabalhando com a tag Canvas do HTML5 - parte I

Dentre as inovações introduzidas pelo HTML5, certamente a que causou maior impacto foi a adoção da tag Canvas. A discussão em torno desse recurso acabou ampliada pelo potencial que ele tem de eliminar a necessidade de outras tecnologias bem estabelecidas, como o Adobe Flash, usado para criar animações em páginas da Internet.

Mas, o que é a tag Canvas, como ela funciona e pra que exatamente ela serve ? A grosso modo, essa tag cria uma área retangular dentro de uma página HTML onde é possível desenhar livremente. Ela faz isso franqueando ao desenvolvedor acesso aos pontos (pixels) que compõem a área, o que pode ser combinado com eventos para criar animações. É um comportamento análogo ao disponível através da classe TCanvas que há no Delphi. Tal analogia é reforçada pelo fato que a tag Canvas em si apenas demarca a região na página HTML, sendo que quaisquer desenhos ou interações que se queira implementar têm que ser obtidos através de programação, usando os métodos e propriedades disponibilizados para uso com JavaScript.

Para começar, então, devemos incluir no corpo do texto HTML a marcação do lugar onde o Canvas será renderizado, exatamente do mesmo modo que fazemos com outras tags. O exemplo abaixo cria uma página HTML que possui apenas um Canvas, com comprimento de 400 pontos e altura de 200 pontos:
<body>
<canvas id="myCanvas" width="400" height="200"
style="border:1px solid #c3c3c3;">
Seu navegador não suporta canvas ...
</canvas>
/* ... */
</body>
O texto inserido na tag será exibido apenas se a página for aberta por um navegador que não implementa o recurso de Canvas. Neste caso, para obter um resultado mais profissional, o texto pode ser substituído por um conteúdo HTML apropriado - como uma imagem, por exemplo.

Daqui em diante, todo o trabalho em cima do Canvas tem que ser feito por JavasScript. Primeiro, precisamos recuperar o contexto para desenho pois é nele que o conteúdo apresentado pelo Canvas é criado e manipulado:
function desenha () {
var myCanvas = document.getElementById("myCanvas");
var ctx = myCanvas.getContext("2d");
/* ... */
}

Todas as funções disponíveis no contexto que recuperamos deverão informar coordenadas, isto é, pares de valores (x,y) para se referir a um ponto dentro do plano delimitado pela área do Canvas. A diferença em relação a um plano cartesiano é que no canvas o canto superior esquerdo é sempre (0,0), com os valores de X crescendo para a direita e os de Y crescendo para baixo, como mostra essa imagem da fundação Mozilla :
Coordenadas na tag Canvas

O exemplo abaixo é bastante básico : move a posição atual do cursor de desenho para o centro do Canvas, traça uma linha até o canto inferior esquerdo, outra até o canto inferior direito e uma terceira até o ponto original. Por fim, a figura fechada é preenchida com a cor corrente :
/* ... */
ctx.beginPath ();

ctx.moveTo (myCanvas.width / 2,
myCanvas.height / 2);
ctx.lineTo (0,
myCanvas.height);
ctx.lineTo (myCanvas.width, myCanvas.height);
ctx.lineTo (myCanvas.width / 2,
myCanvas.height / 2);

ctx.stroke();
ctx.fill();

ctx.closePath();
/* ... */
Seu navegador não suporta canvas ...
Vamos por partes ! As funções beginPath() e closePath() do contexto delimitam passos que constituirão um único desenho para o Canvas, não importando quantos passos são necessários para montá-lo. Com isso, os passos entre essas funções compartilham estilos para traçar linhas e preencher áreas, por exemplo. Então, se há partes com cores diferentes, elas deverão ser traçadas como desenhos diferentes dentro do Canvas.

No exemplo, o primeiro passo é uma chamada à função moveTo(). Ela em si não faz qualquer desenho, servindo apenas para estabelecer um ponto de partida para passos seguintes. Ou seja, é o ponto onde o pincel primeiro tocará a área de pintura. Assim, ao chamarmos a função lineTo(), traçamos uma linha reta a partir daquele ponto até o ponto indicado nos parâmetros do lineTo. Esse novo ponto, então, passa a ser a posição atual do pincel. Se fosse preciso, poderíamos mover novamente sua posição para qualquer outro ponto sem afetar visualmente o canvas.

A função stroke() efetiva todos os comandos dados antes, forçando as linhas a serem traçadas com os estilos estabelecidos. Como não comandamos nada diferente, o canvas usará o estilo padrão de cor, espessura e tracejado.

Para encerrar, a função fill() é chamada para preencher a área interna da figura - também usando estilos padronizados.

Há muitas outras funções para desenhar retângulos, arcos e até curvas mais elaboradas, além da capacidade de incluir textos e imagens externas, o que permite combinar vários recursos para compor figuras bastante complexas. Em outro post, mostra mais desses recursos.

Os exemplos mostrados neste post usam o contexto para desenhos 2D mas já há uma versão experimental de contexto 3D, baseado no WebGL. Veja um exemplo de uso neste link.

18 de agosto de 2011

Atualização da especificação do C++ ganha aprovação unânime

Já faz algum tempo, o órgão responsável por padronizações internacionais (ISO) tem um comitê para discutir novos recursos para a linguagem de programação C++. Após 8 anos de trabalho, um rascunho das especificações já tinha sido liberado no início deste ano para que a comunidade decidisse se aprovava ou não.

O foco principal das mudanças na especificação foi a adequação do C++ a arquiteturas mais modernas de processamento paralelo, isto é, teve como objetivo facilitar o desenvolvimento de software C++ para esse tipo de ambiente. Além de alterações na STL (Standard Template Library), o novo C++ também ganha tratamento para expressões lambda (veja funções anônimas) e novos tipos de dado para trabalhar com computação paralela. Há ainda mudanças sintáticas para melhorar a performance dos programas.

Um resumo das alterações introduzidas pode ser consultado no artigo da Wikipedia sobre o C++0x - nome pelo qual a versão era conhecida mas que agora foi batizado oficialmente como C++11.

Na semana passada, o rascunho foi finalmente aprovado - por unanimidade - e passa a ser a recomendação oficial para a linguagem C++. Abaixo, segue matéria da InfoWorld que anuncia a aprovação. A matéria original em inglês está neste link.

"Com a recente aprovação do upgrade para a linguagem C++, o ISO (International Organization for Standards) está fornecendo aos desenvolvedores ferramentas que alavancarão o uso de algorítmos paralelos e permitirão uma melhor performance", disse na terça-feira o presidente do comitê responsável pela linguagem, Herb Sutter.

"O C++11 é a primeira grande revisão do ISO C++", disse o presidente. "Foi introduzido no C++11 as funções lambda, que são peças chaves para os emergentes algorítmos paralelos e que revolucionam o uso da Standard Template Library (STL)", disse Sutter, que é também um dos principais arquitetos para linguagens nativas na Microsoft. "O que já existia na biblioteca padrão do C++98 se tornará imediatamente mais fácil de ser usado", disse. Além disso, alterações na semântica do C++11 trazem melhoria na performance. Os novos recursos para tratamento de concorrência incluem tipos de dados para programação portável e livre de locks.

A votação final para o padrão C++ se encerrou na quarta-feira passada e foi unanimemente aprovada, disse Sutter em seu blog. O C++11 era conhecido como C++0x e sua publicação oficial se dará dentro de algumas semanas. "A linguagem", ele diz, "é usada para quase tudo -- o mundo está construído sobre C++."

O C++, incluindo seu subconjunto, o C, é usado para criar compiladores e runtimes de virtualmente todas as linguagens que concorrem com ele, todos os principais navegadores da internet, todos os principais sistemas operacionais, diz Sutter. É também a principal linguagem usada pelo Google e pelo Facebook e a principal linguagem para quase todos os produtos da Microsoft, afirma. "O C++ é a linguagem a se escolher na construção de aplicações de alta performance, qualquer que seja o domínio dessa aplicação", diz Sutter.

"C++ é uma linguagem de uso geral", afirma Henry Skoglund, desenvolvedor C++. "Muito do que foi incluído no novo padrão eu diria que é importante para desenvolvimento de sistemas e de compiladores," ele diz. "Os recursos do Lamdba", assegura Skoglund, "permitem aos desenvolvedores escrever código com menos bugs e em menos linhas."

Também contempladas no C++11 estão as funções auto e decltype, onde a primeira é útil para dedução de tipos e a segunda permite obter o tipo de dado real de qualquer expressão. Ainda, ponteiros smart, tais como o unique_ptr, oferecem um gerenciamento de memória automatizado e padronizado.

O próximo passo para o padrão C++ é ser implementado pelos compiladores nos próximos um ou dois anos, afirma Sutter. "Enquanto isso se desenrola, o comitê de padrões continuará a trabalhar nos recursos já incluídos no C++11, incrementando a biblioteca padrão de modo que uma biblioteca maior, portável (que não requeira novos recursos da linguagem além dos que já foram incluídos), esteja disponível dentro de cada implementação C++." Está sendo cogitada também uma nova rodada de extensões à linguagem, como conceitos de template ou lambdas mais fortes para o C++11.

Mesmo antes de se tornar oficial, alguns compiladores - como o C++ da Embarcadero (C++ Builder XE) e da Microsoft (Visual C++ 2010) - já incorporaram às suas bibliotecas recursos definidos por esse novo padrão.

4 de agosto de 2011

Recuperando emails de uma caixa postal com Delphi

Até pouco tempo atrás, o ERP da ABC71 possuia um recurso que permitia aos usuários enviarem sugestões de melhorias do software por email. Uma aplicação em nossos servidores monitorava a caixa postal específica, interpretava algumas informações incluídas em cada email, vinculava a solicitação a um responsável e respondia automaticamente o email do usuário com uma mensagem pré-formatada preparada pelo atendimento a Clientes.

Hoje esse esquema não existe mais - foi substituído por outros canais com papel similar - mas a ideia da aplicação capaz de monitorar uma caixa postal ainda é válida e pode ser reaproveitada em outros cenários.

A solução adotada por nós é baseada no protocolo chamado POP3 (Post Office Protocol). Com ele é possível recuperar todas as mensagens existentes na caixa de entrada de uma conta de email. A implementação dele que usamos é a do Projeto Indy distribuida junto com o IDE do Delphi;

Da mesma forma que outros protocolos baseados no IP, usar o POP3 exige que se faça a conexão com o servidor antes de realizar qualquer operação. Temos, então, que informar o nome (ou endereço) desse servidor, a porta onde se conectar e um nome de usuário e sua senha, válidos para a operação desejada.
var _IdPOP3 : TIdPOP3;
begin
_IdPOP3 := TIdPOP3.Create (Nil);

_IdPOP3.Host := _ServidorPOP;
_IdPOP3.Port := _PortaPOP;
_IdPOP3.Username := _Username;
_IdPOP3.Password := _Userpwd;
_IdPOP3.AutoLogin := True;

_IdPOP3.Connect ();

A propriedade AutoLogin ajustada com o valor true indica que o componente tentará automaticamente fazer o login no servidor sempre que isso for necessário, evitando que tenhamos que comandar o login manualmente.

Uma vez que temos a conexão estabelecida, podemos iniciar a recuperação das mensagens da caixa de entrada. Há basicamente dois níveis de informação que conseguimos recuperar sobre uma mensagem. Em ambos os casos, as informações são armazenadas numa variável do tipo TIdMessage. No primeiro nível, são obtidos somente os dados de cabeçalho da mensagem - como o assunto, o remetente e os destinatários -, o que reduz o tráfego na rede. O trecho abaixo recupera o cabeçalho da primeira mensagem da caixa de entrada:
var msg : TidMessage;
begin
msg := TidMessage.Create(self);

_IdPOP3.RetrieveHeader (1, msg);
{ ... }
msg.Free;

O segundo nível permite recuperar a mensagem completa, incluindo todas as informações do nível anterior, bem como o corpo da mensagem e todos os anexos dela. Ao utilizar esse método, a caixa postal marca automaticamente a mensagem como lida:
var msg : TidMessage;
begin msg := TidMessage.Create(self);

_IdPOP3.Retrieve (1, msg);
{ ... }
msg.Free;

Com as informações obtidas nesse nível, temos maior flexibilidade para customizar tratamentos para as mensagens. Por exemplo, podemos redirecionar a mensagem para outra pessoa de acordo com o conteúdo ou processar os anexos, salvando-os numa pasta do computador ou num banco de dados.

Não podemos esquecer que o conteúdo de um email pode ser composto de diversas partes distintas, conforme mostrei no post sobre envio de email com Delphi. Então, dependendo de como o email foi composto, recuperar o corpo da mensagem pode ser um simples acesso à propriedade msg.Body.Text ou significará termos que percorrer a lista de partes para determinar qual é o texto contido. Se o texto no corpo está em branco, basta percorrer a lista de partes procurando por uma que seja do tipo texto (TIdText):
var { ... }
parte : TIdMessagePart;
texto : TIdText;
corpo : string;
begin
{ ... }
_IdPOP3.Retrieve(1, msg);

for j := 0 to msg.MessageParts.Count - 1 do begin
parte := msg.MessageParts.Items[j];
{ Verifica se a parte é um texto }
if (parte is TIdText) then begin
texto := parte as TIdText;
corpo := texto.Body.Text;
break;
end;
{ ... }

O tipo do texto contido numa parte fica informado na propriedade ContentType. Como é permitido ter mais que uma parte com texto, pode-se testar esse tipo para recuperar o texto que interessa. É comum enviar uma parte com texto HTML e outra com texto TEXT/PLAIN para que o programa leitor de email decida qual exibir, de acordo com a opção feita pelo usuário.

Da mesma forma que recuperamos o texto lendo as partes, podemos salvar os anexos. Para isso, a parte deve ser do tipo TIdAttachment. Também podemos determinar o tipo do conteúdo do anexo lendo a propriedade ContentType da parte em questão. Salvar o arquivo fica fácil :
{ ... }
for j := 0 to msg.MessageParts.Count - 1 do begin
parte := msg.MessageParts.Items[j];
{ Verifica se a parte é um anexo }
if (parte is TIdAttachment) then begin
anexo := parte as TIdAttachment;
anexo.SaveToFile('c:\temp\' + anexo.FileName);
end;
{ ... }

Mas, como saber quais mensagens podem ser recuperadas ? A quantidade de mensagens existentes é conseguida através da função CheckMessages; podemos recuperar qualquer uma delas usando um número inteiro entre 1 e essa quantidade. A lista é trazida em ordem cronológica, com as mensagens mais antigas da caixa de entrada possuindo os menores números de identificação.
for i := 1 to _IdPOP3.CheckMessages do
begin
msg := TidMessage.Create(self);
_IdPOP3.RetrieveHeader (i, msg);

if DeveRecuperarMsg (msg.MsgId) then
TrataMsg (Msg);
msg.Free;
end;

As mensagens lidas permanecem na caixa até que sejam removidas. O POP3 permite fazer essa remoção mas nem sempre isso é uma opção. Para esses casos, uma sugestão é controlar manualmente as mensagens. Elas possuem uma string de identificação chamada MsgID que é única, como mostra o código acima. A ideia é recuperar apenas o cabeçalho da mensagem, testar se o MsgID atual já foi tratado antes e só então trazer a mensagem completa, se for necessário.

Quando concluir as operações na caixa postal, finalize a conexão com o POP3 usando a função Disconnect.

Como se pode ver pelo exemplo retratado neste post, o protocolo POP3 é bastante simples, limitando-se a poucas funcionalidades básicas. Se for preciso usar recursos mais avançados, tais como restringir as mensagens recuperadas usando filtros ou realizar operações envolvendo "pastas" na caixa postal, teremos que apelar a um protocolo mais completo, como o IMAP4. No post Trabalhando com emails em uma caixa postal usando IMAP4 em Delphi eu mostro como usá-lo.

Mais Informações
Post Office Protocol

1 de agosto de 2011

Adobe lança ferramenta para criação de conteúdo rico com HTML5

Já faz algum tempo que a mídia especializada em TI vem prevendo dificuldades para a tecnologia Flash. Razões para isso não faltam. Primeiro, foi o surgimento do HTML5, cuja especificação inclui recursos que permitem desenvolver animações apenas com padrões abertos. Depois, as declarações de Steve Jobs criticando o excesso de bugs existentes no Flash, argumento usado para justificar a falta da tecnologia Flash no sistema usado pelos dispositivos móveis da Apple.

A própria Adobe parece estar de precavendo contra uma possível debandada no uso de sua tecnologia. Hoje eles anunciaram o preview de uma ferramenta onde as animações são construídas com padrões da internet - HTML5, CSS e JavaScript - ao invés do Flash. Com isso, procuram se manter no topo no nicho tecnológico em que conquistaram grande destaque. Ao que parece, se o Flash realmente naufragar, a Adobe ainda terá uma grande ferramenta para construção de animações. Caso ele sobreviva, nunca é demais dar ao desenvolvedor outras possibilidade de escolha, principalmente se há uma opção baseada em padrões abertos.

A ferramenta, que chama-se Edge, está disponível no site Adobe Edge como parte do laboratório da Adobe. O anúncio dela foi tema de um artigo na Infoworld.com, o qual reproduzo abaixo, traduzido:
Plantando sementes que têm o potencial de derrubar sua própria franquia de sucesso em desenvolvimento de animações Flash, a Adobe lançou um preview de uma nova aplicação chamada Adobe Edge, projetada para montar conteúdo web dinâmico usando HTML5 e outros padrões abertos relacionados, anunciou a empresa nesta segunda-feira.

"Esta é uma ferramenta para animações e interatividade para designers que queiram construir conteúdo web interativo usando padrões da Web", disse Devin Fernandez, gerente de produto da Adobe.

Tradicionalmente, Web designers têm usado o Adobe Flash, ou concorrentes como o Microsoft Silverlight, para acrescentar animações estilosas e conteúdo interativo a páginas Web, na forma de telas de abertura para o site, gráficos interativos, vídeos curtos ou propagandas. A Adobe estima que 99 porcento de todos os computadores desktop possuem o plug-in necessário para executar arquivos Flash.

Nos últimos anos, no entanto, a W3C (World Wide Web Consortium) e outros órgãos de padronização vêm desenvolvendo um punhado de especificações que podem ser usadas na criação de conteúdo rico semelhante ao Flash. Os fabricantes de navegadores estão incorporando esses padrões - tais como HTML5, a tag Canvas, JavaScript e CSS (Cascading Style Sheets) - em seus navegadores, o que elimina a necessidade de um plug-in externo para executá-los.

A Apple também não está ajudando a sorte da Adobe pois seu CEO, Steve Jobs, criticou o Flash no passado, afirmando que ele possui bugs demais e instando os desenvolvedores a usarem o HTML5 no lugar.

"Muitos trabalhos que estavam previamente reservados para o Flash estão agora sendo feitos com padrões Web," admitiu Fernandez. "Nós vemos como uma enorme oportunidade para a companhia ajudar as pessoas a extrairem o melhor do HTML5."

Esta ferramenta usa HTML5, CSS e Javascript para inserir conteúdo Web animado diretamente numa página HTML. Com uma abordagem similar à da ferramenta de criação do Flash, o Edge permite ao desenvolvedor alterar atributos de uma imagem ou de um elemento HTML ao longo de um intervalo de tempo, resultando numa página animada.

"A Adobe tem mostrado que pode se adaptar muito bem a novas tendências. Isto mostra que eles podem se manter como principais vendedores de ferramentas, não importa qual a tecnologia que está embarcada," disse Al Hilwa, analista de desenvolvimento de aplicações do IDC. "Há poucas empresas sintonizadas com as necessidades e sensibilidades de um designer como a Adobe está, e esta ferramenta realmente mostra isso. Ela traz o modelo de linha do tempo, que é familiar a muitos desenvolvedores Flash, para o mundo novo do HTML5 e JavaScript, enquanto mantém a integridade do código."

A Adobe não tem expectativa de que o Edge vá suplantar o Flash inteiramente, ao menos não no futuro próximo. "A tecnologia Flash permanecerá um componente chave para casos de uso específicos, como vídeos de qualidade e jogos," disse Fernandez. "Nós definitivamente vemos HTML5 e Flash coexistindo, e, por isso, continuaremos a trabalhar em soluções para ambos na Adobe. Os usuários decidirão qual tecnologia eles usarão."

A edição preview está disponível como um download gratuito. Adobe espera liberar a versão comercial final em 2012, segundo Fernandez. Haverá versões tanto para Microsoft Windows quanto para Apple Macintosh.

A matéria original em inglês pode ser encontrada nesse link.