Caneta laser
Já pensou como seria legal escrever com uma caneta laser?

Todas as produções multimídia modernas valem-se de recursos especiais de animação para obter destaque em parte da informação mostrada no vídeo, com o propósito de chamar a atenção do usuário. Os pacotes de apresentação geralmente disponibilizam inúmeros efeitos especiais como fade, dissolve, fusão, rolamentos, etc. Mas não deixa de ser um desafio desenhar e produzir nossos próprios efeitos.

Um efeito em especial sempre me chamou a atenção e o tinha na "gaveta dos projetos" - aquele conjunto de programas e rotinas que temos vontade de fazer, mas nunca sobra o tempo necessário ou nunca aparece uma oportunidade real de uso, então vai ficando na gaveta mesmo.

Trata-se de uma impressão de figuras e textos feita à laser. É isso mesmo, um raio laser vai desenhando as letras do texto ou a figura a ser mostrada. Este efeito data dos primórdios da informática e já era usado antes mesmo dos computadores possuirem alta resolução gráfica. Sempre achei que seria fácil de ser implementado num programa e que a rotina do raio laser seria extremamente simples de ser feita. No tempo dos computadores de 4 Mhz isto até exigiria assembler e acesso direto ao vídeo, mas no tempo dos micros de 1.2 Ghz e Delphi...

Então lá vamos nós. Nesta altura do campeonato, considero que o leitor deve estar muito mais interessado na mecânica de programação do que no efeito propriamente dito. É para ser assim mesmo, afinal não estamos revolucionando o mundo da multimídia mas sim aplicando alguns conhecimentos numa nova estrutura de programação. Então, talvez fosse o caso de dar uma paradinha e tentar, antes de prosseguir, visualizar como seria a sua solução para a rotina de impressão à laser. Pode ir, eu espero.

Voltando então aos procedimentos de criação do nosso efeito, vamos considerar primeiro a impressão de um pequeno texto. Uma frase, do tipo "NÃO PERCA A TILT DESTE MES". É claro, o texto estará na propriedade Text de um componente TEdit (assim poderemos mudar as frases em tempo de execução).

O problema é ter acesso ao desenho da letra, à sua posição na frase e ao espaçamento proporcional que cada uma possui. Resolvendo de forma rápida esta questão, decidi fazer o seguinte: crio um TLabel com a propriedade AutoSize em True e uso a propriedade Caption para definir letra a letra a ser impressa, da frase estabelecida em Edit1.Text. Ao passar cada letra de Edit1.Text para Label1.Caption, as propriedades Width e Height do TLabel irão me fornecer a largura e altura da letra (considerando que Label1 já esteja com as propriedades Font devidamente ajustadas para letra desejada).

  for Tmh:= 1 to length(Edit1.Text) do begin
    Label1.Caption:= Edit1.Text[Tmh];
    BMPdaletra; Showletra;
  end;

Para gerar o exemplo, usei uma fonte Ariston e corpo 48. Cada um seleciona a fonte que desejar ou então crie uma caixa de diálogo para escolher entre as fontes instaladas, durante a execução do programa.

Resolvido o problema do tamanho da letra, precisamos agora obter o desenho dela bit a bit. A rotina só irá "acionar" o laser se o ponto da letra for impresso. Na parte em branco da imagem o raio fica desligado. Novamente usei o que já existe. Criei uma TImage que é ajustada para as mesmas dimensão da TLabel e que recebe o desenho da letra com uma impressão direta, via função Canvas.TextOut.

  procedure BMPdaletra;
  begin
    with Form1 do begin
    Image1.Canvas.Font:= Label1.Font;
    Image1.Width:= Label1.Width;
    Image1.Height:= Label1.Height;
    Image1.Canvas.TextOut(0,0,Label1.Caption);
    end;
  end;

