• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 346
  • Last Modified:

Using A Bitmap As Font

Hello experts, I would like to know how to use a bitmap as a font for my application just like WinAmp does. Can anyone help me?
0
New2Delphi
Asked:
New2Delphi
  • 4
  • 4
  • 2
  • +4
2 Solutions
 
Dennis9Commented:
Hi.
What u mean, the text or the skin it uses??

Dennis
0
 
TOndrejCommented:
Not sure what you mean, but if you want a bitmap tiled within text drawn on a canvas then you can use a path and a clipping region, see TPictureLabel.Paint on http://members.nbci.com/tondrej/Delphi.htm as an example
0
 
edsteeleCommented:
WinAmp uses a bitmap of an alphabet and then chops the bitmap up into little pieces, one per letter and pastes each bitmap when it needs a letter.  Technically, this is not a font, it is simply drawing an image (which happens to be an image of a letter) to a canvas.

Unless you are trying to created a skinned application, I would instead look for a font that will work for you.

Eric
0
Easily Design & Build Your Next Website

Squarespace’s all-in-one platform gives you everything you need to express yourself creatively online, whether it is with a domain, website, or online store. Get started with your free trial today, and when ready, take 10% off your first purchase with offer code 'EXPERTS'.

 
Mohammed NasmanSoftware DeveloperCommented:
Hello

  I didn't understand what u want well, but in winamp the font look like image, if you want to draw font in image here's some code

procedure TForm1.Button1Click(Sender: TObject);
begin
  Image1.Canvas.Brush.Color := clblack;
  Image1.Canvas.Rectangle(0,0,Image1.Width,Image1.Height);
  Image1.Canvas.Font.Color := clGreen;
  Image1.Canvas.Font.Style := [fsBold];
  Image1.Canvas.TextOut(5,5,'Delphi is the Best');
end;

Mohammed
0
 
New2DelphiAuthor Commented:
Dennis9, TOndrej, mnasman: edsteele has the idea. Do you know how I can do this? Can you help me out?

edsteele: Yes, that's exactly what I want to do. How can I use a bitmap of an alphabet and then chop the bitmap up into little pieces, one per letter
and paste each bitmap when my app needs a letter. Please help me out. Thanks!
0
 
DragonSlayerCommented:
Hi New2Delphi,

I tried this:
1. Create a bitmap file with all the letters I want, each letter *must* have a fixed width
2. Put a TImageList in your Form
3. Set the Height and Width to match the Height and Width for ONE letter
4. Load the bitmap file into the TImageList
5. Drop a PaintBox in your Form
6. Drop a TEdit in your Form
7. Drop a TButton in your Form
8. Handle the OnClick for the TButton and OnPaint for the TPaintBox

In the example below, my PaintBox is called PaintBox1, TButton is called btnDraw, TEdit is called ed.

I grabbed the sample font bitmap from WinAmp's EXE file.



procedure TfrmDownload.btnDrawTextClick(Sender: TObject);
begin
  PaintBox1.Refresh;
end;

procedure TfrmDownload.PaintBox1Paint(Sender: TObject);
var
  i: Integer;
  iLeft: Integer;
  iImage: TBitmap;
  iIndex: Integer;
  sString: string;
const
  LetterWidth = 5;
begin
  sString := UpperCase(Trim(ed.Text));

  if sString = '' then
    Exit;

  PaintBox1.Canvas.FillRect(Rect(0, 0, 297, 33));
  iLeft := 0;

  for i := 1 to Length(sString) do
  begin
    iImage := TBitmap.Create;
    iImage.Transparent := True;
    iImage.TransparentColor := clWhite;
    iImage.TransparentMode := tmFixed;
    iIndex := Byte(sString[i]) - Byte('A');
    ImageList1.GetBitmap(iIndex, iImage);
    PaintBox1.Canvas.Draw(iLeft, 10, iImage);
    Inc(iLeft, LetterWidth);
    iImage.Free;
  end;
end;


Of course, I only limited my character set to 26. You can create your own set, and load the appropriate character (heck, you could even have all the ASCII characters! If you have that, just change iIndex := Byte(sString[i]) - Byte('A'); to iIndex := Byte(sString[i]);).

Also, to make it better, you have to handle word-wrapping, and perhaps a variable-width font... just some suggestions :)



Hope that helped!

DragonSlayer.
0
 
edsteeleCommented:
I haven't run it, but it looks like DragonSlayer's code should do the trick, or at least send you in the right direction.  Using a TImageList is a very nice way to break the master image into smaller images for use.

If you don't want to use a TImageList, you can always use the CopyRect method of the TCanvas object.

var
  LetterBitmap: TBitmap;

procedure DrawLetter(Letter: Char; x, y: Integer; Canvas: TCanvas);
var
  DestRect, SrcRect: TRect;
begin
  LetterBitmap.CopyMode := cmSrcCopy;
  DestRect := TRect(x, y, x + LetterWidth - 1, y + LetterHeight - 1);
  SrcRect := TRect(Ord(Letter) - Ord('A'), 0, Ord(Letter) - Ord('A') + LetterWidth - 1, LetterHeight - 1);
  LetterBitmap.CopyRect(DestRect, Canvas, SrcRect);
end;

I may be off by a pixel here or there.  Of course you will have to load the bitmap of letters into LetterBitmap before calling the DrawLetter procedure.

Good Luck!
Eric
0
 
New2DelphiAuthor Commented:
Any other suggestions?

I need to use:
A-Z
a-z
0-9
!@#$%^&*()_=+-:;"'[]{}?/>.<,~`

How can I do this?
0
 
DragonSlayerCommented:
It's the same... just make sure that you retrieve from the correct index.

