Hi All, I'd like some advice about the attached unit, named "uFixedWidthFonts.pas". It is designed to read 2-colour bitmaps of font character sets of different sizes, from files which are Windowz BMP format. For example, "Chars_Lower_8x8.bmp" -- this is a 320 x 56 pixels, 1 layer BMP file, file size 2.25 KB. E.g. the BMP file is a 2 colour image of a 256 character bitmap, where each character in the BMP file (in this case) is 8x8 pixels.
There are 8 BMP files:
Chars_Lower_8x8.bmp
Chars_Lower_16x16.bmp
Chars_Lower_24x24.bmp
Chars_Lower_32x32.bmp
Chars_Upper_8x8.bmp
Chars_Upper_16x16.bmp
Chars_Upper_24x24.bmp
Chars_Upper_32x32.bmp
The *Lower* files define the Commodore PET 4032 upper/lower case character
set & the *Upper* files define the Graphics/Uppercase character set.
My main question is: would I be better off using a TImageList?!? Can someone
please post sample code. Note: I tried to run the TImageList example program
for Lazarus... it compiles okay... but when run it does not find some of its
files (BMPs) in the Image sub-folder of the example program. e.g. it gets a
runtime error.
Note that this unit is based strongly on a unit from the Jedi SDL component,
sample unit for drawing bitmap fonts onto a graphic canvas.
At the moment I use statements like this to define the bitmap font (some of
the code is pasted below):
Best Regards & Happy Programming ;-)))
PEW
-----------------
const
Rects_low = 0;
Rects_high = 255;
type
// these lines "borrowed" from SDL.pas
SInt16 = smallint;
UInt16 = word;
// [ALVAROGP] TSDL_Rect converted to class, to avoid warnings
{
PSDL_Rect = ^TSDL_Rect;
TSDL_Rect = record
x, y: SInt16;
w, h: UInt16;
end;
}
TSDL_Rect = class
public
x, y: SInt16;
w, h: UInt16;
end;
// end lines from SDL
PFixedFont = ^TFixedFont;
TFixedFont = object
private
Image: TBitmap;
// [ALVAROGP] Rects redefined as array of class TSDL_Rect
{
Rects: array[Rects_low..Rects_high] of PSDL_Rect;
}
Rects: array[Rects_low..Rects_high] of TSDL_Rect;
public
LastCharacterDefined: byte;
TransparentColor,
TextColor,
BackgroundColor: Tcolor;
// this is used only when UseTransparentBackground is false
Char_width,
Char_height: byte; // default is 8x8
ReverseVideo: Boolean; // default =false
HorizontalGap: byte;
// Horizontal Gap between characters in Pixels -- default =1
UseTransparentBackground: Boolean;
constructor Initialize;
procedure LoadFont(const Fontfile: string);
procedure FreeUpAll;
destructor Finalize;
procedure WriteText2(x, y: integer; Txt: string; TextLength: cardinal;
var PaintBox1: TPaintBox);
end;
var
Font1: PFixedFont;
-----------------
[...snip...]
function PSDLRect(aLeft, aTop, aWidth, aHeight: integer): TSDL_Rect;
var
Rect: TSDL_Rect;
begin
Rect := TSDL_Rect.Create;
with Rect do
begin
x := aLeft;
y := aTop;
w := aWidth;
h := aHeight;
end;
Result := Rect;
end;
{---------------------------------------------------------}
constructor TFixedFont.Initialize;
begin
// defaults
LastCharacterDefined := 0; // PEW
Char_width := 8;
Char_height := 8;
HorizontalGap := 1; // 1 pixel by default
ReverseVideo := False; // off by default
end;
{---------------------------------------------------------}
procedure TFixedFont.LoadFont(const Fontfile: string);
var
i, x, y: integer;
begin
FreeUpAll;
if not fileexists(Fontfile) then
begin
showmessage('Error: font file does not exist: "' + fontfile + '"');
exit;
end;
Image := TBitmap.Create;
try
Image.LoadFromFile(Fontfile);
except
showmessage('Error: Exception occurred trying to load font file.');
exit;
end;
if Image = nil then
exit;
x := 0;
y := 0;
i := Rects_low;
repeat
if x >= Image.width then
break;
Rects[i] := PSDLRect(x, y, Char_width, Char_height);
LastCharacterDefined := i; // PEW
inc(i);
inc(x, Char_width);
if x >= Image.width then
begin
// font bitmap is a block of characters, so if we go past
// the end of bitmap, then go down to next row of characters.
x := 0;
inc(y, Char_height);
end;
until (y >= Image.height) or (i > Rects_High);
// Determine the transparent color
TransparentColor := Image.Canvas.Pixels[Rects[Rects_low].x +
Rects[Rects_low].w, 0];
UseTransparentBackground := true; // default
end;
{---------------------------------------------------------}
--
Fond Regards,
Peter Eric (aka 'pew') WILLIAMS
from Hobart, Tasmania, Australia -- phone (03) 6236-9675
My free website is: http://pewtas.googlepages.com (or)
http://tinyurl.com/yuyejs
(please visit my free website and let me know what you think about it.)
unit uFixedWidthFonts;
{$MODE Delphi}
interface
uses
graphics, ExtCtrls, SysUtils, Dialogs;
const
Rects_low = 0;
Rects_high = 255;
type
// these lines "borrowed" from SDL.pas
SInt16 = smallint;
UInt16 = word;
// [ALVAROGP] TSDL_Rect converted to class, to avoid warnings
{
PSDL_Rect = ^TSDL_Rect;
TSDL_Rect = record
x, y: SInt16;
w, h: UInt16;
end;
}
TSDL_Rect = class
public
x, y: SInt16;
w, h: UInt16;
end;
// end lines from SDL
PFixedFont = ^TFixedFont;
TFixedFont = object
private
Image: TBitmap;
// [ALVAROGP] Rects redefined as array of class TSDL_Rect
{
Rects: array[Rects_low..Rects_high] of PSDL_Rect;
}
Rects: array[Rects_low..Rects_high] of TSDL_Rect;
public
LastCharacterDefined: byte;
TransparentColor,
TextColor,
BackgroundColor: Tcolor;
// this is used only when UseTransparentBackground is false
Char_width,
Char_height: byte; // default is 8x8
ReverseVideo: Boolean; // default =false
HorizontalGap: byte;
// Horizontal Gap between characters in Pixels -- default =1
UseTransparentBackground: Boolean;
constructor Initialize;
procedure LoadFont(const Fontfile: string);
procedure FreeUpAll;
destructor Finalize;
procedure WriteText2(x, y: integer; Txt: string; TextLength: cardinal;
var PaintBox1: TPaintBox);
end;
var
Font1: PFixedFont;
implementation
// Use with caution! The procedure allocates memory for TSDL_Rect and return with its pointer.
// But you MUST free it after you don't need it anymore!!!
// this procedure pinched from SDL
// [ALVAROGP] PROCEDURE REWRITTEN BELOW TO AVOID WARNINGS
{
function PSDLRect(aLeft, aTop, aWidth, aHeight: integer): PSDL_Rect;
var
Rect: PSDL_Rect;
begin
New(Rect);
with Rect^ do
begin
x := aLeft;
y := aTop;
w := aWidth;
h := aHeight;
end;
Result := Rect;
end;
}
function PSDLRect(aLeft, aTop, aWidth, aHeight: integer): TSDL_Rect;
var
Rect: TSDL_Rect;
begin
Rect := TSDL_Rect.Create;
with Rect do
begin
x := aLeft;
y := aTop;
w := aWidth;
h := aHeight;
end;
Result := Rect;
end;
{---------------------------------------------------------}
constructor TFixedFont.Initialize;
begin
// defaults
LastCharacterDefined := 0; // PEW
Char_width := 8;
Char_height := 8;
HorizontalGap := 1; // 1 pixel by default
ReverseVideo := False; // off by default
end;
{---------------------------------------------------------}
procedure TFixedFont.LoadFont(const Fontfile: string);
var
i, x, y: integer;
begin
FreeUpAll;
if not fileexists(Fontfile) then
begin
showmessage('Error: font file does not exist: "' + fontfile + '"');
exit;
end;
Image := TBitmap.Create;
try
Image.LoadFromFile(Fontfile);
except
showmessage('Error: Exception occurred trying to load font file.');
exit;
end;
if Image = nil then
exit;
x := 0;
y := 0;
i := Rects_low;
repeat
if x >= Image.width then
break;
Rects[i] := PSDLRect(x, y, Char_width, Char_height);
LastCharacterDefined := i; // PEW
inc(i);
inc(x, Char_width);
if x >= Image.width then
begin
// font bitmap is a block of characters, so if we go past
// the end of bitmap, then go down to next row of characters.
x := 0;
inc(y, Char_height);
end;
until (y >= Image.height) or (i > Rects_High);
// Determine the transparent color
TransparentColor := Image.Canvas.Pixels[Rects[Rects_low].x +
Rects[Rects_low].w, 0];
UseTransparentBackground := true; // default
end;
{---------------------------------------------------------}
procedure TFixedFont.FreeUpAll;
var
i: integer;
begin
for i := Rects_low to Rects_high do
if Rects[i] <> nil then
// [ALVAROGP] Rects are not records any more
{
Dispose(Rects[i]);
}
Rects[i].Free;
if Image <> nil then
Image.Free;
end;
{---------------------------------------------------------}
destructor TFixedFont.Finalize;
begin
FreeUpAll;
end;
{---------------------------------------------------------}
// Draw a partial text in a single line without clipping x
procedure TFixedFont.WriteText2(x, y: integer; Txt: string; TextLength:
cardinal;
var PaintBox1: TPaintBox);
var
i: cardinal; // PEW
ch, px, py: integer;
begin
if (Image = nil) or (Txt = '') then
exit;
PaintBox1.Canvas.Lock;
i := 1;
while i <= TextLength do
begin
ch := ord(Txt[i]);
if (ch >= Rects_low) and (ch <= LastCharacterDefined) then
begin
// [ALVAROGP] Rects are not records any more
for px := 0 to Rects[ch].w - 1 do
// [ALVAROGP] Rects are not records any more
for py := 0 to Rects[ch].h - 1 do
if y + py < PaintBox1.Canvas.ClipRect.Left +
PaintBox1.Canvas.ClipRect.Bottom - PaintBox1.Canvas.ClipRect.Top
then
begin
if ReverseVideo then
begin
// reversed text
// [ALVAROGP] Rects are not records any more
if Image.Canvas.Pixels[Rects[ch].x + px, Rects[ch].y + py] =
TransparentColor then
PaintBox1.Canvas.Pixels[x + px, y + py] := TextColor
else if not UseTransparentBackground then
PaintBox1.Canvas.Pixels[x + px, y + py] := BackgroundColor;
end
else
begin
// normal text
// [ALVAROGP] Rects are not records any more
if Image.Canvas.Pixels[Rects[ch].x + px, Rects[ch].y + py] <>
TransparentColor then
PaintBox1.Canvas.Pixels[x + px, y + py] := TextColor
else if not UseTransparentBackground then
PaintBox1.Canvas.Pixels[x + px, y + py] := BackgroundColor;
end
end;
x := x + Rects[ch].w + HorizontalGap
end;
inc(i);
end;
PaintBox1.Canvas.Unlock;
//PaintBox1.invalidate;
end;
{---------------------------------------------------------}
end.
<<attachment: Chars_Lower_8x8.bmp>>
_______________________________________________ Lazarus mailing list [email protected] http://www.lazarus.freepascal.org/mailman/listinfo/lazarus