Tendo então a matriz de impressão da letra, agora basta varrer linha a linha, ponto a ponto a TImage da letra e decidir de o raio é acionado ou não.

  procedure Showletra;
  var
    Orig,Dest: HBitmap;
    Tmx,Tmy: integer;
  begin
    Orig:= Tela.Canvas.Handle;
    Dest:= Form1.Alvo.Canvas.Handle;
    Form1.Alvo.Canvas.Pen.Color:= clRed;
    for Tmy:= 0 to Form1.Image1.Height -1 do begin
      for Tmx:= 0 to Form1.Image1.Width -1 do begin
        if Form1.Image1.Canvas.Pixels[Tmx,Tmy] = clBlack
        then begin
          Tela.Canvas.Pixels[Px+Tmx,Py+Tmy]:= clLime;
          BitBlt(Dest,0,0,500,200,Orig,0,0,SRCCOPY);
          Form1.Alvo.Canvas.MoveTo(250,200);
          Form1.Alvo.Canvas.LineTo(Px+Tmx,Py+Tmy);
          Form1.Alvo.Repaint;
        end;
      end;
    end;

    BitBlt(Dest,0,0,500,200,Orig,0,0,SRCCOPY);
    Px:= Px + Form1.Image1.width;
  end;

As variáveis globais Px e Py irão conter a posição de impressão das letras na TImage final, ou seja, aquela que será mostrada ao usuário.

Como a impressão envolve uma grande quantidade de operações, como uma transferência completa da TImage final para o vídeo e outros tantos processamentos internos, não houve necessidade de criar nenhuma rotina de retardamento da impressão. Mas, como cada computador é um computador diferente, pode ser que para você a rotina esteja muito rápida, ou muito lenta. Daí é só inserir o conjunto todo dentro de uma estrutura controlada por um evento OnTimer e ajustar o timer do relógio.

A impressão de imagens usa basicamente a mesma estrutura, até que mais simples pois não apenas as dimensões já são conhecidas, como a matriz de definição da imagem já é fornecida. Eliminamos a fase de inicial da rotina anterior.

  procedure ShowFigura;
  var
    Orig,Dest: HBitmap;
    Tmx,Tmy: integer;
  begin
    Orig:= Tela.Canvas.Handle;
    Dest:= Form1.Alvo.Canvas.Handle;
    for Tmy:= 0 to Form1.Image1.Height -1 do begin
      for Tmx:= 0 to Form1.Image1.Width -1 do begin
        if Form1.Image1.Canvas.Pixels[Tmx,Tmy] = clBlack
        then begin
          Tela.Canvas.Pixels[Tmx-1,Tmy-1]:= clGray;
          Tela.Canvas.Pixels[Tmx,Tmy]:= clWhite;
          BitBlt(Dest,0,0,250,250,Orig,0,0,SRCCOPY);
          Form1.Alvo.Canvas.Pen.Color:= clWhite;
          Form1.Alvo.Canvas.MoveTo(125,250);
 
          Form1.Alvo.Canvas.LineTo(Tmx,Tmy);
          Form1.Alvo.Canvas.Pen.Color:= clYellow;
          Form1.Alvo.Canvas.Rectangle(Tmx-2,Tmy-2,Tmx+2,Tmy+2);
          Form1.Alvo.Repaint;
        end;
      end;
    end;
    BitBlt(Dest,0,0,250,250,Orig,0,0,SRCCOPY);
  end;

Aqui basta carregar a figura numa TImage e transferí-la para a tela via raio laser. Só para diferenciar, coloquei um pequeno quadrado na ponta do raio para que o ponto de impressão simulasse uns respingos. Também estou fazendo duas impressões do ponto: uma na sua posição (numa cor) e outra um pixel afastado (em outra cor), para obter uma aparência de profundidade no "sulco criado pelo raio".

Como estão, ambas as rotinas podem ser usadas sem contra indicações e sem efeitos colaterais adversos. Mas ainda podem ser incrementadas e reestruturadas de acordo com o interesse de cada programador. O objetivo aqui era dar apenas os primeiros passos e mostrar uma das inúmeras direções possíveis, quando se deseja criar um determinado efeito de animação.

Que tal tentar criar o seu efeito especial?


Download...
Clique no link para fazer o download dos arquivos. Se sua assinatura do club TILT está para vencer, clique aqui e saiba como renová-la.

Fontes do laser de texto
Fontes do laser de figuras
 
online