Load up an ASCII chart, you will see that '!' starts at ASCII 33, and it continues all the way till ASCII 126 ('~').

So what you do is, have a bitmap that has the text you want in the same order as the ASCII chart, and change the part that says
   iIndex := Byte(sString[i]) - Byte('A');
to
   iIndex := Byte(sString[i]) - Byte('!');

The END :)
0
 
edsteeleCommented:
There is another way to make the accessing of the indexes a bit nicer, but you have to carry an extra array around and you have to initialize it.  Something like this:

var
  CharIndex: Array[' '..'~'] of Byte;

procedure TMainForm.FormCreate(Sender: TObject);
var
  c: Char;
  Idx: Integer;
begin
  Idx := 0;
  for c := 'A' to 'Z' do
  begin
    CharIndex[c] := Idx;
    Inc(Idx);
  end;
  for c := 'a' to 'z' do
  begin
    CharIndex[c] := Idx;
    Inc(Idx);
  end;
  for c := '0' to '9' do
  begin
    CharIndex[c] := Idx;
    Inc(Idx);
  end;
  CharIndex[' '] := Idx;  Inc(Idx);
  CharIndex['!'] := Idx;  Inc(Idx);
  CharIndex['@'] := Idx;  Inc(Idx);
  CharIndex['#'] := Idx;  Inc(Idx);
  CharIndex['$'] := Idx;  Inc(Idx);
  CharIndex['%'] := Idx;  Inc(Idx);
  CharIndex['^'] := Idx;  Inc(Idx);
  CharIndex['&'] := Idx;  Inc(Idx);
  CharIndex['*'] := Idx;  Inc(Idx);
  CharIndex['('] := Idx;  Inc(Idx);
  CharIndex[')'] := Idx;  Inc(Idx);
  CharIndex['_'] := Idx;  Inc(Idx);
  CharIndex['='] := Idx;  Inc(Idx);
  CharIndex['+'] := Idx;  Inc(Idx);
  CharIndex['-'] := Idx;  Inc(Idx);
  CharIndex[':'] := Idx;  Inc(Idx);
  CharIndex[';'] := Idx;  Inc(Idx);
  CharIndex['"'] := Idx;  Inc(Idx);
  CharIndex[''''] := Idx;  Inc(Idx);
  CharIndex['['] := Idx;  Inc(Idx);
  CharIndex[']'] := Idx;  Inc(Idx);
  CharIndex['{'] := Idx;  Inc(Idx);
  CharIndex['}'] := Idx;  Inc(Idx);
  CharIndex['?'] := Idx;  Inc(Idx);
  CharIndex['/'] := Idx;  Inc(Idx);
  CharIndex['>'] := Idx;  Inc(Idx);
  CharIndex['.'] := Idx;  Inc(Idx);
  CharIndex['<'] := Idx;  Inc(Idx);
  CharIndex[','] := Idx;  Inc(Idx);
  CharIndex['~'] := Idx;  Inc(Idx);
  CharIndex['`'] := Idx;  Inc(Idx);
end;

Now when you need the index of particular characters, you can just use something like:

for i := 1 to Length(MyString) do
begin
  PlotChar(CharIndex[MyString[i]]);
end;

If you had a procedure called "PlotChar", that loop would call it for each character in the string "MyString", passing the index you defined.

The setup is ugly, but this allows you to put the characters in any order you want if you don't want to follow the ASCII ordering.  You may want to define the "CharIndex" array to hold the whole ASCII range and initialize the whole array to a special character of your choosing.  That way if you request a character that is not part of your defined set of characters, you get the special character back.

Eric
0
 
New2DelphiAuthor Commented:
edsteele, could you create the PlotChar procedure? I would really appreciate it. Thanks!
0
 
edsteeleCommented:
Sure.

type
  TForm1 = class(TForm)
  private
    ...
    CurrX, CurrY: Integer;
    ...
  public
    ...
    procedure PlotChar(Idx, X, Y: Integer); overload;
    procedure PlotChar(Idx: Integer); overload;
    ...
  end;

procedure TForm1.PlotChar(Idx, X, Y: Integer);
begin
  CurrX := X;
  CurrY := Y;
  PlotChar(Idx);
end;

procedure TForm1.PlotChar(Idx: Integer);
var
  CharBitmap: TBitmap;
begin
  CharBitmap := TBitmap.Create;
  MyImageList.GetBitmap(Idx, CharBitmap);
  TargetCanvas.Draw(CurrX, CurrY, CharBitmap);
  CurrX := CurrX + CharBitmap.Width;
  CharBitmap.Free;
end;

I used two overloaded procedures to accomplish this so that plotting many characters in a row will be easier.  First, you call PlotChar(Idx, X, Y), where X and Y are the coordinates on the canvas where you would like the character placed.  After that, you can just call PlotChar(Idx) repeatedly for the other characters on the line.  To start plotting in another location, simply call PlotChar(Idx, X, Y) again.

Note: If you will need to plot to more than one canvas, you may want to pass that in to the procedure also instead of coding it directly.

Eric
0
 
New2DelphiAuthor Commented:
Okay! Thanks! Let me check it out first.
0
 
Russell LibbySoftware Engineer, Advisory Commented:
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

To be split between edsteele and DragonSlayer

Please leave any comments here within the next seven days.
 
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
 
Thank you,
Russell

EE Cleanup Volunteer
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Easily Design & Build Your Next Website

Squarespace’s all-in-one platform gives you everything you need to express yourself creatively online, whether it is with a domain, website, or online store. Get started with your free trial today, and when ready, take 10% off your first purchase with offer code 'EXPERTS'.

  • 4
  • 4
  • 2
  • +4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now