unit fonts; {$MODE OBJFPC} {$M+} interface uses mipmaps, images, type_fixes; { TODO use fixed point? floating point? } // TODO avoid refcounting of the IFont by just using (and deriving from) TFont throughout. type // the only one TCharacterSet = (csUnicode); TTextDirection = (tdLeftToRight, tdRightToLeft, tdTopToBottom, tdBottomToTop); TGlyphPoint = record X : Integer; Y : Integer; IsOnCurve : Boolean; end; TGlyphPointArray = array of TGlyphPoint; TGlyphP = ^TGlyph; TCoordinate = TCardinal; // FIXME fractional coordinates? TGlyphBox = record Ascent : TCoordinate; LeftSideBearing : TCoordinate; AdvanceWidth : TCoordinate; __Reserved1 : TCoordinate; __Reserved2 : TCoordinate; __Reserved3 : TCoordinate; __Reserved4 : TCoordinate; __Reserved5 : TCoordinate; __Reserved6 : Pointer; end; TGlyphBoxArray = array of TGlyphBox; { this "class" has some very questionable optimizations so that it will have that last bit of speed since it's used in an inner loop. } TGlyph = object { faster. } Boxes : TGlyphBoxArray; // Boxes[0] is the bezier (non-bitmap) box. // FIXME vertical fonts? // FIXME log which font it is (the TFont); maybe here or else in the TFont itself... Bitmaps : TMipmap; // for bitmap glyph. // FIXME ComposeWithGlyph : TGlyphP; // if any. this only makes sense with bezier Points, that is, with non-bitmap glyphs. FIXME: add the transform matrix and scale etc. Points : TGlyphPointArray; PointsReferenceHeight : TCardinal; function AddBitmap(const aImage : IImage) : TCardinal; // returns index in "Boxes". destructor Done(); constructor Init(); end; TGlyphArray = array of TGlyph; // not neccessarily just one font, just an access interface for someone wanting to display some text (can also be a Fontset, why does the user care?). IFont = interface function GetGlyph(aCode : TCardinal) : TGlyphP{or nil}; function GetFallbackGlyph : TGlyphP; // not nil. end; const cFallbackGlyph : TGlyphP = nil; implementation uses sysutils; constructor TGlyph.Init(); begin //ComposeWithGlyph := nil; Bitmaps := nil; SetLength(Points, 0); PointsReferenceHeight := 1024; end; destructor TGlyph.Done(); begin // ComposeWithGlyph ? SetLength(Boxes, 0); SetLength(Points, 0); FreeAndNil(Bitmaps); end; function TGlyph.AddBitmap(const aImage : IImage) : TCardinal; // returns index in "Boxes". begin if not Assigned(Bitmaps) then Bitmaps := TMipmap.Create(); Result := Bitmaps.Add(aImage) + 1; if Length(Boxes) <= Result then SetLength(Boxes, Result + 1); end; initialization New(cFallbackGlyph, Init()); cFallbackGlyph^.Bitmaps := nil; SetLength(cFallbackGlyph^.Points, 0); finalization Dispose(cFallbackGlyph, Done()); end.