DEADSOFTWARE

FlexUI: added 8/14/16 winN/winN-prop fonts; removed horizontal wrapping
authorKetmar Dark <ketmar@ketmar.no-ip.org>
Tue, 3 Oct 2017 09:10:24 +0000 (12:10 +0300)
committerKetmar Dark <ketmar@ketmar.no-ip.org>
Tue, 3 Oct 2017 09:22:53 +0000 (12:22 +0300)
  proper horizontal wrapping with size calculations/constraints is not
  that easy; it makes the code way more complex, it never really worked,
  and i never used it. althrough it is a great feature to have (for
  proper windows resizing), it is better served by something like Yoga
  (huge and complex). but i want to have a simplistic layouter, suitable
  for common UI tasks, and not-so-complex layouts.

  maybe i'll add that wrapping feature later, but i'm not sure. it looks
  like i need a full-blown constraints solver for this feature, and i am
  not ready to migrate to Cassowary yet. ;-)

  tl;dr: removing horizontal wrapping allowed me to unify distribution
         code, made code smaller (by ~1/3), and more readable. the price
         is acceptable (for now).

src/flexui/fui_common.pas
src/flexui/fui_ctls.pas
src/flexui/fui_flexlay.pas
src/flexui/fui_gfx_gl.pas
src/flexui/fui_gfx_gl_fonts.inc

index 744ddff1bd71de3c59974e8e70b34aac3e263c92..0c809154051de215431d58616bb2a8d4bcf77b1e 100644 (file)
@@ -86,6 +86,8 @@ type
     function isOpaque (): Boolean; inline;
     function isTransparent (): Boolean; inline;
 
+    function toString (): AnsiString;
+
     // WARNING! This function does blending in RGB space, and RGB space is not linear!
     // alpha value of `self` doesn't matter
     // `aa` means: 255 for replace color, 0 for keep `self`
@@ -102,6 +104,8 @@ type
     function empty (): Boolean; inline; // invalid rects are empty too
     function valid (): Boolean; inline;
 
+    function toString (): AnsiString;
+
     // modifies this rect, so it won't be bigger than `r`
     // returns `false` if this rect becomes empty
     function intersect (constref r: TGxRect): Boolean; inline;
@@ -195,6 +199,9 @@ begin
   result.a := a;
 end;
 
+function TGxRGBA.toString (): AnsiString; begin result := formatstrf('rgba(%s,%s,%s,%s)', [r, g, b, a]); end;
+
+
 
 // ////////////////////////////////////////////////////////////////////////// //
 constructor TGxRect.Create (ax, ay, aw, ah: Integer); begin x := ax; y := ay; w := aw; h := ah; end;
@@ -207,6 +214,8 @@ begin
   result := intersectRect(x, y, w, h, r.x, r.y, r.w, r.h);
 end;
 
+function TGxRect.toString (): AnsiString; begin result := formatstrf('(%s,%s;%sx%s)', [x, y, w, h]); end;
+
 
 // ////////////////////////////////////////////////////////////////////////// //
 constructor TGxOfs.Create (axofs, ayofs: Integer); begin xofs := axofs; yofs := ayofs; end;
index 7969a2617ef52edbaeb113583ae4888d72052413..7f722fea97090a79a967d319758fefc3e020ea09 100644 (file)
@@ -106,6 +106,8 @@ type
 
     procedure calcFullClientSize ();
 
+    procedure drawFrame (gx, gy, resx, thalign: Integer; const text: AnsiString; dbl: Boolean);
+
   protected
     var savedClip: TGxRect; // valid only in `draw*()` calls
     //WARNING! do not call scissor functions outside `.draw*()` API!
@@ -121,8 +123,6 @@ type
     mMaxSize: TLaySize; // maximum size
     mFlex: Integer;
     mHoriz: Boolean;
-    mCanWrap: Boolean;
-    mLineStart: Boolean;
     mHGroup: AnsiString;
     mVGroup: AnsiString;
     mAlign: Integer;
@@ -143,9 +143,7 @@ type
     //procedure setMaxSize (const sz: TLaySize); inline; // max size; <0: set to some huge value
     function getFlex (): Integer; inline; // <=0: not flexible
     function isHorizBox (): Boolean; inline; // horizontal layout for children?
-    function canWrap (): Boolean; inline; // for horizontal boxes: can wrap children? for child: `false` means 'nonbreakable at *next* ctl'
     function noPad (): Boolean; inline; // ignore padding in box direction for this control
-    function isLineStart (): Boolean; inline; // `true` if this ctl should start a new line; ignored for vertical boxes
     function getAlign (): Integer; inline; // aligning in non-main direction: <0: left/up; 0: center; >0: right/down
     function getExpand (): Boolean; inline; // expanding in non-main direction: `true` will ignore align and eat all available space
     function getHGroup (): AnsiString; inline; // empty: not grouped
@@ -161,8 +159,6 @@ type
     property flMaxSize: TLaySize read mMaxSize write mMaxSize;
     property flPadding: TLaySize read mPadding write mPadding;
     property flHoriz: Boolean read mHoriz write mHoriz;
-    property flCanWrap: Boolean read mCanWrap write mCanWrap;
-    property flLineStart: Boolean read mLineStart write mLineStart;
     property flAlign: Integer read mAlign write mAlign;
     property flExpand: Boolean read mExpand write mExpand;
     property flHGroup: AnsiString read mHGroup write mHGroup;
@@ -373,17 +369,9 @@ type
 
     function parseProperty (const prname: AnsiString; par: TTextParser): Boolean; override;
 
-    procedure drawControl (gx, gy: Integer); override;
-  end;
-
-  TUIHLine = class(TUILine)
-  public
-    procedure AfterConstruction (); override; // so it will be correctly initialized when created from parser
-  end;
+    procedure layPrepare (); override; // called before registering control in layouter
 
-  TUIVLine = class(TUILine)
-  public
-    procedure AfterConstruction (); override; // so it will be correctly initialized when created from parser
+    procedure drawControl (gx, gy: Integer); override;
   end;
 
   // ////////////////////////////////////////////////////////////////////// //
@@ -890,14 +878,12 @@ begin
   actionCB := nil;
   // layouter interface
   //mDefSize := TLaySize.Create(64, uiContext.charHeight(' ')); // default size
-  mDefSize := TLaySize.Create(0, 0); // default size
+  mDefSize := TLaySize.Create(0, 0); // default size: hidden control
   mMaxSize := TLaySize.Create(-1, -1); // maximum size
   mPadding := TLaySize.Create(0, 0);
   mNoPad := false;
   mFlex := 0;
   mHoriz := true;
-  mCanWrap := false;
-  mLineStart := false;
   mHGroup := '';
   mVGroup := '';
   mStyleId := '';
@@ -1000,9 +986,7 @@ function TUIControl.getMaxSize (): TLaySize; inline; begin result := mLayMaxSize
 function TUIControl.getPadding (): TLaySize; inline; begin result := mPadding; end;
 function TUIControl.getFlex (): Integer; inline; begin result := mFlex; end;
 function TUIControl.isHorizBox (): Boolean; inline; begin result := mHoriz; end;
-function TUIControl.canWrap (): Boolean; inline; begin result := mCanWrap; end;
 function TUIControl.noPad (): Boolean; inline; begin result := mNoPad; end;
-function TUIControl.isLineStart (): Boolean; inline; begin result := mLineStart; end;
 function TUIControl.getAlign (): Integer; inline; begin result := mAlign; end;
 function TUIControl.getExpand (): Boolean; inline; begin result := mExpand; end;
 function TUIControl.getHGroup (): AnsiString; inline; begin result := mHGroup; end;
@@ -1019,14 +1003,23 @@ begin
   end;
   mWidth := asize.w;
   mHeight := asize.h;
+  if (mLayMaxSize.w >= 0) then mWidth := nmin(mWidth, mLayMaxSize.w);
+  if (mLayMaxSize.h >= 0) then mHeight := nmin(mHeight, mLayMaxSize.h);
 end;
 
 procedure TUIControl.layPrepare ();
 begin
   mLayDefSize := mDefSize;
-  mLayMaxSize := mMaxSize;
-  if (mLayMaxSize.w >= 0) then mLayMaxSize.w += mFrameWidth*2;
-  if (mLayMaxSize.h >= 0) then mLayMaxSize.h += mFrameHeight*2;
+  if (mLayDefSize.w <> 0) and (mLayDefSize.h <> 0) then
+  begin
+    mLayMaxSize := mMaxSize;
+    if (mLayMaxSize.w >= 0) then begin mLayDefSize.w += mFrameWidth*2; mLayMaxSize.w += mFrameWidth*2; end;
+    if (mLayMaxSize.h >= 0) then begin mLayDefSize.h += mFrameHeight*2; mLayMaxSize.h += mFrameHeight*2; end;
+  end
+  else
+  begin
+    mLayMaxSize := TLaySize.Create(0, 0);
+  end;
 end;
 
 
@@ -1267,8 +1260,6 @@ begin
   if (strEquCI1251(prname, 'padding')) then begin mPadding := parsePadding(par); exit; end;
   if (strEquCI1251(prname, 'nopad')) then begin mNoPad := true; exit; end;
   // flags
-  if (strEquCI1251(prname, 'wrap')) then begin mCanWrap := parseBool(par); exit; end;
-  if (strEquCI1251(prname, 'linestart')) then begin mLineStart := parseBool(par); exit; end;
   if (strEquCI1251(prname, 'expand')) then begin mExpand := parseBool(par); exit; end;
   // align
   if (strEquCI1251(prname, 'align')) then begin mAlign := parseAnyAlign(par); exit; end;
@@ -1490,7 +1481,7 @@ begin
     mParent.getDrawRect(gx, gy, wdt, hgt);
     if (wdt > 0) and (hgt > 0) then
     begin
-      if not intersectRect(gx, gy, wdt, hgt, cgx, cgy, mWidth, mHeight) then
+      if (not intersectRect(gx, gy, wdt, hgt, cgx, cgy, mWidth, mHeight)) then
       begin
         wdt := 0;
         hgt := 0;
@@ -1858,6 +1849,79 @@ end;
 
 
 // ////////////////////////////////////////////////////////////////////////// //
+procedure TUIControl.drawFrame (gx, gy, resx, thalign: Integer; const text: AnsiString; dbl: Boolean);
+var
+  cidx, tx, tw: Integer;
+begin
+  if (mFrameWidth < 1) or (mFrameHeight < 1) then exit;
+  cidx := getColorIndex;
+  uiContext.color := mFrameColor[cidx];
+  case mFrameHeight of
+    8:
+      begin
+        if dbl then
+        begin
+          uiContext.rect(gx+3, gy+3, mWidth-6, mHeight-6);
+          uiContext.rect(gx+5, gy+5, mWidth-10, mHeight-10);
+        end
+        else
+        begin
+          uiContext.rect(gx+4, gy+4, mWidth-8, mHeight-8);
+        end;
+      end;
+    14:
+      begin
+        if dbl then
+        begin
+          uiContext.rect(gx+3, gy+3+3, mWidth-6, mHeight-6-6);
+          uiContext.rect(gx+5, gy+5+3, mWidth-10, mHeight-10-6);
+        end
+        else
+        begin
+          uiContext.rect(gx+4, gy+4+3, mWidth-8, mHeight-8-6);
+        end;
+      end;
+    16:
+      begin
+        if dbl then
+        begin
+          uiContext.rect(gx+3, gy+3+4, mWidth-6, mHeight-6-8);
+          uiContext.rect(gx+5, gy+5+4, mWidth-10, mHeight-10-8);
+        end
+        else
+        begin
+          uiContext.rect(gx+4, gy+4+4, mWidth-8, mHeight-8-8);
+        end;
+      end;
+    else
+      begin
+        //TODO!
+        if dbl then
+        begin
+        end
+        else
+        begin
+        end;
+      end;
+  end;
+
+  // title
+  if (Length(text) > 0) then
+  begin
+    if (resx < 0) then resx := 0;
+    tw := uiContext.textWidth(text);
+    setScissor(mFrameWidth+resx, 0, mWidth-mFrameWidth*2-resx, mFrameHeight);
+         if (thalign < 0) then tx := gx+resx+mFrameWidth+2
+    else if (thalign > 0) then tx := gx+mWidth-mFrameWidth-1-tw
+    else tx := (gx+resx+mFrameWidth)+(mWidth-mFrameWidth*2-resx-tw) div 2;
+    uiContext.color := mBackColor[cidx];
+    uiContext.fillRect(tx-2, gy, tw+4, mFrameHeight);
+    uiContext.color := mFrameTextColor[cidx];
+    uiContext.drawText(tx, gy, text);
+  end;
+end;
+
+
 procedure TUIControl.draw ();
 var
   f: Integer;
@@ -1866,12 +1930,13 @@ var
   procedure resetScissor (fullArea: Boolean); inline;
   begin
     uiContext.clip := savedClip;
-    if (fullArea) then
+    if (fullArea) or ((mFrameWidth = 0) and (mFrameHeight = 0)) then
     begin
       setScissor(0, 0, mWidth, mHeight);
     end
     else
     begin
+      //writeln('frm: (', mFrameWidth, 'x', mFrameHeight, ')');
       setScissor(mFrameWidth, mFrameHeight, mWidth-mFrameWidth*2, mHeight-mFrameHeight*2);
     end;
   end;
@@ -1887,6 +1952,28 @@ begin
     resetScissor(false); // client area
     for f := 0 to High(mChildren) do mChildren[f].draw();
     resetScissor(true); // full area
+    if (self is TUISwitchBox) then
+    begin
+      uiContext.color := TGxRGBA.Create(255, 0, 0, 255);
+      //uiContext.fillRect(gx, gy, mWidth, mHeight);
+      //writeln('frm: (', mFrameWidth, 'x', mFrameHeight, '); sz=(', mWidth, 'x', mHeight, '); clip=', uiContext.clip.toString);
+    end;
+    if false and (mId = 'cbtest') then
+    begin
+      uiContext.color := TGxRGBA.Create(255, 127, 0, 96);
+      uiContext.fillRect(gx, gy, mWidth, mHeight);
+      if (mFrameWidth > 0) and (mFrameHeight > 0) then
+      begin
+        uiContext.color := TGxRGBA.Create(255, 255, 0, 96);
+        uiContext.fillRect(gx+mFrameWidth, gy+mFrameHeight, mWidth-mFrameWidth*2, mHeight-mFrameHeight*2);
+      end;
+    end
+    else if false and (self is TUISwitchBox) then
+    begin
+      uiContext.color := TGxRGBA.Create(255, 0, 0, 255);
+      uiContext.fillRect(gx, gy, mWidth, mHeight);
+      //writeln('frm: (', mFrameWidth, 'x', mFrameHeight, ')');
+    end;
     drawControlPost(gx, gy);
   finally
     uiContext.clip := savedClip;
@@ -2045,7 +2132,7 @@ begin
   inherited;
   mFitToScreen := true;
   mFrameWidth := 8;
-  mFrameHeight := 8;
+  mFrameHeight := uiContext.charHeight(#184);
   if (mWidth < mFrameWidth*2+uiContext.iconWinWidth(TGxContext.TWinIcon.Close)) then mWidth := mFrameWidth*2+uiContext.iconWinWidth(TGxContext.TWinIcon.Close);
   if (mHeight < mFrameHeight*2) then mHeight := mFrameHeight*2;
   if (Length(mTitle) > 0) then
@@ -2062,6 +2149,8 @@ begin
   mInClose := false;
   closeCB := nil;
   mCtl4Style := 'window';
+  mDefSize.w := nmax(1, mDefSize.w);
+  mDefSize.h := nmax(1, mDefSize.h);
 end;
 
 
@@ -2118,58 +2207,46 @@ begin
   uiContext.fillRect(gx, gy, mWidth, mHeight);
 end;
 
-
 procedure TUITopWindow.drawControlPost (gx, gy: Integer);
 var
   cidx: Integer;
-  tx, hgt, sbhgt, iwdt: Integer;
+  hgt, sbhgt, iwdt, ihgt: Integer;
 begin
   cidx := getColorIndex;
+  iwdt := uiContext.iconWinWidth(TGxContext.TWinIcon.Close);
   if (mDragScroll = TXMode.Drag) then
   begin
-    uiContext.color := mFrameColor[cidx];
-    uiContext.rect(gx+4, gy+4, mWidth-8, mHeight-8);
+    //uiContext.color := mFrameColor[cidx];
+    drawFrame(gx, gy, iwdt, 0, mTitle, false);
   end
   else
   begin
-    uiContext.color := mFrameColor[cidx];
-    uiContext.rect(gx+3, gy+3, mWidth-6, mHeight-6);
-    uiContext.rect(gx+5, gy+5, mWidth-10, mHeight-10);
+    ihgt := uiContext.iconWinHeight(TGxContext.TWinIcon.Close);
+    //uiContext.color := mFrameColor[cidx];
+    drawFrame(gx, gy, iwdt, 0, mTitle, true);
     // vertical scroll bar
     hgt := mHeight-mFrameHeight*2;
     if (hgt > 0) and (mFullSize.h > hgt) then
     begin
       //writeln(mTitle, ': height=', mHeight-mFrameHeight*2, '; fullsize=', mFullSize.toString);
       sbhgt := mHeight-mFrameHeight*2+2;
-      uiContext.fillRect(gx+mWidth-mFrameWidth+1, gy+7, mFrameWidth-3, sbhgt);
+      uiContext.fillRect(gx+mWidth-mFrameWidth+1, gy+mFrameHeight-1, mFrameWidth-3, sbhgt);
       hgt += mScrollY;
       if (hgt > mFullSize.h) then hgt := mFullSize.h;
       hgt := sbhgt*hgt div mFullSize.h;
       if (hgt > 0) then
       begin
-        setScissor(mWidth-mFrameWidth+1, 7, mFrameWidth-3, sbhgt);
-        uiContext.darkenRect(gx+mWidth-mFrameWidth+1, gy+7+hgt, mFrameWidth-3, sbhgt, 128);
+        setScissor(mWidth-mFrameWidth+1, mFrameHeight-1, mFrameWidth-3, sbhgt);
+        uiContext.darkenRect(gx+mWidth-mFrameWidth+1, gy+mFrameHeight-1+hgt, mFrameWidth-3, sbhgt, 128);
       end;
     end;
     // frame icon
-    iwdt := uiContext.iconWinWidth(TGxContext.TWinIcon.Close);
-    setScissor(mFrameWidth, 0, iwdt, 8);
+    setScissor(mFrameWidth, 0, iwdt, ihgt);
     uiContext.color := mBackColor[cidx];
-    uiContext.fillRect(gx+mFrameWidth, gy, iwdt, 8);
+    uiContext.fillRect(gx+mFrameWidth, gy, iwdt, ihgt);
     uiContext.color := mFrameIconColor[cidx];
     uiContext.drawIconWin(TGxContext.TWinIcon.Close, gx+mFrameWidth, gy, mInClose);
   end;
-  // title
-  if (Length(mTitle) > 0) then
-  begin
-    iwdt := uiContext.iconWinWidth(TGxContext.TWinIcon.Close);
-    setScissor(mFrameWidth+iwdt, 0, mWidth-mFrameWidth*2-iwdt, 8);
-    tx := (gx+iwdt)+((mWidth-iwdt)-uiContext.textWidth(mTitle)) div 2;
-    uiContext.color := mBackColor[cidx];
-    uiContext.fillRect(tx-3, gy, uiContext.textWidth(mTitle)+3+2, 8);
-    uiContext.color := mFrameTextColor[cidx];
-    uiContext.drawText(tx, gy, mTitle);
-  end;
   // shadow
   inherited drawControlPost(gx, gy);
 end;
@@ -2260,7 +2337,7 @@ begin
   begin
     if (ev.press) then
     begin
-      if (ly < 8) then
+      if (ly < mFrameHeight) then
       begin
         uiGrabCtl := self;
         if (lx >= mFrameWidth) and (lx < mFrameWidth+uiContext.iconWinWidth(TGxContext.TWinIcon.Close)) then
@@ -2357,6 +2434,7 @@ begin
   mCanFocus := false;
   mHAlign := -1; // left
   mCtl4Style := 'box';
+  mDefSize := TLaySize.Create(-1, -1);
 end;
 
 
@@ -2370,7 +2448,7 @@ end;
 procedure TUIBox.setHasFrame (v: Boolean);
 begin
   mHasFrame := v;
-  if (mHasFrame) then begin mFrameWidth := 8; mFrameHeight := 8; end else begin mFrameWidth := 0; mFrameHeight := 0; end;
+  if (mHasFrame) then begin mFrameWidth := 8; mFrameHeight := uiContext.charHeight(#184); end else begin mFrameWidth := 0; mFrameHeight := 0; end;
   if (mHasFrame) then mNoPad := true;
 end;
 
@@ -2420,26 +2498,29 @@ begin
   cidx := getColorIndex;
   uiContext.color := mBackColor[cidx];
   uiContext.fillRect(gx, gy, mWidth, mHeight);
-  if mHasFrame then
+  if (mHasFrame) then
   begin
     // draw frame
-    uiContext.color := mFrameColor[cidx];
-    uiContext.rect(gx+3, gy+3, mWidth-6, mHeight-6);
-  end;
-  // draw caption
-  if (Length(mCaption) > 0) then
+    drawFrame(gx, gy, 0, -1, mCaption, false);
+    //uiContext.color := mFrameColor[cidx];
+    //uiContext.rect(gx+3, gy+3, mWidth-6, mHeight-6);
+  end
+  else if (Length(mCaption) > 0) then
   begin
+    // draw caption
          if (mHAlign < 0) then xpos := 3
     else if (mHAlign > 0) then xpos := mWidth-mFrameWidth*2-uiContext.textWidth(mCaption)
     else xpos := (mWidth-mFrameWidth*2-uiContext.textWidth(mCaption)) div 2;
     xpos += gx+mFrameWidth;
 
-    setScissor(mFrameWidth+1, 0, mWidth-mFrameWidth-2, 8);
-    if mHasFrame then
+    setScissor(mFrameWidth+1, 0, mWidth-mFrameWidth-2, uiContext.textHeight(mCaption));
+    {
+    if (mHasFrame) then
     begin
       uiContext.color := mBackColor[cidx];
       uiContext.fillRect(xpos-3, gy, uiContext.textWidth(mCaption)+4, 8);
     end;
+    }
     uiContext.color := mFrameTextColor[cidx];
     uiContext.drawText(xpos, gy, mCaption);
   end;
@@ -2518,6 +2599,7 @@ begin
   mCanFocus := false;
   mNoPad := true;
   mCtl4Style := 'span';
+  mDefSize := TLaySize.Create(-1, -1);
 end;
 
 
@@ -2541,6 +2623,7 @@ begin
   mExpand := true;
   mCanFocus := false;
   mCtl4Style := 'line';
+  mDefSize := TLaySize.Create(-1, -1);
 end;
 
 
@@ -2551,6 +2634,23 @@ begin
 end;
 
 
+procedure TUILine.layPrepare ();
+begin
+  inherited layPrepare();
+  if (mParent <> nil) then mHoriz := not mParent.mHoriz;
+  if (mHoriz) then
+  begin
+    if (mLayDefSize.w < 0) then mLayDefSize.w := 1;
+    if (mLayDefSize.h < 0) then mLayDefSize.h := 7;
+  end
+  else
+  begin
+    if (mLayDefSize.w < 0) then mLayDefSize.w := 7;
+    if (mLayDefSize.h < 0) then mLayDefSize.h := 1;
+  end;
+end;
+
+
 procedure TUILine.drawControl (gx, gy: Integer);
 var
   cidx: Integer;
@@ -2562,24 +2662,6 @@ begin
 end;
 
 
-// ////////////////////////////////////////////////////////////////////////// //
-procedure TUIHLine.AfterConstruction ();
-begin
-  inherited;
-  mHoriz := true;
-  mDefSize.h := 7;
-end;
-
-
-// ////////////////////////////////////////////////////////////////////////// //
-procedure TUIVLine.AfterConstruction ();
-begin
-  inherited;
-  mHoriz := false;
-  mDefSize.w := 7;
-end;
-
-
 // ////////////////////////////////////////////////////////////////////////// //
 procedure TUIStaticText.AfterConstruction ();
 begin
@@ -2590,7 +2672,6 @@ begin
   mHoriz := true; // nobody cares
   mHeader := false;
   mLine := false;
-  mDefSize.h := uiContext.charHeight(' ');
   mCtl4Style := 'static';
 end;
 
@@ -2685,7 +2766,6 @@ begin
   mHAlign := -1;
   mVAlign := 0;
   mCanFocus := false;
-  mDefSize := TLaySize.Create(uiContext.textWidth(mText), uiContext.textHeight(mText));
   mCtl4Style := 'label';
   mLinkId := '';
 end;
@@ -2943,7 +3023,7 @@ begin
   mVAlign := 0;
   mCanFocus := true;
   mIcon := TGxContext.TMarkIcon.Checkbox;
-  mDefSize := TLaySize.Create(uiContext.textWidth(mText)+3+uiContext.iconMarkWidth(mIcon), uiContext.iconMarkHeight(mIcon));
+  mDefSize := TLaySize.Create(uiContext.textWidth(mText)+3+uiContext.iconMarkWidth(mIcon), nmax(uiContext.iconMarkHeight(mIcon), uiContext.textHeight(mText)));
   mCtl4Style := 'switchbox';
   mChecked := false;
   mBoolVar := @mChecked;
@@ -2965,7 +3045,7 @@ end;
 procedure TUISwitchBox.setText (const s: AnsiString);
 begin
   inherited setText(s);
-  mDefSize := TLaySize.Create(uiContext.textWidth(mText)+3+uiContext.iconMarkWidth(mIcon), uiContext.iconMarkHeight(mIcon));
+  mDefSize := TLaySize.Create(uiContext.textWidth(mText)+3+uiContext.iconMarkWidth(mIcon), nmax(uiContext.iconMarkHeight(mIcon), uiContext.textHeight(mText)));
 end;
 
 
@@ -3000,36 +3080,45 @@ end;
 
 procedure TUISwitchBox.drawControl (gx, gy: Integer);
 var
-  xpos, ypos: Integer;
+  xpos, ypos, iwdt, dy: Integer;
   cidx: Integer;
 begin
   cidx := getColorIndex;
 
+  iwdt := uiContext.iconMarkWidth(mIcon);
        if (mHAlign < 0) then xpos := 0
-  else if (mHAlign > 0) then xpos := mWidth-(uiContext.textWidth(mText)+3+uiContext.iconMarkWidth(mIcon))
-  else xpos := (mWidth-(uiContext.textWidth(mText)+3+uiContext.iconMarkWidth(mIcon))) div 2;
+  else if (mHAlign > 0) then xpos := mWidth-(uiContext.textWidth(mText)+3+iwdt)
+  else xpos := (mWidth-(uiContext.textWidth(mText)+3+iwdt)) div 2;
 
        if (mVAlign < 0) then ypos := 0
-  else if (mVAlign > 0) then ypos := mHeight-uiContext.iconMarkHeight(mIcon)
-  else ypos := (mHeight-uiContext.iconMarkHeight(mIcon)) div 2;
+  else if (mVAlign > 0) then ypos := mHeight-uiContext.textHeight(mText)
+  else ypos := (mHeight-uiContext.textHeight(mText)) div 2;
 
   uiContext.color := mBackColor[cidx];
   uiContext.fillRect(gx, gy, mWidth, mHeight);
 
   uiContext.color := mSwitchColor[cidx];
-  uiContext.drawIconMark(mIcon, gx, gy, checked);
-
-       if (mVAlign < 0) then ypos := 0
-  else if (mVAlign > 0) then ypos := mHeight-uiContext.textHeight(mText)
-  else ypos := (mHeight-uiContext.textHeight(mText)) div 2;
+  if (uiContext.iconMarkHeight(mIcon) < uiContext.textHeight(mText)) then
+  begin
+    case uiContext.textHeight(mText) of
+      14: dy := 2;
+      16: dy := 3;
+      else dy := 1;
+    end;
+    uiContext.drawIconMark(mIcon, gx, gy+ypos+uiContext.textHeight(mText)-uiContext.iconMarkHeight(mIcon)-dy, checked);
+  end
+  else
+  begin
+    uiContext.drawIconMark(mIcon, gx, gy, checked);
+  end;
 
   uiContext.color := mTextColor[cidx];
-  uiContext.drawText(gx+xpos+3+uiContext.iconMarkWidth(mIcon), gy+ypos, mText);
+  uiContext.drawText(gx+xpos+3+iwdt, gy+ypos, mText);
 
   if (mHotChar <> #0) and (mHotChar <> ' ') then
   begin
     uiContext.color := mHotColor[cidx];
-    uiContext.drawChar(gx+xpos+3+uiContext.iconMarkWidth(mIcon)+mHotOfs, gy+ypos, mHotChar);
+    uiContext.drawChar(gx+xpos+3+iwdt+mHotOfs, gy+ypos, mHotChar);
   end;
 end;
 
@@ -3164,8 +3253,7 @@ initialization
   registerCtlClass(TUIHBox, 'hbox');
   registerCtlClass(TUIVBox, 'vbox');
   registerCtlClass(TUISpan, 'span');
-  registerCtlClass(TUIHLine, 'hline');
-  registerCtlClass(TUIVLine, 'vline');
+  registerCtlClass(TUILine, 'line');
   registerCtlClass(TUITextLabel, 'label');
   registerCtlClass(TUIStaticText, 'static');
   registerCtlClass(TUIButton, 'button');
index fb470c4fee5a71a41fd198e1b251b8466841ea3a..a941f554dda7c9a76fe95319c90721b4113ebcb3 100644 (file)
@@ -27,9 +27,7 @@ ControlT:
   function getMaxSize (): TLaySize; // max size; <0: set to some huge value
   function getFlex (): Integer; // <=0: not flexible
   function isHorizBox (): Boolean; // horizontal layout for children?
-  function canWrap (): Boolean; // for horizontal boxes: can wrap children? for child: `false` means 'nonbreakable at *next* ctl'
   function noPad (): Boolean; // ignore padding in box direction for this control
-  function isLineStart (): Boolean; // `true` if this ctl should start a new line; ignored for vertical boxes
   function getAlign (): Integer; // aligning in non-main direction: <0: left/up; 0: center; >0: right/down
   function getExpand (): Boolean; // expanding in non-main direction: `true` will ignore align and eat all available space
   procedure setActualSizePos (constref apos: TLayPos; constref asize: TLaySize);
@@ -58,14 +56,10 @@ type
     // flags
     const
       FlagHorizBox = LongWord(1) shl 0; // horizontal layout for children
-      FlagLineStart = LongWord(1) shl 1;
-      FlagLineCanWrap = LongWord(1) shl 2;
-      FlagNoPad = LongWord(1) shl 3;
+      FlagNoPad = LongWord(1) shl 1;
+      FlagExpand = LongWord(1) shl 2;
       // internal
-      FlagLineDidWrap = LongWord(1) shl 8; // will be set when line was wrapped
-      FlagInGroup = LongWord(1) shl 9; // set if this control is a member of any group
-      FlagExpand = LongWord(1) shl 10;
-      FlagLineFirst = LongWord(1) shl 11;
+      FlagInGroup = LongWord(1) shl 8; // set if this control is a member of any group
 
   private
     type
@@ -76,9 +70,9 @@ type
         tempFlex: Integer;
         flags: LongWord; // see above
         aligndir: Integer;
-        startsize: TLaySize; // current
-        desiredsize: TLaySize;
-        maxsize: TLaySize;
+        startsize: TLaySize; // original size
+        desiredsize: TLaySize; // current size
+        maxsize: TLaySize; // current maximum size
         margins: TLayMargins; // can never be negative
         padding: TLaySize;
         desiredpos: TLayPos;
@@ -87,18 +81,11 @@ type
         firstChild: LayControlIdx; // = -1;
         nextSibling: LayControlIdx; // = -1;
 
-      private
-        function getDidWrap (): Boolean; inline;
-        procedure setDidWrap (v: Boolean); inline;
-
       public
         procedure initialize (); inline;
 
         function horizBox (): Boolean; inline;
-        function lineStart (): Boolean; inline;
-        function canWrap (): Boolean; inline;
         function inGroup (): Boolean; inline;
-        function firstInLine (): Boolean; inline;
         function noPad (): Boolean; inline;
 
         function getExpand (): Boolean; inline;
@@ -110,8 +97,9 @@ type
         function alignBottom (): Boolean; inline;
         function alignCenter (): Boolean; inline;
 
+        function visible (): Boolean; inline;
+
       public
-        property didWrap: Boolean read getDidWrap write setDidWrap;
         property expand: Boolean read getExpand write setExpand;
       end;
 
@@ -127,28 +115,21 @@ type
   private
     ctlist: TLayCtlArray;
     groups: array[0..1] of TLayGrpArray; // horiz, vert
-
-    firstTime: Boolean;
     groupElementChanged: Boolean;
-    wrappingChanged: Boolean;
 
   private
-    procedure fixFlags (cidx: LayControlIdx);
+    procedure firstTimeSetup (cidx: LayControlIdx);
     procedure doChildren (parent: LayControlIdx; child: ControlT);
     procedure appendToGroup (const gname: AnsiString;cidx: LayControlIdx;gidx: Integer);
     procedure setupGroups ();
 
-    // this also sets `tempFlex`
-    procedure calcMaxSizeInternal (cidx: LayControlIdx);
-
-    procedure fixLine (me: PLayControl; i0, i1: LayControlIdx; ypad: Integer; var cury: Integer; var spaceLeft: Single);
+    procedure distributeChildren (boxidx: LayControlIdx; maindir: Integer);
     // do box layouting; call `layBox()` recursively if necessary
     procedure layBox (boxidx: LayControlIdx);
 
     procedure firstPass ();
     procedure secondPass ();
     procedure thirdPass ();
-    procedure fourthPass ();
 
     procedure dumpList (cidx: LayControlIdx; indent: Integer);
 
@@ -159,8 +140,9 @@ type
         ctls: TLayCtlArray;
         cur: Integer;
         first: Boolean;
+        onlyVisible: Boolean;
       public
-        constructor Create (constref actls: TLayCtlArray; acur: Integer);
+        constructor Create (constref actls: TLayCtlArray; acur: Integer; aonlyvis: Boolean);
         function moveNext (): Boolean; inline;
         function getCurrent (): PLayControl; inline;
         function getEnumerator (): TChildrenEnumerator; inline;
@@ -178,6 +160,7 @@ type
     procedure setup (root: ControlT);
 
     function forChildren (cidx: LayControlIdx): TChildrenEnumerator; inline;
+    function forVisibleChildren (cidx: LayControlIdx): TChildrenEnumerator; inline;
 
     procedure layout ();
 
@@ -202,15 +185,9 @@ begin
 end;
 
 function TFlexLayouterBase.TLayControl.horizBox (): Boolean; inline; begin result := ((flags and FlagHorizBox) <> 0); end;
-function TFlexLayouterBase.TLayControl.lineStart (): Boolean; inline; begin result := ((flags and FlagLineStart) <> 0); end;
-function TFlexLayouterBase.TLayControl.canWrap (): Boolean; inline; begin result := ((flags and FlagLineCanWrap) <> 0); end;
 function TFlexLayouterBase.TLayControl.inGroup (): Boolean; inline; begin result := ((flags and FlagInGroup) <> 0); end;
-function TFlexLayouterBase.TLayControl.firstInLine (): Boolean; inline; begin result := ((flags and FlagLineFirst) <> 0); end;
 function TFlexLayouterBase.TLayControl.noPad (): Boolean; inline; begin result := ((flags and FlagNoPad) <> 0); end;
 
-function TFlexLayouterBase.TLayControl.getDidWrap (): Boolean; inline; begin result := ((flags and FlagLineDidWrap) <> 0); end;
-procedure TFlexLayouterBase.TLayControl.setDidWrap (v: Boolean); inline; begin if (v) then flags := flags or FlagLineDidWrap else flags := flags and (not FlagLineDidWrap); end;
-
 function TFlexLayouterBase.TLayControl.getExpand (): Boolean; inline; begin result := ((flags and FlagExpand) <> 0); end;
 procedure TFlexLayouterBase.TLayControl.setExpand (v: Boolean); inline; begin if (v) then flags := flags or FlagExpand else flags := flags and (not FlagExpand); end;
 
@@ -220,27 +197,38 @@ function TFlexLayouterBase.TLayControl.alignRight (): Boolean; inline; begin res
 function TFlexLayouterBase.TLayControl.alignBottom (): Boolean; inline; begin result := (aligndir > 0); end;
 function TFlexLayouterBase.TLayControl.alignCenter (): Boolean; inline; begin result := (aligndir = 0); end;
 
+function TFlexLayouterBase.TLayControl.visible (): Boolean; inline;
+begin
+  result := (startsize.w <> 0) or (startsize.h <> 0);
+end;
+
 
 // ////////////////////////////////////////////////////////////////////////// //
-constructor TFlexLayouterBase.TChildrenEnumerator.Create (constref actls: TLayCtlArray; acur: Integer);
+constructor TFlexLayouterBase.TChildrenEnumerator.Create (constref actls: TLayCtlArray; acur: Integer; aonlyvis: Boolean);
 begin
   ctls := actls;
   cur := acur;
   first := true;
+  onlyVisible := aonlyvis;
 end;
 
 function TFlexLayouterBase.TChildrenEnumerator.moveNext (): Boolean; inline;
 begin
-  if first then
-  begin
-    if (cur >= 0) and (cur < Length(ctls)) then cur := ctls[cur].firstChild else cur := -1;
-    first := false;
-  end
-  else
+  while true do
   begin
-    cur := ctls[cur].nextSibling;
+    if first then
+    begin
+      if (cur >= 0) and (cur < Length(ctls)) then cur := ctls[cur].firstChild else cur := -1;
+      first := false;
+    end
+    else
+    begin
+      cur := ctls[cur].nextSibling;
+    end;
+    result := (cur >= 0);
+    if (not result) or (not onlyVisible) then break;
+    if (ctls[cur].visible) then break;
   end;
-  result := (cur >= 0);
 end;
 
 function TFlexLayouterBase.TChildrenEnumerator.getCurrent (): PLayControl; inline;
@@ -260,10 +248,7 @@ begin
   ctlist := nil;
   groups[0] := nil;
   groups[1] := nil;
-
-  firstTime := false;
   groupElementChanged := false;
-  wrappingChanged := false;
 end;
 
 
@@ -276,7 +261,12 @@ end;
 
 function TFlexLayouterBase.forChildren (cidx: LayControlIdx): TChildrenEnumerator; inline;
 begin
-  result := TChildrenEnumerator.Create(ctlist, cidx);
+  result := TChildrenEnumerator.Create(ctlist, cidx, false);
+end;
+
+function TFlexLayouterBase.forVisibleChildren (cidx: LayControlIdx): TChildrenEnumerator; inline;
+begin
+  result := TChildrenEnumerator.Create(ctlist, cidx, true);
 end;
 
 
@@ -288,22 +278,6 @@ begin
 end;
 
 
-procedure TFlexLayouterBase.fixFlags (cidx: LayControlIdx);
-var
-  lc: PLayControl;
-begin
-  assert((cidx >= 0) and (cidx < Length(ctlist)));
-  lc := @ctlist[cidx];
-  //lc.flags := 0;
-  if (lc.ctl.isHorizBox) then lc.flags := lc.flags or FlagHorizBox;
-  if (lc.ctl.isLineStart) then lc.flags := lc.flags or FlagLineStart;
-  if (lc.ctl.canWrap) then lc.flags := lc.flags or FlagLineCanWrap;
-  if (lc.ctl.getExpand) then lc.flags := lc.flags or FlagExpand;
-  if (lc.ctl.noPad) then lc.flags := lc.flags or FlagNoPad;
-  lc.aligndir := lc.ctl.getAlign;
-end;
-
-
 procedure TFlexLayouterBase.doChildren (parent: LayControlIdx; child: ControlT);
 var
   cidx: LayControlIdx = -1;
@@ -314,6 +288,7 @@ begin
   while (child <> nil) do
   begin
     child.layPrepare;
+    //if (msz.w = 0) or (msz.h = 0) then continue; // hidden controls will have zero maxsize, so skip 'em
     SetLength(ctlist, Length(ctlist)+1);
     lc := @ctlist[High(ctlist)];
     lc.initialize();
@@ -321,8 +296,6 @@ begin
     begin
       cidx := LayControlIdx(High(ctlist));
       ctlist[parent].firstChild := cidx;
-      // first child is always linestart
-      lc.flags := lc.flags or FlagLineStart or FlagLineFirst;
     end
     else
     begin
@@ -332,7 +305,6 @@ begin
     lc.myidx := cidx;
     lc.ctl := child;
     lc.parent := parent;
-    fixFlags(cidx);
     doChildren(cidx, child.firstChild);
     child := child.nextSibling;
   end;
@@ -390,8 +362,6 @@ begin
     ctlist[0].initialize();
     ctlist[0].myidx := 0;
     ctlist[0].ctl := root;
-    fixFlags(0);
-    ctlist[0].flags := ctlist[0].flags or FlagLineStart or FlagLineFirst;
     doChildren(0, root.firstChild);
     setupGroups();
   except
@@ -401,218 +371,158 @@ begin
 end;
 
 
-// this also sets `tempFlex`
-procedure TFlexLayouterBase.calcMaxSizeInternal (cidx: LayControlIdx);
+procedure TFlexLayouterBase.firstTimeSetup (cidx: LayControlIdx);
 var
-  lc, c: PLayControl;
-  msz: TLaySize;
-  negw, negh: Boolean;
-  zerow: Boolean;
-  curwdt, curhgt, totalhgt: Integer;
-  doWrap: Boolean;
-  xpad, ypad: Integer;
-  realpad: Integer;
-  dopad: Boolean = false;
+  lc: PLayControl;
 begin
-  if (cidx < 0) or (cidx >= Length(ctlist)) then exit;
-
+  assert((cidx >= 0) and (cidx < Length(ctlist)));
   lc := @ctlist[cidx];
-  msz := lc.ctl.getMaxSize;
-  negw := (lc.startsize.w < 0);
-  negh := (lc.startsize.h < 0);
-  zerow := (lc.startsize.w = 0);
-
+  lc.flags := 0;
+  if (lc.ctl.isHorizBox) then lc.flags := lc.flags or FlagHorizBox;
+  if (lc.ctl.getExpand) then lc.flags := lc.flags or FlagExpand;
+  if (lc.ctl.noPad) then lc.flags := lc.flags or FlagNoPad;
+  lc.aligndir := lc.ctl.getAlign;
+  lc.startsize := lc.ctl.getDefSize;
+  //lc.startsize.w := nmax(0, lc.startsize.w);
+  //lc.startsize.h := nmax(0, lc.startsize.h);
+  lc.margins := lc.ctl.getMargins;
+  lc.margins.left := nmax(0, lc.margins.left);
+  lc.margins.top := nmax(0, lc.margins.top);
+  lc.margins.right := nmax(0, lc.margins.right);
+  lc.margins.bottom := nmax(0, lc.margins.bottom);
+  lc.padding := lc.ctl.getPadding;
+  lc.padding.w := nmax(0, lc.padding.w);
+  lc.padding.h := nmax(0, lc.padding.h);
+  lc.maxsize := TLaySize.Create(-1, -1);
+  if (lc.maxsize.w >= 0) then lc.startsize.w := nmin(lc.maxsize.w, lc.startsize.w);
+  if (lc.maxsize.h >= 0) then lc.startsize.h := nmin(lc.maxsize.h, lc.startsize.h);
+  lc.desiredsize := lc.startsize;
   lc.tempFlex := lc.ctl.getFlex;
-
-  for c in forChildren(cidx) do calcMaxSizeInternal(c.myidx);
-
-  if (lc.horizBox) then
-  begin
-    // horizontal boxes
-    if (negw) then lc.tempFlex := 0; // size is negative: don't expand
-    curwdt := lc.margins.horiz;
-    curhgt := 0;
-    totalhgt := lc.margins.vert;
-    xpad := nmax(0, lc.padding.w);
-    ypad := 0;
-    for c in forChildren(cidx) do
-    begin
-      if (dopad) then realpad := xpad else realpad := 0;
-      // new line?
-      doWrap := (not c.firstInLine) and (c.lineStart);
-      // need to wrap?
-      if (not doWrap) and (not zerow) and (not negw) and (lc.canWrap) and (c.canWrap) and (msz.w > 0) and (curwdt+c.startsize.w+realpad > lc.startsize.w) then doWrap := true;
-      if (doWrap) then
-      begin
-        totalhgt += curhgt;
-        if (lc.startsize.w < curwdt) then lc.startsize.w := curwdt;
-        curwdt := 0;
-        curhgt := 0;
-        ypad := nmax(0, lc.padding.h);
-        realpad := 0;
-      end;
-      curwdt += c.startsize.w+realpad;
-      if (curhgt < c.startsize.h+ypad) then curhgt := c.startsize.h+ypad;
-      dopad := (xpad > 0) and (not lc.noPad);
-    end;
-    //writeln('00: ', cidx, ': totalhgt=', totalhgt);
-    totalhgt += curhgt;
-    //writeln('01: ', cidx, ': totalhgt=', totalhgt);
-    if (lc.startsize.w < curwdt) then lc.startsize.w := curwdt;
-    if (lc.startsize.h < totalhgt) then lc.startsize.h := totalhgt;
-  end
-  else
-  begin
-    // vertical boxes
-    if (negh) then lc.tempFlex := 0; // size is negative: don't expand
-    curhgt := lc.margins.vert;
-    ypad := nmax(0, lc.padding.h);
-    for c in forChildren(cidx) do
-    begin
-      if (lc.startsize.w < c.startsize.w+lc.margins.horiz) then lc.startsize.w := c.startsize.w+lc.margins.horiz;
-      curhgt += c.startsize.h;
-      if (dopad) then curhgt += ypad;
-      dopad := (not c.noPad);
-    end;
-    if (lc.startsize.h < curhgt) then lc.startsize.h := curhgt;
-  end;
-  if (lc.startsize.w < 0) then lc.startsize.w := 0;
-  if (lc.startsize.h < 0) then lc.startsize.h := 0;
-  {
-  lc.maxsize := msz;
-  if (lc.maxsize.w < lc.startsize.w) then begin if (lc.maxsize.w >= 0) then lc.maxsize.w := lc.startsize.w; end;
-  if (lc.maxsize.h < lc.startsize.h) then begin if (lc.maxsize.h >= 0) then lc.maxsize.h := lc.startsize.h; end;
-  }
-  if (msz.w < 0) then msz.w := lc.startsize.w;
-  if (msz.h < 0) then msz.h := lc.startsize.h;
-  lc.maxsize := msz;
 end;
 
 
 procedure TFlexLayouterBase.firstPass ();
 var
-  f, c: Integer;
-  needRecalcMaxSize: Boolean;
+  f: Integer;
   gtype: Integer;
-  grp: PLayGroup;
-  maxsz: Integer;
-  cidx: LayControlIdx;
-  ct: PLayControl;
 begin
-  // reset all 'laywrap' flags for controls, set initial 'startsize'
-  for f := 0 to High(ctlist) do
-  begin
-    ctlist[f].didWrap := false;
-    ctlist[f].startsize := ctlist[f].ctl.getDefSize;
-    ctlist[f].margins := ctlist[f].ctl.getMargins;
-    ctlist[f].padding := ctlist[f].ctl.getPadding;
-  end;
-  // setup sizes
-  calcMaxSizeInternal(0); // this also sets `tempFlex`
-  //writeln('=== calculated max size (0) ==='); dump();
-  // find max size for group, adjust 'startsize' controls to group max size
-  needRecalcMaxSize := false;
+  groupElementChanged := false;
+  for f := 0 to High(ctlist) do firstTimeSetup(f);
+  // if we have any groups, set "group element changed" flag, so third pass will fix 'em
   for gtype := 0 to 1 do
   begin
-    for f := 0 to High(groups[gtype]) do
+    if (Length(groups[gtype]) > 0) then
     begin
-      grp := @groups[gtype][f];
-      maxsz := 0;
-      for c := 0 to High(grp.ctls) do
-      begin
-        cidx := grp.ctls[c];
-        ct := @ctlist[cidx];
-        if (maxsz < ct.startsize[gtype]) then maxsz := ct.startsize[gtype];
-      end;
-      for c := 0 to High(grp.ctls) do
-      begin
-        cidx := grp.ctls[c];
-        ct := @ctlist[cidx];
-        if (maxsz <> ct.startsize[gtype]) then
-        begin
-          needRecalcMaxSize := true;
-          ct.startsize[gtype] := maxsz;
-        end;
-      end;
+      groupElementChanged := true;
+      break;
     end;
   end;
-  // recalc maxsize if necessary
-  if (needRecalcMaxSize) then calcMaxSizeInternal(0);
-  // set "desired size" to "start size"
-  for f := 0 to High(ctlist) do ctlist[f].desiredsize := ctlist[f].startsize;
-  // set flags
-  firstTime := true;
-  //writeln('=== calculated max size (final) ==='); dump();
 end;
 
 
-procedure TFlexLayouterBase.fixLine (me: PLayControl; i0, i1: LayControlIdx; ypad: Integer; var cury: Integer; var spaceLeft: Single);
+procedure TFlexLayouterBase.distributeChildren (boxidx: LayControlIdx; maindir: Integer);
 var
+  me, lc: PLayControl;
+  suppdir: Integer;
+  marg0, marg1, margtotal: Integer;
+  marg0Op, marg1Op, margtotalOp: Integer;
   flexTotal: Integer = 0; // total sum of flex fields
-  flexBoxCount: Integer = 0; // number of boxes
-  curx: Integer;
-  lc: PLayControl;
-  osz: TLaySize;
+  spaceLeft: Integer = 0;
+  dopad: Boolean = false;
+  prevpad: Boolean = false;
+  maxdim: Integer = 0;
+  curpos: Integer;
   toadd: Integer;
-  sti0: Integer;
-  lineh: Integer;
-  xpad: Integer;
+  pad: Integer;
+  osz: TLaySize;
 begin
-  if (ypad < 0) then ypad := 0;
-  curx := me.margins.left;
-  sti0 := i0;
-  // calc minimal line height, count flexboxes
-  lineh := 0;
-  while (i0 <> i1) do
+  assert((boxidx >= 0) and (boxidx < Length(ctlist)));
+  assert((maindir = 0) or (maindir = 1));
+  // cache some parameters
+  me := @ctlist[boxidx];
+  suppdir := 1-maindir;
+  if (maindir = 0) then
   begin
-    lc := @ctlist[i0];
-    lineh := nmax(lineh, lc.startsize.h+ypad);
-    if (lc.tempFlex > 0) then begin flexTotal += lc.tempFlex; flexBoxCount += 1; end;
-    i0 := lc.nextSibling;
+    marg0 := me.margins.left;
+    marg1 := me.margins.right;
+    marg0Op := me.margins.top;
+    marg1Op := me.margins.bottom;
+  end
+  else
+  begin
+    marg0 := me.margins.top;
+    marg1 := me.margins.bottom;
+    marg0Op := me.margins.left;
+    marg1Op := me.margins.right;
+  end;
+  margtotal := marg0+marg1;
+  margtotalOp := marg0Op+marg1Op;
+  // horizontal boxes
+  pad := nmax(0, me.padding[maindir]);
+  // calc required space, count flexes
+  for lc in forVisibleChildren(boxidx) do
+  begin
+    if (lc.tempFlex > 0) then flexTotal += lc.tempFlex;
+    spaceLeft += nmax(0, lc.desiredsize[maindir]);
+    // insert padding if both current and previous children allow padding
+    dopad := (not lc.noPad);
+    if (prevpad) and (dopad) then spaceLeft += pad;
+    prevpad := dopad;
+    maxdim := nmax(maxdim, lc.desiredsize[suppdir]);
   end;
-  // distribute space, expand/align
-  xpad := nmax(0, me.padding.w);
-  i0 := sti0;
-  while (i0 <> i1) do
+  // add margins
+  spaceLeft += margtotal;
+  maxdim += margtotalOp;
+  // fix box size
+  me.desiredsize[maindir] := nmax(spaceLeft, me.desiredsize[maindir]);
+  me.desiredsize[suppdir] := nmax(maxdim, me.desiredsize[suppdir]);
+  // calculate free space
+  spaceLeft := me.desiredsize[maindir]-spaceLeft;
+  // distribute children
+  dopad := false;
+  prevpad := false;
+  curpos := marg0;
+  for lc in forVisibleChildren(boxidx) do
   begin
-    lc := @ctlist[i0];
     osz := lc.desiredsize;
-    lc.desiredsize := lc.startsize;
-    lc.desiredpos.x := curx;
-    lc.desiredpos.y := cury;
-    curx += lc.desiredsize.w;
-    if (xpad > 0) and (not lc.noPad) then curx += xpad;
+    // main direction
+    // insert padding if both current and previous children allow padding
+    dopad := (not lc.noPad);
+    if (prevpad) and (dopad) then curpos += pad;
+    prevpad := dopad;
+    lc.desiredpos[maindir] := curpos;
+    if (lc.desiredsize[maindir] < 0) then lc.desiredsize[maindir] := 0;
+    curpos += lc.desiredsize[maindir];
     // fix flexbox size
-    if (lc.tempFlex > 0) and (spaceLeft > 0) then
+    //writeln(':lcidx=', lc.myidx, '; tempFlex=', lc.tempFlex, '; spaceLeft=', spaceLeft);
+    if (spaceLeft > 0) and (lc.tempFlex > 0) then
     begin
       toadd := trunc(spaceLeft*lc.tempFlex/flexTotal+0.5);
       if (toadd > 0) then
       begin
         // size changed
-        lc.desiredsize.w += toadd;
-        curx += toadd;
         // compensate (crudely) rounding errors
-        if (curx > me.desiredsize.w-me.margins.horiz) then begin lc.desiredsize.w -= 1; curx -= 1; end;
-        // relayout children
-        layBox(lc.firstChild);
+        if (curpos+toadd > me.desiredsize[maindir]-margtotal) then toadd -= 1;
+        //writeln('***curpos=', curpos, '; toadd=', toadd, '; spaceLeft=', spaceLeft);
+        // fix size
+        lc.desiredsize[maindir] := lc.desiredsize[maindir]+toadd;
+        curpos += toadd;
       end;
     end;
-    // expand or align
-         if (lc.expand) then lc.desiredsize.h := nmax(1, lineh) // expand
-    else if (lc.alignBottom) then lc.desiredpos.y := cury+(lineh-lc.desiredsize.h) // bottom align
-    else if (lc.alignCenter) then lc.desiredpos.y := cury+(lineh-lc.desiredsize.h) div 2; // center
+    // secondary direction: expand or align
+    if (lc.desiredsize[suppdir] < 0) then lc.desiredsize[suppdir] := 0;
+    lc.desiredpos[suppdir] := marg0Op; // left/top align
+         if (lc.expand) then lc.desiredsize[suppdir] := me.desiredsize[suppdir]-margtotalOp // expand
+    else if (lc.aligndir > 0) then lc.desiredpos[suppdir] := me.desiredsize[suppdir]-marg1Op-lc.desiredsize[suppdir] // right/bottom align
+    else if (lc.aligndir = 0) then lc.desiredpos[suppdir] := (me.desiredsize[suppdir]-lc.desiredsize[suppdir]) div 2; // center
+    lc.desiredsize[suppdir] := nmax(lc.desiredsize[suppdir], osz[suppdir]);
+    // relayout children if size was changed
     if (not osz.equals(lc.desiredsize)) then
     begin
       if (lc.inGroup) then groupElementChanged := true;
-      // relayout children
-      layBox(lc.firstChild);
+      layBox(lc.myidx);
     end;
-    i0 := lc.nextSibling;
   end;
-  flexTotal := 0;
-  flexBoxCount := 0;
-  spaceLeft := me.desiredsize.w-me.margins.horiz;
-  cury += lineh;
 end;
 
 
@@ -620,145 +530,30 @@ end;
 procedure TFlexLayouterBase.layBox (boxidx: LayControlIdx);
 var
   me: PLayControl;
-  flexTotal: Integer; // total sum of flex fields
-  flexBoxCount: Integer; // number of boxes
-  spaceLeft: Single;
-  cury: Integer;
-  maxwdt: Integer;
-  lineStartIdx: LayControlIdx;
   lc: PLayControl;
-  doWrap: Boolean;
-  toadd: Integer;
   osz: TLaySize;
-  xpad, ypad, realpad: Integer;
-  dopad: Boolean = false;
 begin
   if (boxidx < 0) or (boxidx >= Length(ctlist)) then exit;
   me := @ctlist[boxidx];
-
   // if we have no children, there's nothing to do
   if (me.firstChild <> -1) then
   begin
-    // first, layout all children
-    for lc in forChildren(boxidx) do layBox(lc.myidx);
-
-    // second, layout lines, distribute flex data
-    if (me.horizBox) then
+    while true do
     begin
-      // horizontal boxes
-      cury := me.margins.top;
-      xpad := nmax(0, me.padding.w);
-      ypad := 0;
-
-      fixLine(me, -1, -1, 0, cury, spaceLeft); //HACK!
-
-      lineStartIdx := me.firstChild;
-      for lc in forChildren(boxidx) do
-      begin
-        if (dopad) then realpad := xpad else realpad := 0;
-        // new line?
-        doWrap := (not lc.firstInLine) and (lc.lineStart);
-        // need to wrap?
-        if (not doWrap) and (lc.canWrap) and (lc.canWrap) and (lc.desiredsize.w > 0) and (spaceLeft-realpad < lc.desiredsize.w) then doWrap := true;
-        if (doWrap) then
-        begin
-          // new line, fix this one
-          if (not lc.didWrap) then begin wrappingChanged := true; lc.didWrap := true; end;
-          fixLine(me, lineStartIdx, lc.myidx, ypad, cury, spaceLeft);
-          lineStartIdx := lc.myidx;
-          ypad := nmax(0, me.padding.h);
-          realpad := 0;
-        end
-        else
-        begin
-          if (lc.didWrap) then begin wrappingChanged := true; lc.didWrap := false; end;
-        end;
-        spaceLeft -= lc.desiredsize.w+realpad;
-        dopad := (xpad > 0) and (not lc.noPad);
-        //if (maxhgt < lc.desiredsize.h) then maxhgt := lc.desiredsize.h;
-        //if (lc.tempFlex > 0) then begin flexTotal += lc.tempFlex; flexBoxCount += 1; end;
-      end;
-      // fix last line
-      fixLine(me, lineStartIdx, -1, ypad, cury, spaceLeft);
-    end
-    else
-    begin
-      // vertical boxes
-      maxwdt := 0;
-      flexTotal := 0;
-      flexBoxCount := 0;
-      spaceLeft := me.desiredsize.h-me.margins.vert;
-      ypad := nmax(0, me.padding.h);
-
-      // calc flex
-      for lc in forChildren(boxidx) do
-      begin
-        spaceLeft -= lc.desiredsize.h;
-        if (maxwdt < lc.desiredsize.w) then maxwdt := lc.desiredsize.w;
-        if (lc.tempFlex > 0) then begin flexTotal += lc.tempFlex; flexBoxCount += 1; end;
-      end;
-
-      // distribute space
-      cury := me.margins.top;
-      //writeln('me: ', boxidx, '; margins: ', me.margins.toString);
-      for lc in forChildren(boxidx) do
-      begin
-        osz := lc.desiredsize;
-        lc.desiredsize := lc.startsize;
-        lc.desiredpos.x := me.margins.left;
-        lc.desiredpos.y := cury;
-        cury += lc.desiredsize.h;
-        if (ypad > 0) and (not lc.noPad) then cury += ypad;
-        // fix flexbox size
-        if (lc.tempFlex > 0) and (spaceLeft > 0) then
-        begin
-          toadd := trunc(spaceLeft*lc.tempFlex/flexTotal+0.5);
-          if (toadd > 0) then
-          begin
-            // size changed
-            lc.desiredsize.h += toadd;
-            cury += toadd;
-            // compensate (crudely) rounding errors
-            if (cury > me.desiredsize.h-me.margins.vert) then begin lc.desiredsize.h -= 1; cury -= 1; end;
-          end;
-        end;
-        // expand or align
-             if (lc.expand) then lc.desiredsize.w := nmax(1, me.desiredsize.w-me.margins.vert) // expand
-        else if (lc.alignRight) then lc.desiredpos.x := me.desiredsize.w-me.margins.right-lc.desiredsize.w // right align
-        else if (lc.alignCenter) then lc.desiredpos.x := (me.desiredsize.w-lc.desiredsize.w) div 2; // center
-        if (not osz.equals(lc.desiredsize)) then
-        begin
-          if (lc.inGroup) then groupElementChanged := true;
-          // relayout children
-          layBox(lc.firstChild);
-        end;
-      end;
+      osz := me.desiredsize;
+      // layout all children
+      for lc in forVisibleChildren(boxidx) do layBox(lc.myidx);
+      // distribute children
+      if (me.horizBox) then distributeChildren(me.myidx, 0) else distributeChildren(me.myidx, 1);
+      // relayout children if size was changed
+      if (osz.equals(me.desiredsize)) then break;
+      if (me.inGroup) then groupElementChanged := true;
     end;
   end;
-
-  if (me.maxsize.w >= 0) and (me.desiredsize.w > me.maxsize.w) then me.desiredsize.w := me.maxsize.w;
-  if (me.maxsize.h >= 0) and (me.desiredsize.h > me.maxsize.h) then me.desiredsize.h := me.maxsize.h;
 end;
 
 
 procedure TFlexLayouterBase.secondPass ();
-begin
-  // reset flags
-  groupElementChanged := false;
-  wrappingChanged := false;
-
-  if (Length(ctlist) > 0) then
-  begin
-    ctlist[0].desiredpos := TLayPos.Create(0, 0);
-    layBox(0);
-  end;
-
-  // fix 'wrapping-changed' flag
-  if (firstTime) then begin wrappingChanged := false; firstTime := false; end;
-end;
-
-
-procedure TFlexLayouterBase.thirdPass ();
 var
   secondAgain: Boolean;
   gtype: Integer;
@@ -767,15 +562,18 @@ var
   f, c: Integer;
   cidx: LayControlIdx;
   ct: PLayControl;
+  loopsLeft: Integer = 64;
 begin
-  while true do
+  while (loopsLeft > 0) do
   begin
-    secondPass();
+    Dec(loopsLeft);
+    layBox(0);
     secondAgain := false;
     if (groupElementChanged) then
     begin
       secondAgain := true;
-      // find max size for group, adjust 'startsize' controls to group max size
+      groupElementChanged := false;
+      // fix group sizes
       for gtype := 0 to 1 do
       begin
         for f := 0 to High(groups[gtype]) do
@@ -786,58 +584,33 @@ begin
           begin
             cidx := grp.ctls[c];
             ct := @ctlist[cidx];
-            ct.expand := false; // don't expand grouped controls anymore
-            if (maxsz < ct.startsize[gtype]) then maxsz := ct.startsize[gtype];
+            maxsz := nmax(maxsz, ct.desiredsize[gtype]);
           end;
           for c := 0 to High(grp.ctls) do
           begin
             cidx := grp.ctls[c];
             ct := @ctlist[cidx];
-            ct.startsize[gtype] := maxsz;
             ct.desiredsize[gtype] := maxsz;
-            ct.tempFlex := 0; // don't change control size anymore
           end;
         end;
       end;
-    end
-    else
+    end;
+    // don't change group control sizes anymore
+    for f := 0 to High(ctlist) do
     begin
-      for f := 0 to High(ctlist) do
+      ct := @ctlist[f];
+      if (ct.inGroup) then
       begin
-        ct := @ctlist[f];
-        if (ct.inGroup) then
-        begin
-          ct.expand := false; // don't expand grouped controls anymore
-          ct.tempFlex := 0; // don't change control size anymore
-        end;
-        (*
-        for c := 0 to 1 do
-        begin
-          if (ct.maxsize[c] < 0) then continue;
-          if (ct.desiredsize[c] > ct.maxsize[c]) then
-          begin
-            //writeln('ctl #', f, '; dimension #', c, ': desired=', ctlist[f].desiredsize[c], '; max=', ctlist[f].maxsize[c]);
-            ct.startsize[c] := ct.maxsize[c];
-            ct.desiredsize[c] := ct.maxsize[c];
-            ct.tempFlex := 0; // don't change control size anymore
-            secondAgain := true;
-          end;
-        end;
-        *)
+        ct.expand := false; // don't expand grouped controls anymore
+        ct.tempFlex := 0; // don't change control size anymore
       end;
     end;
-    if (not secondAgain) and (not wrappingChanged) then break;
-    firstTime := false;
+    if (not secondAgain) then break;
   end;
 end;
 
 
-(*
-fourth pass:
-  set 'actualsize' and 'actualpos' to 'desiredsize' and 'desiredpos'
-  return
-*)
-procedure TFlexLayouterBase.fourthPass ();
+procedure TFlexLayouterBase.thirdPass ();
 var
   f: Integer;
 begin
@@ -850,10 +623,13 @@ end;
 
 procedure TFlexLayouterBase.layout ();
 begin
+  if (Length(ctlist) = 0) then exit;
+  ctlist[0].desiredpos := TLayPos.Create(0, 0);
   firstPass();
+  //writeln('============== AFTER FIRST PASS =============='); dump();
   secondPass();
+  //writeln('============== AFTER SECOND PASS =============='); dump();
   thirdPass();
-  fourthPass();
 end;
 
 
@@ -883,7 +659,10 @@ begin
   begin
     lc := @ctlist[cidx];
     for f := 0 to indent do write(' ');
-    writeln(lc.myidx, ': startsize:', lc.startsize.toString, '; desiredsize=', lc.desiredsize.toString, '; maxsize=', lc.maxsize.toString, '; tempFlex=', lc.tempFlex, '; despos=', lc.desiredpos.toString);
+    if (not lc.visible) then write('!');
+    write(lc.myidx, ': ');
+    if (lc.ctl.id <> '') then write('<', lc.ctl.className, '> {', lc.ctl.id, '} ') else write('<', lc.ctl.className, '> ');
+    writeln('startsize:', lc.startsize.toString, '; desiredsize=', lc.desiredsize.toString, '; maxsize=', lc.maxsize.toString, '; tempFlex=', lc.tempFlex, '; despos=', lc.desiredpos.toString);
     dumpList(lc.firstChild, indent+2);
     cidx := lc.nextSibling;
   end;
@@ -896,36 +675,4 @@ begin
 end;
 
 
-// ////////////////////////////////////////////////////////////////////////// //
-(*
-void main () begin
-  auto win := new GuiControl();
-  (win ~= new GuiControl()).mSize := TLaySize(10, 5);
-  (win ~= new GuiControl()).mSize := TLaySize(16, 8);
-
-  //win.mSize := TLaySize(40, 20);
-
-  auto lay := TFlexLayouterBase!GuiControl();
-  lay.setup(win);
-
-  writeln('============================');
-  lay.dumpFlat();
-
-  writeln('=== initial ===');
-  lay.dump();
-
-  //lay.calcMaxSizeInternal(0);
-  /*
-  lay.firstPass();
-  writeln('=== after first pass ===');
-  lay.dump();
-
-  lay.secondPass();
-  writeln('=== after second pass ===');
-  lay.dump();
-  */
-  lay.layout();
-  writeln('=== final ===');
-  lay.dump();
-*)
 end.
index f70e78967a753b4255e82716058fc49e04123a5d..1f08d3a1c8d72184cfe3ee8c688fe6d1d4b9f579 100644 (file)
@@ -408,7 +408,7 @@ end;
 
 procedure TGxBmpFont.oglCreateTexture ();
 begin
-  mTexId := createFontTexture(mFontBmp, mFontWdt, (mWidth <= 0));
+  mTexId := createFontTexture(mFontBmp, mFontWdt, mHeight, (mWidth <= 0));
 end;
 
 
@@ -462,12 +462,12 @@ begin
   for ch in s do
   begin
     tx := (Integer(ch) mod 16)*8;
-    ty := (Integer(ch) div 16)*8;
+    ty := (Integer(ch) div 16)*16;
     glBegin(GL_QUADS);
-      glTexCoord2f((tx+0)/128.0, (ty+0)/128.0); glVertex2i(x+0, y+0); // top-left
-      glTexCoord2f((tx+8)/128.0, (ty+0)/128.0); glVertex2i(x+8, y+0); // top-right
-      glTexCoord2f((tx+8)/128.0, (ty+8)/128.0); glVertex2i(x+8, y+8); // bottom-right
-      glTexCoord2f((tx+0)/128.0, (ty+8)/128.0); glVertex2i(x+0, y+8); // bottom-left
+      glTexCoord2f((tx+0)/128.0, (ty+0)/256.0); glVertex2i(x+0, y+0); // top-left
+      glTexCoord2f((tx+8)/128.0, (ty+0)/256.0); glVertex2i(x+8, y+0); // top-right
+      glTexCoord2f((tx+8)/128.0, (ty+mHeight)/256.0); glVertex2i(x+8, y+mHeight); // bottom-right
+      glTexCoord2f((tx+0)/128.0, (ty+mHeight)/256.0); glVertex2i(x+0, y+mHeight); // bottom-left
     glEnd();
     x += (mFontWdt[Byte(ch)] and $0f)+1;
     result += (mFontWdt[Byte(ch)] and $0f)+1;
@@ -535,11 +535,17 @@ end;
 procedure createFonts ();
 begin
   deleteFonts();
-  SetLength(fontList, 4);
+  SetLength(fontList, 10);
   fontList[0] := TGxBmpFont.Create('dos', 8, 8, @kgiFont8[0], @kgiFont8PropWidth[0]);
   fontList[1] := TGxBmpFont.Create('dos-prop', 0, 8, @kgiFont8[0], @kgiFont8PropWidth[0]);
   fontList[2] := TGxBmpFont.Create('msx', 6, 8, @kgiFont6[0], @kgiFont6PropWidth[0]);
   fontList[3] := TGxBmpFont.Create('msx-prop', 0, 8, @kgiFont6[0], @kgiFont6PropWidth[0]);
+  fontList[4] := TGxBmpFont.Create('win8', 8, 8, @kgiWFont8[0], @kgiWFont8Wdt[0]);
+  fontList[5] := TGxBmpFont.Create('win8-prop', 0, 8, @kgiWFont8[0], @kgiWFont8Wdt[0]);
+  fontList[6] := TGxBmpFont.Create('win14', 8, 14, @kgiFont14[0], @kgiFont14Wdt[0]);
+  fontList[7] := TGxBmpFont.Create('win14-prop', 9, 14, @kgiFont14[0], @kgiFont14Wdt[0]);
+  fontList[8] := TGxBmpFont.Create('win16', 8, 16, @kgiFont16[0], @kgiFont16Wdt[0]);
+  fontList[9] := TGxBmpFont.Create('win16-prop', 0, 16, @kgiFont16[0], @kgiFont16Wdt[0]);
 end;
 
 
index c3372e223df2a04803f0fbc3da92ead8b1821d69..b520d471ec918c653749986786e3862da6fa31cf 100644 (file)
@@ -218,11 +218,399 @@ const kgiFont8PropWidth: array[0..256-1] of Byte = (
   $06,$06,$06,$06,$35,$05,$06,$07,$15,$32,$32,$08,$15,$15,$24,$08
 );
 
+const kgiFont14: array[0..256*14-1] of Byte = (
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7e,$81,$a5,$81,$81,$bd,$99,$81,$7e,$00,$00,$00,
+$00,$00,$7e,$ff,$db,$ff,$ff,$c3,$e7,$ff,$7e,$00,$00,$00,$00,$00,$00,$6c,$fe,$fe,$fe,$fe,$7c,$38,$10,$00,$00,$00,
+$00,$00,$00,$10,$38,$7c,$fe,$7c,$38,$10,$00,$00,$00,$00,$00,$00,$18,$3c,$3c,$e7,$e7,$e7,$99,$18,$3c,$00,$00,$00,
+$00,$00,$18,$3c,$7e,$ff,$ff,$7e,$18,$18,$3c,$00,$00,$00,$00,$00,$00,$00,$00,$18,$3c,$3c,$18,$00,$00,$00,$00,$00,
+$ff,$ff,$ff,$ff,$ff,$e7,$c3,$c3,$e7,$ff,$ff,$ff,$ff,$ff,$00,$00,$00,$00,$3c,$66,$42,$42,$66,$3c,$00,$00,$00,$00,
+$ff,$ff,$ff,$ff,$c3,$99,$bd,$bd,$99,$c3,$ff,$ff,$ff,$ff,$00,$00,$1e,$0e,$1a,$32,$78,$cc,$cc,$cc,$78,$00,$00,$00,
+$00,$00,$3c,$66,$66,$66,$3c,$18,$7e,$18,$18,$00,$00,$00,$00,$00,$3e,$30,$3e,$30,$30,$30,$70,$f0,$e0,$00,$00,$00,
+$00,$00,$7f,$63,$7f,$63,$63,$63,$67,$e7,$e6,$c0,$00,$00,$00,$00,$18,$18,$db,$3c,$e7,$3c,$db,$18,$18,$00,$00,$00,
+$00,$00,$80,$c0,$e0,$f8,$fe,$f8,$e0,$c0,$80,$00,$00,$00,$00,$00,$02,$06,$0e,$3e,$fe,$3e,$0e,$06,$02,$00,$00,$00,
+$00,$00,$18,$3c,$7e,$18,$18,$18,$7e,$3c,$18,$00,$00,$00,$00,$00,$66,$66,$66,$66,$66,$66,$00,$66,$66,$00,$00,$00,
+$00,$00,$7f,$db,$db,$db,$7b,$1b,$1b,$1b,$1b,$00,$00,$00,$00,$7c,$c6,$60,$38,$6c,$c6,$c6,$6c,$38,$0c,$c6,$7c,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$fe,$fe,$fe,$00,$00,$00,$00,$00,$18,$3c,$7e,$18,$18,$18,$7e,$3c,$18,$7e,$00,$00,
+$00,$00,$18,$3c,$7e,$18,$18,$18,$18,$18,$18,$00,$00,$00,$00,$00,$18,$18,$18,$18,$18,$18,$7e,$3c,$18,$00,$00,$00,
+$00,$00,$00,$00,$18,$0c,$fe,$0c,$18,$00,$00,$00,$00,$00,$00,$00,$00,$00,$30,$60,$fe,$60,$30,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$c0,$c0,$fe,$00,$00,$00,$00,$00,$00,$00,$00,$00,$28,$6c,$fe,$6c,$28,$00,$00,$00,$00,$00,
+$00,$00,$00,$10,$38,$38,$7c,$7c,$fe,$fe,$00,$00,$00,$00,$00,$00,$00,$fe,$fe,$7c,$7c,$38,$38,$10,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$3c,$3c,$3c,$18,$18,$00,$18,$18,$00,$00,$00,
+$00,$66,$66,$66,$24,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$6c,$6c,$fe,$6c,$6c,$6c,$fe,$6c,$6c,$00,$00,$00,
+$18,$18,$7c,$c6,$c2,$c0,$7c,$06,$86,$c6,$7c,$18,$18,$00,$00,$00,$00,$00,$c2,$c6,$0c,$18,$30,$66,$c6,$00,$00,$00,
+$00,$00,$38,$6c,$6c,$38,$76,$dc,$cc,$cc,$76,$00,$00,$00,$00,$30,$30,$30,$60,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$0c,$18,$30,$30,$30,$30,$30,$18,$0c,$00,$00,$00,$00,$00,$30,$18,$0c,$0c,$0c,$0c,$0c,$18,$30,$00,$00,$00,
+$00,$00,$00,$00,$66,$3c,$ff,$3c,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$18,$7e,$18,$18,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$18,$18,$18,$30,$00,$00,$00,$00,$00,$00,$00,$00,$fe,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$18,$00,$00,$00,$00,$00,$02,$06,$0c,$18,$30,$60,$c0,$80,$00,$00,$00,$00,
+$00,$00,$7c,$c6,$ce,$de,$f6,$e6,$c6,$c6,$7c,$00,$00,$00,$00,$00,$18,$38,$78,$18,$18,$18,$18,$18,$7e,$00,$00,$00,
+$00,$00,$7c,$c6,$06,$0c,$18,$30,$60,$c6,$fe,$00,$00,$00,$00,$00,$7c,$c6,$06,$06,$3c,$06,$06,$c6,$7c,$00,$00,$00,
+$00,$00,$0c,$1c,$3c,$6c,$cc,$fe,$0c,$0c,$1e,$00,$00,$00,$00,$00,$fe,$c0,$c0,$fc,$0e,$06,$06,$c6,$7c,$00,$00,$00,
+$00,$00,$38,$60,$c0,$c0,$fc,$c6,$c6,$c6,$7c,$00,$00,$00,$00,$00,$fe,$c6,$06,$0c,$18,$30,$30,$30,$30,$00,$00,$00,
+$00,$00,$7c,$c6,$c6,$c6,$7c,$c6,$c6,$c6,$7c,$00,$00,$00,$00,$00,$7c,$c6,$c6,$c6,$7e,$06,$06,$0c,$78,$00,$00,$00,
+$00,$00,$00,$18,$18,$00,$00,$00,$18,$18,$00,$00,$00,$00,$00,$00,$00,$18,$18,$00,$00,$00,$18,$18,$30,$00,$00,$00,
+$00,$00,$06,$0c,$18,$30,$60,$30,$18,$0c,$06,$00,$00,$00,$00,$00,$00,$00,$00,$fe,$00,$00,$fe,$00,$00,$00,$00,$00,
+$00,$00,$60,$30,$18,$0c,$06,$0c,$18,$30,$60,$00,$00,$00,$00,$00,$7c,$c6,$c6,$0c,$18,$18,$00,$18,$18,$00,$00,$00,
+$00,$00,$7c,$c6,$c6,$de,$de,$de,$dc,$c0,$7c,$00,$00,$00,$00,$00,$10,$38,$6c,$c6,$c6,$fe,$c6,$c6,$c6,$00,$00,$00,
+$00,$00,$fc,$66,$66,$66,$7c,$66,$66,$66,$fc,$00,$00,$00,$00,$00,$3c,$66,$c2,$c0,$c0,$c0,$c2,$66,$3c,$00,$00,$00,
+$00,$00,$f8,$6c,$66,$66,$66,$66,$66,$6c,$f8,$00,$00,$00,$00,$00,$fe,$66,$62,$68,$78,$68,$62,$66,$fe,$00,$00,$00,
+$00,$00,$fe,$66,$62,$68,$78,$68,$60,$60,$f0,$00,$00,$00,$00,$00,$3c,$66,$c2,$c0,$c0,$de,$c6,$66,$3a,$00,$00,$00,
+$00,$00,$c6,$c6,$c6,$c6,$fe,$c6,$c6,$c6,$c6,$00,$00,$00,$00,$00,$3c,$18,$18,$18,$18,$18,$18,$18,$3c,$00,$00,$00,
+$00,$00,$1e,$0c,$0c,$0c,$0c,$0c,$cc,$cc,$78,$00,$00,$00,$00,$00,$e6,$66,$6c,$6c,$78,$6c,$6c,$66,$e6,$00,$00,$00,
+$00,$00,$f0,$60,$60,$60,$60,$60,$62,$66,$fe,$00,$00,$00,$00,$00,$c6,$ee,$fe,$fe,$d6,$c6,$c6,$c6,$c6,$00,$00,$00,
+$00,$00,$c6,$e6,$f6,$fe,$de,$ce,$c6,$c6,$c6,$00,$00,$00,$00,$00,$38,$6c,$c6,$c6,$c6,$c6,$c6,$6c,$38,$00,$00,$00,
+$00,$00,$fc,$66,$66,$66,$7c,$60,$60,$60,$f0,$00,$00,$00,$00,$00,$7c,$c6,$c6,$c6,$c6,$d6,$de,$7c,$0c,$0e,$00,$00,
+$00,$00,$fc,$66,$66,$66,$7c,$6c,$66,$66,$e6,$00,$00,$00,$00,$00,$7c,$c6,$c6,$60,$38,$0c,$c6,$c6,$7c,$00,$00,$00,
+$00,$00,$7e,$7e,$5a,$18,$18,$18,$18,$18,$3c,$00,$00,$00,$00,$00,$c6,$c6,$c6,$c6,$c6,$c6,$c6,$c6,$7c,$00,$00,$00,
+$00,$00,$c6,$c6,$c6,$c6,$c6,$c6,$6c,$38,$10,$00,$00,$00,$00,$00,$c6,$c6,$c6,$c6,$d6,$d6,$fe,$7c,$6c,$00,$00,$00,
+$00,$00,$c6,$c6,$6c,$38,$38,$38,$6c,$c6,$c6,$00,$00,$00,$00,$00,$66,$66,$66,$66,$3c,$18,$18,$18,$3c,$00,$00,$00,
+$00,$00,$fe,$c6,$8c,$18,$30,$60,$c2,$c6,$fe,$00,$00,$00,$00,$00,$3c,$30,$30,$30,$30,$30,$30,$30,$3c,$00,$00,$00,
+$00,$00,$80,$c0,$e0,$70,$38,$1c,$0e,$06,$02,$00,$00,$00,$00,$00,$3c,$0c,$0c,$0c,$0c,$0c,$0c,$0c,$3c,$00,$00,$00,
+$10,$38,$6c,$c6,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$ff,$00,
+$30,$30,$18,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$78,$0c,$7c,$cc,$cc,$76,$00,$00,$00,
+$00,$00,$e0,$60,$60,$78,$6c,$66,$66,$66,$dc,$00,$00,$00,$00,$00,$00,$00,$00,$7c,$c6,$c0,$c0,$c6,$7c,$00,$00,$00,
+$00,$00,$1c,$0c,$0c,$3c,$6c,$cc,$cc,$cc,$76,$00,$00,$00,$00,$00,$00,$00,$00,$7c,$c6,$fe,$c0,$c6,$7c,$00,$00,$00,
+$00,$00,$38,$6c,$64,$60,$f0,$60,$60,$60,$f0,$00,$00,$00,$00,$00,$00,$00,$00,$76,$cc,$cc,$cc,$7c,$0c,$cc,$78,$00,
+$00,$00,$e0,$60,$60,$6c,$76,$66,$66,$66,$e6,$00,$00,$00,$00,$00,$18,$18,$00,$38,$18,$18,$18,$18,$3c,$00,$00,$00,
+$00,$00,$06,$06,$00,$0e,$06,$06,$06,$06,$66,$66,$3c,$00,$00,$00,$e0,$60,$60,$66,$6c,$78,$6c,$66,$e6,$00,$00,$00,
+$00,$00,$38,$18,$18,$18,$18,$18,$18,$18,$3c,$00,$00,$00,$00,$00,$00,$00,$00,$ec,$fe,$d6,$d6,$d6,$d6,$00,$00,$00,
+$00,$00,$00,$00,$00,$dc,$66,$66,$66,$66,$66,$00,$00,$00,$00,$00,$00,$00,$00,$7c,$c6,$c6,$c6,$c6,$7c,$00,$00,$00,
+$00,$00,$00,$00,$00,$dc,$66,$66,$66,$7c,$60,$60,$f0,$00,$00,$00,$00,$00,$00,$76,$cc,$cc,$cc,$7c,$0c,$0c,$1e,$00,
+$00,$00,$00,$00,$00,$dc,$76,$62,$60,$60,$f0,$00,$00,$00,$00,$00,$00,$00,$00,$7c,$c6,$70,$1c,$c6,$7c,$00,$00,$00,
+$00,$00,$10,$30,$30,$fc,$30,$30,$30,$36,$1c,$00,$00,$00,$00,$00,$00,$00,$00,$cc,$cc,$cc,$cc,$cc,$76,$00,$00,$00,
+$00,$00,$00,$00,$00,$66,$66,$66,$66,$3c,$18,$00,$00,$00,$00,$00,$00,$00,$00,$c6,$c6,$d6,$d6,$fe,$6c,$00,$00,$00,
+$00,$00,$00,$00,$00,$c6,$6c,$38,$38,$6c,$c6,$00,$00,$00,$00,$00,$00,$00,$00,$c6,$c6,$c6,$c6,$7e,$06,$0c,$f8,$00,
+$00,$00,$00,$00,$00,$fe,$cc,$18,$30,$66,$fe,$00,$00,$00,$00,$00,$0e,$18,$18,$18,$70,$18,$18,$18,$0e,$00,$00,$00,
+$00,$00,$18,$18,$18,$18,$00,$18,$18,$18,$18,$00,$00,$00,$00,$00,$70,$18,$18,$18,$0e,$18,$18,$18,$70,$00,$00,$00,
+$00,$00,$76,$dc,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$10,$38,$6c,$c6,$c6,$fe,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$6c,$00,$fe,$66,$62,$68,$78,$68,$60,$62,$66,$fe,$00,$00,$00,$b0,$d8,$d8,$d8,$d8,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$11,$44,$11,$44,$11,$44,$11,$44,$11,$44,$11,$44,$11,$44,$55,$aa,$55,$aa,$55,$aa,$55,$aa,$55,$aa,$55,$aa,$55,$aa,
+$dd,$77,$dd,$77,$dd,$77,$dd,$77,$dd,$77,$dd,$77,$dd,$77,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,
+$18,$18,$18,$18,$18,$18,$18,$f8,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$f8,$18,$f8,$18,$18,$18,$18,$18,$18,
+$36,$36,$36,$36,$36,$36,$36,$f6,$36,$36,$36,$36,$36,$36,$00,$00,$00,$00,$00,$00,$00,$fe,$36,$36,$36,$36,$36,$36,
+$00,$00,$00,$28,$00,$7c,$c6,$fe,$c0,$c0,$c6,$7c,$00,$00,$36,$36,$36,$36,$36,$f6,$06,$f6,$36,$36,$36,$36,$36,$36,
+$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$00,$00,$00,$00,$00,$fe,$06,$f6,$36,$36,$36,$36,$36,$36,
+$36,$36,$36,$36,$36,$f6,$06,$fe,$00,$00,$00,$00,$00,$00,$36,$36,$36,$36,$36,$36,$36,$fe,$00,$00,$00,$00,$00,$00,
+$18,$18,$18,$18,$18,$f8,$18,$f8,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$f8,$18,$18,$18,$18,$18,$18,
+$00,$00,$1e,$36,$66,$c6,$c6,$fe,$c6,$c6,$c6,$c6,$00,$00,$00,$00,$fe,$62,$62,$60,$7c,$66,$66,$66,$66,$fc,$00,$00,
+$00,$00,$fc,$66,$66,$66,$7c,$66,$66,$66,$66,$fc,$00,$00,$00,$00,$fe,$62,$62,$60,$60,$60,$60,$60,$60,$f0,$00,$00,
+$00,$00,$1e,$36,$66,$66,$66,$66,$66,$66,$66,$ff,$c3,$81,$00,$00,$fe,$66,$62,$68,$78,$68,$60,$62,$66,$fe,$00,$00,
+$00,$00,$d6,$d6,$54,$54,$7c,$7c,$54,$d6,$d6,$d6,$00,$00,$00,$00,$7c,$c6,$06,$06,$3c,$06,$06,$06,$c6,$7c,$00,$00,
+$00,$00,$c6,$c6,$ce,$ce,$d6,$e6,$e6,$c6,$c6,$c6,$00,$00,$38,$38,$c6,$c6,$ce,$ce,$d6,$e6,$e6,$c6,$c6,$c6,$00,$00,
+$00,$00,$e6,$66,$6c,$6c,$78,$78,$6c,$6c,$66,$e6,$00,$00,$00,$00,$1e,$36,$66,$c6,$c6,$c6,$c6,$c6,$c6,$c6,$00,$00,
+$00,$00,$c6,$ee,$fe,$fe,$d6,$c6,$c6,$c6,$c6,$c6,$00,$00,$00,$00,$c6,$c6,$c6,$c6,$fe,$c6,$c6,$c6,$c6,$c6,$00,$00,
+$00,$00,$7c,$c6,$c6,$c6,$c6,$c6,$c6,$c6,$c6,$7c,$00,$00,$00,$00,$fe,$c6,$c6,$c6,$c6,$c6,$c6,$c6,$c6,$c6,$00,$00,
+$00,$00,$fc,$66,$66,$66,$7c,$60,$60,$60,$60,$f0,$00,$00,$00,$00,$3c,$66,$c2,$c0,$c0,$c0,$c0,$c2,$66,$3c,$00,$00,
+$00,$00,$7e,$5a,$18,$18,$18,$18,$18,$18,$18,$3c,$00,$00,$00,$00,$c6,$c6,$c6,$c6,$c6,$7e,$06,$06,$c6,$7c,$00,$00,
+$00,$3c,$18,$7e,$db,$db,$db,$db,$db,$7e,$18,$3c,$00,$00,$00,$00,$c6,$c6,$6c,$7c,$38,$38,$7c,$6c,$c6,$c6,$00,$00,
+$00,$00,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$fe,$06,$06,$00,$00,$c6,$c6,$c6,$c6,$c6,$7e,$06,$06,$06,$06,$00,$00,
+$00,$00,$db,$db,$db,$db,$db,$db,$db,$db,$db,$ff,$00,$00,$00,$00,$db,$db,$db,$db,$db,$db,$db,$db,$db,$ff,$03,$03,
+$00,$00,$f8,$b0,$30,$30,$3c,$36,$36,$36,$36,$7c,$00,$00,$00,$00,$c3,$c3,$c3,$c3,$f3,$db,$db,$db,$db,$f3,$00,$00,
+$00,$00,$f0,$60,$60,$60,$7c,$66,$66,$66,$66,$fc,$00,$00,$00,$00,$7c,$c6,$06,$26,$3e,$26,$06,$06,$c6,$7c,$00,$00,
+$00,$00,$ce,$db,$db,$db,$fb,$db,$db,$db,$db,$ce,$00,$00,$00,$00,$3f,$66,$66,$66,$3e,$3e,$66,$66,$66,$e7,$00,$00,
+$00,$00,$00,$00,$00,$78,$0c,$7c,$cc,$cc,$cc,$76,$00,$00,$00,$02,$06,$3c,$60,$60,$7c,$66,$66,$66,$66,$3c,$00,$00,
+$00,$00,$00,$00,$00,$fc,$66,$66,$7c,$66,$66,$fc,$00,$00,$00,$00,$00,$00,$00,$7e,$32,$32,$30,$30,$30,$78,$00,$00,
+$00,$00,$00,$00,$00,$1e,$36,$36,$66,$66,$66,$ff,$c3,$c3,$00,$00,$00,$00,$00,$7c,$c6,$fe,$c0,$c0,$c6,$7c,$00,$00,
+$00,$00,$00,$00,$00,$d6,$d6,$54,$7c,$54,$d6,$d6,$00,$00,$00,$00,$00,$00,$00,$3c,$66,$06,$0c,$06,$66,$3c,$00,$00,
+$00,$00,$00,$00,$00,$c6,$c6,$ce,$d6,$e6,$c6,$c6,$00,$00,$00,$00,$00,$38,$38,$c6,$c6,$ce,$d6,$e6,$c6,$c6,$00,$00,
+$00,$00,$00,$00,$00,$e6,$6c,$78,$78,$6c,$66,$e6,$00,$00,$00,$00,$00,$00,$00,$1e,$36,$66,$66,$66,$66,$66,$00,$00,
+$00,$00,$00,$00,$00,$c6,$ee,$fe,$fe,$d6,$d6,$c6,$00,$00,$00,$00,$00,$00,$00,$c6,$c6,$c6,$fe,$c6,$c6,$c6,$00,$00,
+$00,$00,$00,$00,$00,$7c,$c6,$c6,$c6,$c6,$c6,$7c,$00,$00,$00,$00,$00,$00,$00,$fe,$c6,$c6,$c6,$c6,$c6,$c6,$00,$00,
+$00,$00,$00,$00,$00,$dc,$66,$66,$66,$66,$66,$7c,$60,$f0,$00,$00,$00,$00,$00,$7c,$c6,$c0,$c0,$c0,$c6,$7c,$00,$00,
+$00,$00,$00,$00,$00,$7e,$5a,$18,$18,$18,$18,$3c,$00,$00,$00,$00,$00,$00,$00,$c6,$c6,$c6,$c6,$c6,$7e,$06,$c6,$7c,
+$00,$00,$00,$00,$3c,$18,$7e,$db,$db,$db,$db,$7e,$18,$3c,$00,$00,$00,$00,$00,$c6,$6c,$38,$38,$38,$6c,$c6,$00,$00,
+$00,$00,$00,$00,$00,$cc,$cc,$cc,$cc,$cc,$cc,$fe,$06,$06,$00,$00,$00,$00,$00,$c6,$c6,$c6,$c6,$7e,$06,$06,$00,$00,
+$00,$00,$00,$00,$00,$d6,$d6,$d6,$d6,$d6,$d6,$fe,$00,$00,$00,$00,$00,$00,$00,$d6,$d6,$d6,$d6,$d6,$d6,$fe,$03,$03,
+$00,$00,$00,$00,$00,$f8,$b0,$30,$3e,$33,$33,$7e,$00,$00,$00,$00,$00,$00,$00,$c6,$c6,$c6,$f6,$de,$de,$f6,$00,$00,
+$00,$00,$00,$00,$00,$f0,$60,$60,$7c,$66,$66,$fc,$00,$00,$00,$00,$00,$00,$00,$3c,$66,$06,$1e,$06,$66,$3c,$00,$00,
+$00,$00,$00,$00,$00,$ce,$db,$db,$fb,$db,$db,$ce,$00,$00,$00,$00,$00,$00,$00,$7e,$cc,$cc,$fc,$6c,$cc,$ce,$00,$00);
+const kgiFont14Wdt: array[0..256-1] of Byte = (
+$00,$08,$08,$07,$07,$08,$08,$24,$08,$16,$08,$07,$16,$07,$08,$08,$07,$07,$16,$16,$08,$07,$07,$16,$16,$16,$07,$07,
+$07,$07,$07,$07,$00,$24,$16,$07,$07,$07,$07,$13,$24,$24,$08,$16,$23,$07,$32,$07,$07,$16,$07,$07,$07,$07,$07,$07,
+$07,$07,$32,$23,$16,$07,$16,$07,$07,$07,$07,$07,$07,$07,$07,$07,$07,$24,$07,$07,$07,$07,$07,$07,$07,$07,$07,$07,
+$16,$07,$07,$07,$07,$16,$07,$24,$07,$24,$07,$08,$23,$07,$07,$07,$07,$07,$06,$07,$07,$24,$16,$07,$24,$07,$07,$07,
+$07,$07,$07,$07,$07,$07,$16,$07,$07,$07,$07,$16,$32,$16,$07,$07,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$07,$05,$00,$00,$00,$00,$00,$00,$08,$08,$08,$08,$08,$08,$08,$08,$07,$08,$08,$08,$08,$08,$08,$08,$07,$07,$07,$07,
+$08,$07,$07,$07,$07,$07,$07,$07,$07,$07,$07,$07,$07,$07,$16,$07,$08,$07,$07,$07,$08,$08,$07,$08,$07,$07,$08,$08,
+$07,$16,$07,$16,$08,$07,$07,$16,$07,$07,$07,$16,$07,$07,$07,$07,$07,$07,$16,$07,$08,$07,$07,$07,$07,$08,$08,$07,
+$07,$16,$08,$07);
 
-function createFontTexture (const font: PByte; const fontwdt: PByte; prop: Boolean): GLuint;
+const kgiFont16: array[0..256*16-1] of Byte = (
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7e,$81,$a5,$81,$81,$bd,$99,$81,$81,$7e,
+$00,$00,$00,$00,$00,$00,$7e,$ff,$db,$ff,$ff,$c3,$e7,$ff,$ff,$7e,$00,$00,$00,$00,$00,$00,$00,$00,$6c,$fe,$fe,$fe,
+$fe,$7c,$38,$10,$00,$00,$00,$00,$00,$00,$00,$00,$10,$38,$7c,$fe,$7c,$38,$10,$00,$00,$00,$00,$00,$00,$00,$00,$18,
+$3c,$3c,$e7,$e7,$e7,$99,$18,$3c,$00,$00,$00,$00,$00,$00,$00,$18,$3c,$7e,$ff,$ff,$7e,$18,$18,$3c,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$18,$3c,$3c,$18,$00,$00,$00,$00,$00,$00,$ff,$ff,$ff,$ff,$ff,$ff,$e7,$c3,$c3,$e7,$ff,$ff,
+$ff,$ff,$ff,$ff,$00,$00,$00,$00,$00,$3c,$66,$42,$42,$66,$3c,$00,$00,$00,$00,$00,$ff,$ff,$ff,$ff,$ff,$c3,$99,$bd,
+$bd,$99,$c3,$ff,$ff,$ff,$ff,$ff,$00,$00,$1e,$0e,$1a,$32,$78,$cc,$cc,$cc,$cc,$78,$00,$00,$00,$00,$00,$00,$3c,$66,
+$66,$66,$66,$3c,$18,$7e,$18,$18,$00,$00,$00,$00,$00,$00,$3e,$30,$3e,$30,$30,$30,$30,$70,$f0,$e0,$00,$00,$00,$00,
+$00,$00,$7f,$63,$7f,$63,$63,$63,$63,$67,$e7,$e6,$c0,$00,$00,$00,$00,$00,$00,$18,$18,$db,$3c,$e7,$3c,$db,$18,$18,
+$00,$00,$00,$00,$00,$80,$c0,$e0,$f0,$f8,$fe,$f8,$f0,$e0,$c0,$80,$00,$00,$00,$00,$00,$02,$06,$0e,$1e,$3e,$fe,$3e,
+$1e,$0e,$06,$02,$00,$00,$00,$00,$00,$00,$18,$3c,$7e,$18,$18,$18,$18,$7e,$3c,$18,$00,$00,$00,$00,$00,$00,$66,$66,
+$66,$66,$66,$66,$66,$00,$66,$66,$00,$00,$00,$00,$00,$00,$7f,$db,$db,$db,$7b,$1b,$1b,$1b,$1b,$1b,$00,$00,$00,$00,
+$00,$7c,$c6,$60,$38,$6c,$c6,$c6,$6c,$38,$0c,$c6,$7c,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$fe,$fe,$fe,$fe,
+$00,$00,$00,$00,$00,$00,$18,$3c,$7e,$18,$18,$18,$18,$7e,$3c,$18,$7e,$00,$00,$00,$00,$00,$18,$3c,$7e,$18,$18,$18,
+$18,$18,$18,$18,$00,$00,$00,$00,$00,$00,$18,$18,$18,$18,$18,$18,$18,$7e,$3c,$18,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$18,$0c,$fe,$0c,$18,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$30,$60,$fe,$60,$30,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$c0,$c0,$c0,$c0,$fe,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$28,$6c,$fe,$6c,$28,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$10,$38,$38,$7c,$7c,$fe,$fe,$00,$00,$00,$00,$00,$00,$00,$00,$00,$fe,$fe,$7c,$7c,
+$38,$38,$10,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$3c,
+$3c,$3c,$18,$18,$18,$00,$18,$18,$00,$00,$00,$00,$00,$66,$66,$66,$24,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$6c,$6c,$fe,$6c,$6c,$6c,$fe,$6c,$6c,$00,$00,$00,$00,$18,$18,$7c,$c6,$c2,$c0,$7c,$06,$86,$c6,$7c,$18,
+$18,$00,$00,$00,$00,$00,$00,$00,$c2,$c6,$0c,$18,$30,$60,$c6,$86,$00,$00,$00,$00,$00,$00,$38,$6c,$6c,$38,$76,$dc,
+$cc,$cc,$cc,$76,$00,$00,$00,$00,$00,$30,$30,$30,$60,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0c,$18,
+$30,$30,$30,$30,$30,$30,$18,$0c,$00,$00,$00,$00,$00,$00,$30,$18,$0c,$0c,$0c,$0c,$0c,$0c,$18,$30,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$66,$3c,$ff,$3c,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$18,$7e,$18,$18,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$18,$18,$30,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$fe,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$18,$00,$00,$00,$00,$00,$00,$00,$00,
+$02,$06,$0c,$18,$30,$60,$c0,$80,$00,$00,$00,$00,$00,$00,$7c,$c6,$c6,$ce,$d6,$d6,$e6,$c6,$c6,$7c,$00,$00,$00,$00,
+$00,$00,$18,$38,$78,$18,$18,$18,$18,$18,$18,$7e,$00,$00,$00,$00,$00,$00,$7c,$c6,$06,$0c,$18,$30,$60,$c0,$c6,$fe,
+$00,$00,$00,$00,$00,$00,$7c,$c6,$06,$06,$3c,$06,$06,$06,$c6,$7c,$00,$00,$00,$00,$00,$00,$0c,$1c,$3c,$6c,$cc,$fe,
+$0c,$0c,$0c,$1e,$00,$00,$00,$00,$00,$00,$fe,$c0,$c0,$c0,$fc,$0e,$06,$06,$c6,$7c,$00,$00,$00,$00,$00,$00,$38,$60,
+$c0,$c0,$fc,$c6,$c6,$c6,$c6,$7c,$00,$00,$00,$00,$00,$00,$fe,$c6,$06,$06,$0c,$18,$30,$30,$30,$30,$00,$00,$00,$00,
+$00,$00,$7c,$c6,$c6,$c6,$7c,$c6,$c6,$c6,$c6,$7c,$00,$00,$00,$00,$00,$00,$7c,$c6,$c6,$c6,$7e,$06,$06,$06,$0c,$78,
+$00,$00,$00,$00,$00,$00,$00,$00,$18,$18,$00,$00,$00,$18,$18,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$18,$00,$00,
+$00,$18,$18,$30,$00,$00,$00,$00,$00,$00,$00,$06,$0c,$18,$30,$60,$30,$18,$0c,$06,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$fe,$00,$00,$fe,$00,$00,$00,$00,$00,$00,$00,$00,$00,$60,$30,$18,$0c,$06,$0c,$18,$30,$60,$00,$00,$00,$00,
+$00,$00,$7c,$c6,$c6,$0c,$18,$18,$18,$00,$18,$18,$00,$00,$00,$00,$00,$00,$00,$7c,$c6,$c6,$de,$de,$de,$dc,$c0,$7c,
+$00,$00,$00,$00,$00,$00,$10,$38,$6c,$c6,$c6,$fe,$c6,$c6,$c6,$c6,$00,$00,$00,$00,$00,$00,$fc,$66,$66,$66,$7c,$66,
+$66,$66,$66,$fc,$00,$00,$00,$00,$00,$00,$3c,$66,$c2,$c0,$c0,$c0,$c0,$c2,$66,$3c,$00,$00,$00,$00,$00,$00,$f8,$6c,
+$66,$66,$66,$66,$66,$66,$6c,$f8,$00,$00,$00,$00,$00,$00,$fe,$66,$62,$68,$78,$68,$60,$62,$66,$fe,$00,$00,$00,$00,
+$00,$00,$fe,$66,$62,$68,$78,$68,$60,$60,$60,$f0,$00,$00,$00,$00,$00,$00,$3c,$66,$c2,$c0,$c0,$de,$c6,$c6,$66,$3a,
+$00,$00,$00,$00,$00,$00,$c6,$c6,$c6,$c6,$fe,$c6,$c6,$c6,$c6,$c6,$00,$00,$00,$00,$00,$00,$3c,$18,$18,$18,$18,$18,
+$18,$18,$18,$3c,$00,$00,$00,$00,$00,$00,$1e,$0c,$0c,$0c,$0c,$0c,$cc,$cc,$cc,$78,$00,$00,$00,$00,$00,$00,$e6,$66,
+$6c,$6c,$78,$78,$6c,$66,$66,$e6,$00,$00,$00,$00,$00,$00,$f0,$60,$60,$60,$60,$60,$60,$62,$66,$fe,$00,$00,$00,$00,
+$00,$00,$c6,$ee,$fe,$fe,$d6,$c6,$c6,$c6,$c6,$c6,$00,$00,$00,$00,$00,$00,$c6,$e6,$f6,$fe,$de,$ce,$c6,$c6,$c6,$c6,
+$00,$00,$00,$00,$00,$00,$38,$6c,$c6,$c6,$c6,$c6,$c6,$c6,$6c,$38,$00,$00,$00,$00,$00,$00,$fc,$66,$66,$66,$7c,$60,
+$60,$60,$60,$f0,$00,$00,$00,$00,$00,$00,$7c,$c6,$c6,$c6,$c6,$c6,$c6,$d6,$de,$7c,$0c,$0e,$00,$00,$00,$00,$fc,$66,
+$66,$66,$7c,$6c,$66,$66,$66,$e6,$00,$00,$00,$00,$00,$00,$7c,$c6,$c6,$60,$38,$0c,$06,$c6,$c6,$7c,$00,$00,$00,$00,
+$00,$00,$7e,$7e,$5a,$18,$18,$18,$18,$18,$18,$3c,$00,$00,$00,$00,$00,$00,$c6,$c6,$c6,$c6,$c6,$c6,$c6,$c6,$c6,$7c,
+$00,$00,$00,$00,$00,$00,$c6,$c6,$c6,$c6,$c6,$c6,$c6,$6c,$38,$10,$00,$00,$00,$00,$00,$00,$c6,$c6,$c6,$c6,$c6,$d6,
+$d6,$fe,$6c,$6c,$00,$00,$00,$00,$00,$00,$c6,$c6,$6c,$6c,$38,$38,$6c,$6c,$c6,$c6,$00,$00,$00,$00,$00,$00,$66,$66,
+$66,$66,$3c,$18,$18,$18,$18,$3c,$00,$00,$00,$00,$00,$00,$fe,$c6,$86,$0c,$18,$30,$60,$c2,$c6,$fe,$00,$00,$00,$00,
+$00,$00,$3c,$30,$30,$30,$30,$30,$30,$30,$30,$3c,$00,$00,$00,$00,$00,$00,$00,$80,$c0,$e0,$70,$38,$1c,$0e,$06,$02,
+$00,$00,$00,$00,$00,$00,$3c,$0c,$0c,$0c,$0c,$0c,$0c,$0c,$0c,$3c,$00,$00,$00,$00,$10,$38,$6c,$c6,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$ff,$00,$00,$30,$30,$18,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$78,$0c,$7c,$cc,$cc,$cc,$76,$00,$00,$00,$00,
+$00,$00,$e0,$60,$60,$78,$6c,$66,$66,$66,$66,$dc,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7c,$c6,$c0,$c0,$c0,$c6,$7c,
+$00,$00,$00,$00,$00,$00,$1c,$0c,$0c,$3c,$6c,$cc,$cc,$cc,$cc,$76,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7c,$c6,$fe,
+$c0,$c0,$c6,$7c,$00,$00,$00,$00,$00,$00,$38,$6c,$64,$60,$f0,$60,$60,$60,$60,$f0,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$76,$cc,$cc,$cc,$cc,$cc,$7c,$0c,$cc,$78,$00,$00,$00,$e0,$60,$60,$6c,$76,$66,$66,$66,$66,$e6,$00,$00,$00,$00,
+$00,$00,$18,$18,$00,$38,$18,$18,$18,$18,$18,$3c,$00,$00,$00,$00,$00,$00,$06,$06,$00,$0e,$06,$06,$06,$06,$06,$06,
+$66,$66,$3c,$00,$00,$00,$e0,$60,$60,$66,$6c,$78,$78,$6c,$66,$e6,$00,$00,$00,$00,$00,$00,$38,$18,$18,$18,$18,$18,
+$18,$18,$18,$3c,$00,$00,$00,$00,$00,$00,$00,$00,$00,$ec,$fe,$d6,$d6,$d6,$d6,$d6,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$dc,$66,$66,$66,$66,$66,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7c,$c6,$c6,$c6,$c6,$c6,$7c,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$dc,$66,$66,$66,$66,$66,$7c,$60,$60,$f0,$00,$00,$00,$00,$00,$00,$76,$cc,$cc,$cc,$cc,$cc,$7c,
+$0c,$0c,$1e,$00,$00,$00,$00,$00,$00,$dc,$76,$62,$60,$60,$60,$f0,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7c,$c6,$60,
+$38,$0c,$c6,$7c,$00,$00,$00,$00,$00,$00,$10,$30,$30,$fc,$30,$30,$30,$30,$36,$1c,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$cc,$cc,$cc,$cc,$cc,$cc,$76,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$66,$66,$66,$66,$3c,$18,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$c6,$c6,$c6,$d6,$d6,$fe,$6c,$00,$00,$00,$00,$00,$00,$00,$00,$00,$c6,$6c,$38,$38,$38,$6c,$c6,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$c6,$c6,$c6,$c6,$c6,$c6,$7e,$06,$0c,$f8,$00,$00,$00,$00,$00,$00,$fe,$cc,$18,
+$30,$60,$c6,$fe,$00,$00,$00,$00,$00,$00,$0e,$18,$18,$18,$70,$18,$18,$18,$18,$0e,$00,$00,$00,$00,$00,$00,$18,$18,
+$18,$18,$00,$18,$18,$18,$18,$18,$00,$00,$00,$00,$00,$00,$70,$18,$18,$18,$0e,$18,$18,$18,$18,$70,$00,$00,$00,$00,
+$00,$00,$76,$dc,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$10,$38,$6c,$c6,$c6,$c6,$fe,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$6c,$00,$fe,$66,$62,$68,$78,$68,$60,$62,$66,$fe,$00,$00,$00,$00,$00,$b0,$d8,$d8,$d8,$d8,$d8,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$11,$44,$11,$44,$11,$44,$11,$44,$11,$44,$11,$44,
+$11,$44,$11,$44,$55,$aa,$55,$aa,$55,$aa,$55,$aa,$55,$aa,$55,$aa,$55,$aa,$55,$aa,$dd,$77,$dd,$77,$dd,$77,$dd,$77,
+$dd,$77,$dd,$77,$dd,$77,$dd,$77,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,
+$18,$18,$18,$f8,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$f8,$18,$f8,$18,$18,$18,$18,$18,$18,$18,$18,
+$36,$36,$36,$36,$36,$36,$36,$f6,$36,$36,$36,$36,$36,$36,$36,$36,$00,$00,$00,$00,$00,$00,$00,$fe,$36,$36,$36,$36,
+$36,$36,$36,$36,$00,$00,$28,$28,$00,$7c,$c6,$fe,$c0,$c0,$c6,$7c,$00,$00,$00,$00,$36,$36,$36,$36,$36,$f6,$06,$f6,
+$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$00,$00,$00,$00,
+$00,$fe,$06,$f6,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$f6,$06,$fe,$00,$00,$00,$00,$00,$00,$00,$00,
+$36,$36,$36,$36,$36,$36,$36,$fe,$00,$00,$00,$00,$00,$00,$00,$00,$18,$18,$18,$18,$18,$f8,$18,$f8,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$f8,$18,$18,$18,$18,$18,$18,$18,$18,$00,$00,$1e,$36,$66,$c6,$c6,$fe,
+$c6,$c6,$c6,$c6,$00,$00,$00,$00,$00,$00,$fe,$62,$62,$60,$7c,$66,$66,$66,$66,$fc,$00,$00,$00,$00,$00,$00,$fc,$66,
+$66,$66,$7c,$66,$66,$66,$66,$fc,$00,$00,$00,$00,$00,$00,$fe,$62,$62,$60,$60,$60,$60,$60,$60,$f0,$00,$00,$00,$00,
+$00,$00,$1e,$36,$66,$66,$66,$66,$66,$66,$66,$ff,$c3,$81,$00,$00,$00,$00,$fe,$66,$62,$68,$78,$68,$60,$62,$66,$fe,
+$00,$00,$00,$00,$00,$00,$d6,$d6,$54,$54,$7c,$7c,$54,$d6,$d6,$d6,$00,$00,$00,$00,$00,$00,$7c,$c6,$06,$06,$3c,$06,
+$06,$06,$c6,$7c,$00,$00,$00,$00,$00,$00,$c6,$c6,$ce,$ce,$d6,$e6,$e6,$c6,$c6,$c6,$00,$00,$00,$00,$38,$38,$c6,$c6,
+$ce,$ce,$d6,$e6,$e6,$c6,$c6,$c6,$00,$00,$00,$00,$00,$00,$e6,$66,$6c,$6c,$78,$78,$6c,$6c,$66,$e6,$00,$00,$00,$00,
+$00,$00,$1e,$36,$66,$c6,$c6,$c6,$c6,$c6,$c6,$c6,$00,$00,$00,$00,$00,$00,$c6,$ee,$fe,$fe,$d6,$c6,$c6,$c6,$c6,$c6,
+$00,$00,$00,$00,$00,$00,$c6,$c6,$c6,$c6,$fe,$c6,$c6,$c6,$c6,$c6,$00,$00,$00,$00,$00,$00,$7c,$c6,$c6,$c6,$c6,$c6,
+$c6,$c6,$c6,$7c,$00,$00,$00,$00,$00,$00,$fe,$c6,$c6,$c6,$c6,$c6,$c6,$c6,$c6,$c6,$00,$00,$00,$00,$00,$00,$fc,$66,
+$66,$66,$7c,$60,$60,$60,$60,$f0,$00,$00,$00,$00,$00,$00,$3c,$66,$c2,$c0,$c0,$c0,$c0,$c2,$66,$3c,$00,$00,$00,$00,
+$00,$00,$7e,$5a,$18,$18,$18,$18,$18,$18,$18,$3c,$00,$00,$00,$00,$00,$00,$c6,$c6,$c6,$c6,$c6,$7e,$06,$06,$c6,$7c,
+$00,$00,$00,$00,$00,$3c,$18,$7e,$db,$db,$db,$db,$db,$7e,$18,$3c,$00,$00,$00,$00,$00,$00,$c6,$c6,$6c,$7c,$38,$38,
+$7c,$6c,$c6,$c6,$00,$00,$00,$00,$00,$00,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$fe,$06,$06,$00,$00,$00,$00,$c6,$c6,
+$c6,$c6,$c6,$7e,$06,$06,$06,$06,$00,$00,$00,$00,$00,$00,$db,$db,$db,$db,$db,$db,$db,$db,$db,$ff,$00,$00,$00,$00,
+$00,$00,$db,$db,$db,$db,$db,$db,$db,$db,$db,$ff,$03,$03,$00,$00,$00,$00,$f8,$b0,$30,$30,$3c,$36,$36,$36,$36,$7c,
+$00,$00,$00,$00,$00,$00,$c3,$c3,$c3,$c3,$f3,$db,$db,$db,$db,$f3,$00,$00,$00,$00,$00,$00,$f0,$60,$60,$60,$7c,$66,
+$66,$66,$66,$fc,$00,$00,$00,$00,$00,$00,$7c,$c6,$06,$26,$3e,$26,$06,$06,$c6,$7c,$00,$00,$00,$00,$00,$00,$ce,$db,
+$db,$db,$fb,$db,$db,$db,$db,$ce,$00,$00,$00,$00,$00,$00,$3f,$66,$66,$66,$3e,$3e,$66,$66,$66,$e7,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$78,$0c,$7c,$cc,$cc,$cc,$76,$00,$00,$00,$00,$00,$02,$06,$3c,$60,$60,$7c,$66,$66,$66,$66,$3c,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$fc,$66,$66,$7c,$66,$66,$fc,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7e,$32,$32,
+$30,$30,$30,$78,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1e,$36,$36,$66,$66,$66,$ff,$c3,$c3,$00,$00,$00,$00,$00,$00,
+$00,$7c,$c6,$fe,$c0,$c0,$c6,$7c,$00,$00,$00,$00,$00,$00,$00,$00,$00,$d6,$d6,$54,$7c,$54,$d6,$d6,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$3c,$66,$06,$0c,$06,$66,$3c,$00,$00,$00,$00,$00,$00,$00,$00,$00,$c6,$c6,$ce,$d6,$e6,$c6,$c6,
+$00,$00,$00,$00,$00,$00,$00,$38,$38,$c6,$c6,$ce,$d6,$e6,$c6,$c6,$00,$00,$00,$00,$00,$00,$00,$00,$00,$e6,$6c,$78,
+$78,$6c,$66,$e6,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1e,$36,$66,$66,$66,$66,$66,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$c6,$ee,$fe,$fe,$d6,$d6,$c6,$00,$00,$00,$00,$00,$00,$00,$00,$00,$c6,$c6,$c6,$fe,$c6,$c6,$c6,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$7c,$c6,$c6,$c6,$c6,$c6,$7c,$00,$00,$00,$00,$00,$00,$00,$00,$00,$fe,$c6,$c6,$c6,$c6,$c6,$c6,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$dc,$66,$66,$66,$66,$66,$7c,$60,$60,$f0,$00,$00,$00,$00,$00,$00,$7c,$c6,$c0,
+$c0,$c0,$c6,$7c,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7e,$5a,$18,$18,$18,$18,$3c,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$c6,$c6,$c6,$c6,$c6,$7e,$06,$06,$c6,$7c,$00,$00,$00,$00,$00,$3c,$18,$7e,$db,$db,$db,$db,$7e,$18,$18,$3c,$00,
+$00,$00,$00,$00,$00,$c6,$6c,$38,$38,$38,$6c,$c6,$00,$00,$00,$00,$00,$00,$00,$00,$00,$cc,$cc,$cc,$cc,$cc,$cc,$fe,
+$06,$06,$00,$00,$00,$00,$00,$00,$00,$c6,$c6,$c6,$c6,$7e,$06,$06,$00,$00,$00,$00,$00,$00,$00,$00,$00,$d6,$d6,$d6,
+$d6,$d6,$d6,$fe,$00,$00,$00,$00,$00,$00,$00,$00,$00,$d6,$d6,$d6,$d6,$d6,$d6,$fe,$03,$03,$00,$00,$00,$00,$00,$00,
+$00,$f8,$b0,$30,$3e,$33,$33,$7e,$00,$00,$00,$00,$00,$00,$00,$00,$00,$c6,$c6,$c6,$f6,$de,$de,$f6,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$f0,$60,$60,$7c,$66,$66,$fc,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3c,$66,$06,$1e,$06,$66,$3c,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$ce,$db,$db,$fb,$db,$db,$ce,$00,$00,$00,$00,$00,$00,$00,$00,$00,$7e,$cc,$cc,
+$fc,$6c,$cc,$ce,$00,$00,$00,$00);
+const kgiFont16Wdt: array[0..256-1] of Byte = (
+$00,$08,$08,$07,$07,$08,$08,$24,$08,$16,$08,$07,$16,$07,$08,$08,$07,$07,$16,$16,$08,$07,$07,$16,$16,$16,$07,$07,
+$07,$07,$07,$07,$00,$24,$16,$07,$07,$07,$07,$13,$24,$24,$08,$16,$23,$07,$32,$07,$07,$16,$07,$07,$07,$07,$07,$07,
+$07,$07,$32,$23,$16,$07,$16,$07,$07,$07,$07,$07,$07,$07,$07,$07,$07,$24,$07,$07,$07,$07,$07,$07,$07,$07,$07,$07,
+$16,$07,$07,$07,$07,$16,$07,$24,$07,$24,$07,$08,$23,$07,$07,$07,$07,$07,$06,$07,$07,$24,$16,$07,$24,$07,$07,$07,
+$07,$07,$07,$07,$07,$07,$16,$07,$07,$07,$07,$16,$32,$16,$07,$07,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+$07,$05,$00,$00,$00,$00,$00,$00,$08,$08,$08,$08,$08,$08,$08,$08,$07,$08,$08,$08,$08,$08,$08,$08,$07,$07,$07,$07,
+$08,$07,$07,$07,$07,$07,$07,$07,$07,$07,$07,$07,$07,$07,$16,$07,$08,$07,$07,$07,$08,$08,$07,$08,$07,$07,$08,$08,
+$07,$16,$07,$16,$08,$07,$07,$16,$07,$07,$07,$16,$07,$07,$07,$07,$07,$07,$16,$07,$08,$07,$07,$07,$07,$08,$08,$07,
+$07,$16,$08,$07);
+
+const kgiWFont8: array[0..256*8-1] of Byte = (
+  $00,$00,$00,$00,$00,$00,$00,$00,$7e,$81,$a5,$81,$bd,$99,$81,$7e,$7e,$ff,$db,$ff,$c3,$e7,$ff,$7e,$6c,$fe,$fe,$fe,
+  $7c,$38,$10,$00,$10,$38,$7c,$fe,$7c,$38,$10,$00,$10,$7c,$10,$fe,$fe,$92,$10,$7c,$00,$10,$38,$7c,$fe,$7c,$10,$7c,
+  $00,$00,$18,$3c,$3c,$18,$00,$00,$ff,$ff,$e7,$c3,$c3,$e7,$ff,$ff,$00,$3c,$66,$42,$42,$66,$3c,$00,$ff,$c3,$99,$bd,
+  $bd,$99,$c3,$ff,$0f,$03,$05,$79,$cc,$cc,$cc,$78,$3c,$66,$66,$66,$3c,$18,$7e,$18,$3e,$30,$3e,$30,$30,$70,$f0,$e0,
+  $7f,$63,$7f,$63,$63,$67,$e6,$c0,$89,$4a,$3c,$e4,$27,$3c,$52,$91,$80,$e0,$f8,$fe,$f8,$e0,$80,$00,$02,$0e,$3e,$fe,
+  $3e,$0e,$02,$00,$18,$3c,$7e,$18,$18,$7e,$3c,$18,$24,$24,$24,$24,$24,$00,$24,$00,$7f,$db,$db,$7b,$1b,$1b,$1b,$00,
+  $3e,$63,$38,$6c,$6c,$38,$86,$fc,$00,$00,$00,$00,$7e,$7e,$7e,$00,$18,$3c,$7e,$18,$7e,$3c,$18,$ff,$18,$3c,$7e,$18,
+  $18,$18,$18,$00,$18,$18,$18,$18,$7e,$3c,$18,$00,$00,$18,$0c,$fe,$0c,$18,$00,$00,$00,$30,$60,$fe,$60,$30,$00,$00,
+  $00,$00,$00,$c0,$c0,$fe,$00,$00,$00,$24,$66,$ff,$66,$24,$00,$00,$00,$18,$3c,$7e,$ff,$ff,$00,$00,$00,$ff,$ff,$7e,
+  $3c,$18,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$3c,$3c,$18,$18,$00,$18,$00,$6c,$6c,$28,$00,$00,$00,$00,$00,
+  $6c,$6c,$fe,$6c,$fe,$6c,$6c,$00,$18,$7e,$c0,$7c,$06,$fc,$18,$00,$00,$c6,$cc,$18,$30,$66,$c6,$00,$38,$6c,$38,$76,
+  $dc,$cc,$76,$00,$30,$30,$60,$00,$00,$00,$00,$00,$18,$30,$60,$60,$60,$30,$18,$00,$60,$30,$18,$18,$18,$30,$60,$00,
+  $00,$66,$3c,$ff,$3c,$66,$00,$00,$00,$18,$18,$7e,$18,$18,$00,$00,$00,$00,$00,$00,$00,$18,$18,$30,$00,$00,$00,$7e,
+  $00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$18,$00,$06,$0c,$18,$30,$60,$c0,$80,$00,$7c,$ce,$de,$f6,$e6,$c6,$7c,$00,
+  $30,$70,$30,$30,$30,$30,$fc,$00,$78,$cc,$0c,$38,$60,$cc,$fc,$00,$78,$cc,$0c,$38,$0c,$cc,$78,$00,$1c,$3c,$6c,$cc,
+  $fe,$0c,$1e,$00,$fc,$c0,$f8,$0c,$0c,$cc,$78,$00,$38,$60,$c0,$f8,$cc,$cc,$78,$00,$fc,$cc,$0c,$18,$30,$30,$30,$00,
+  $78,$cc,$cc,$78,$cc,$cc,$78,$00,$78,$cc,$cc,$7c,$0c,$18,$70,$00,$00,$18,$18,$00,$00,$18,$18,$00,$00,$18,$18,$00,
+  $00,$18,$18,$30,$18,$30,$60,$c0,$60,$30,$18,$00,$00,$00,$7e,$00,$7e,$00,$00,$00,$60,$30,$18,$0c,$18,$30,$60,$00,
+  $3c,$66,$0c,$18,$18,$00,$18,$00,$7c,$c6,$de,$de,$dc,$c0,$7c,$00,$30,$78,$cc,$cc,$fc,$cc,$cc,$00,$fc,$66,$66,$7c,
+  $66,$66,$fc,$00,$3c,$66,$c0,$c0,$c0,$66,$3c,$00,$f8,$6c,$66,$66,$66,$6c,$f8,$00,$fe,$62,$68,$78,$68,$62,$fe,$00,
+  $fe,$62,$68,$78,$68,$60,$f0,$00,$3c,$66,$c0,$c0,$ce,$66,$3a,$00,$cc,$cc,$cc,$fc,$cc,$cc,$cc,$00,$78,$30,$30,$30,
+  $30,$30,$78,$00,$1e,$0c,$0c,$0c,$cc,$cc,$78,$00,$e6,$66,$6c,$78,$6c,$66,$e6,$00,$f0,$60,$60,$60,$62,$66,$fe,$00,
+  $c6,$ee,$fe,$fe,$d6,$c6,$c6,$00,$c6,$e6,$f6,$de,$ce,$c6,$c6,$00,$38,$6c,$c6,$c6,$c6,$6c,$38,$00,$fc,$66,$66,$7c,
+  $60,$60,$f0,$00,$7c,$c6,$c6,$c6,$d6,$7c,$0e,$00,$fc,$66,$66,$7c,$6c,$66,$e6,$00,$7c,$c6,$e0,$78,$0e,$c6,$7c,$00,
+  $fc,$b4,$30,$30,$30,$30,$78,$00,$cc,$cc,$cc,$cc,$cc,$cc,$fc,$00,$cc,$cc,$cc,$cc,$cc,$78,$30,$00,$c6,$c6,$c6,$c6,
+  $d6,$fe,$6c,$00,$c6,$c6,$6c,$38,$6c,$c6,$c6,$00,$cc,$cc,$cc,$78,$30,$30,$78,$00,$fe,$c6,$8c,$18,$32,$66,$fe,$00,
+  $78,$60,$60,$60,$60,$60,$78,$00,$c0,$60,$30,$18,$0c,$06,$02,$00,$78,$18,$18,$18,$18,$18,$78,$00,$10,$38,$6c,$c6,
+  $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$ff,$30,$30,$18,$00,$00,$00,$00,$00,$00,$00,$78,$0c,$7c,$cc,$76,$00,
+  $e0,$60,$60,$7c,$66,$66,$dc,$00,$00,$00,$78,$cc,$c0,$cc,$78,$00,$1c,$0c,$0c,$7c,$cc,$cc,$76,$00,$00,$00,$78,$cc,
+  $fc,$c0,$78,$00,$38,$6c,$64,$f0,$60,$60,$f0,$00,$00,$00,$76,$cc,$cc,$7c,$0c,$f8,$e0,$60,$6c,$76,$66,$66,$e6,$00,
+  $30,$00,$70,$30,$30,$30,$78,$00,$0c,$00,$1c,$0c,$0c,$cc,$cc,$78,$e0,$60,$66,$6c,$78,$6c,$e6,$00,$70,$30,$30,$30,
+  $30,$30,$78,$00,$00,$00,$cc,$fe,$fe,$d6,$d6,$00,$00,$00,$b8,$cc,$cc,$cc,$cc,$00,$00,$00,$78,$cc,$cc,$cc,$78,$00,
+  $00,$00,$dc,$66,$66,$7c,$60,$f0,$00,$00,$76,$cc,$cc,$7c,$0c,$1e,$00,$00,$dc,$76,$62,$60,$f0,$00,$00,$00,$7c,$c0,
+  $70,$1c,$f8,$00,$10,$30,$fc,$30,$30,$34,$18,$00,$00,$00,$cc,$cc,$cc,$cc,$76,$00,$00,$00,$cc,$cc,$cc,$78,$30,$00,
+  $00,$00,$c6,$c6,$d6,$fe,$6c,$00,$00,$00,$c6,$6c,$38,$6c,$c6,$00,$00,$00,$cc,$cc,$cc,$7c,$0c,$f8,$00,$00,$fc,$98,
+  $30,$64,$fc,$00,$1c,$30,$30,$e0,$30,$30,$1c,$00,$18,$18,$18,$00,$18,$18,$18,$00,$e0,$30,$30,$1c,$30,$30,$e0,$00,
+  $76,$dc,$00,$00,$00,$00,$00,$00,$00,$10,$38,$6c,$c6,$c6,$fe,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+  $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+  $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+  $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+  $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+  $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+  $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+  $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+  $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+  $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+  $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+  $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+  $48,$00,$fc,$c0,$c0,$f8,$c0,$fe,$a0,$d0,$90,$90,$90,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+  $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+  $00,$00,$00,$00,$00,$00,$00,$00,$22,$88,$22,$88,$22,$88,$22,$88,$55,$aa,$55,$aa,$55,$aa,$55,$aa,$ff,$ab,$d5,$ab,
+  $d5,$ab,$d5,$ff,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$f0,$10,$10,$10,$10,$10,$f0,$10,$f0,$10,$10,$10,
+  $14,$14,$14,$14,$f4,$14,$14,$14,$00,$00,$00,$00,$fc,$14,$14,$14,$48,$00,$78,$cc,$fc,$c0,$7c,$00,$14,$14,$f4,$04,
+  $f4,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$00,$00,$fc,$04,$f4,$14,$14,$14,$14,$14,$f4,$04,$fc,$00,$00,$00,
+  $14,$14,$14,$14,$fc,$00,$00,$00,$10,$10,$f0,$10,$f0,$00,$00,$00,$00,$00,$00,$00,$f0,$10,$10,$10,$0e,$1e,$36,$66,
+  $fe,$c6,$c6,$00,$fc,$c0,$c0,$fc,$c6,$c6,$fc,$00,$f8,$cc,$cc,$fc,$c6,$c6,$fc,$00,$fc,$c0,$c0,$c0,$c0,$c0,$c0,$00,
+  $7e,$66,$66,$66,$66,$66,$ff,$c3,$fc,$c0,$c0,$f8,$c0,$c0,$fe,$00,$db,$db,$7e,$18,$7e,$db,$db,$00,$3c,$66,$06,$3c,
+  $06,$c6,$7c,$00,$c6,$c6,$ce,$de,$f6,$e6,$c6,$00,$d6,$c6,$ce,$de,$f6,$e6,$c6,$00,$c6,$cc,$d8,$f8,$cc,$c6,$c6,$00,
+  $06,$0e,$1e,$36,$66,$c6,$c6,$00,$c6,$ee,$fe,$d6,$c6,$c6,$c6,$00,$c6,$c6,$c6,$fe,$c6,$c6,$c6,$00,$7c,$c6,$c6,$c6,
+  $c6,$c6,$7c,$00,$fe,$c6,$c6,$c6,$c6,$c6,$c6,$00,$fc,$c6,$c6,$fc,$c0,$c0,$c0,$00,$7c,$c6,$c0,$c0,$c0,$c6,$7c,$00,
+  $fc,$30,$30,$30,$30,$30,$30,$00,$c6,$c6,$c6,$7e,$06,$c6,$7c,$00,$18,$7e,$db,$db,$db,$7e,$18,$00,$c3,$66,$3c,$18,
+  $3c,$66,$c3,$00,$cc,$cc,$cc,$cc,$cc,$cc,$fe,$06,$c6,$c6,$c6,$7e,$06,$06,$06,$00,$d6,$d6,$d6,$d6,$d6,$d6,$fe,$00,
+  $d6,$d6,$d6,$d6,$d6,$d6,$ff,$03,$f0,$30,$30,$3e,$33,$33,$3e,$00,$c2,$c2,$c2,$f2,$da,$da,$f2,$00,$c0,$c0,$c0,$fc,
+  $c6,$c6,$fc,$00,$7c,$c6,$06,$1e,$06,$c6,$7c,$00,$ce,$db,$db,$fb,$db,$db,$ce,$00,$7e,$c6,$c6,$7e,$36,$66,$c6,$00,
+  $00,$00,$78,$0c,$7c,$cc,$7e,$00,$04,$78,$c0,$f8,$cc,$cc,$78,$00,$00,$00,$f8,$cc,$f8,$c6,$fc,$00,$00,$00,$fc,$c0,
+  $c0,$c0,$c0,$00,$00,$00,$7e,$66,$66,$66,$ff,$c3,$00,$00,$78,$cc,$fc,$c0,$7c,$00,$00,$00,$db,$7e,$18,$7e,$db,$00,
+  $00,$00,$78,$cc,$18,$cc,$78,$00,$00,$00,$cc,$cc,$dc,$ec,$cc,$00,$30,$00,$cc,$cc,$dc,$ec,$cc,$00,$00,$00,$cc,$d8,
+  $f0,$cc,$cc,$00,$00,$00,$0e,$1e,$36,$66,$c6,$00,$00,$00,$c6,$ee,$d6,$c6,$c6,$00,$00,$00,$cc,$cc,$fc,$cc,$cc,$00,
+  $00,$00,$78,$cc,$cc,$cc,$78,$00,$00,$00,$fc,$cc,$cc,$cc,$cc,$00,$00,$00,$f8,$cc,$cc,$f8,$c0,$c0,$00,$00,$78,$cc,
+  $c0,$cc,$78,$00,$00,$00,$fc,$30,$30,$30,$30,$00,$00,$00,$cc,$cc,$7c,$0c,$cc,$78,$00,$18,$7e,$db,$db,$7e,$18,$18,
+  $00,$00,$c6,$6c,$38,$6c,$c6,$00,$00,$00,$cc,$cc,$cc,$cc,$fe,$06,$00,$00,$cc,$cc,$7c,$0c,$0c,$00,$00,$00,$d6,$d6,
+  $d6,$d6,$fe,$00,$00,$00,$d6,$d6,$d6,$d6,$ff,$03,$00,$00,$f0,$30,$3e,$33,$3e,$00,$00,$00,$c2,$c2,$f2,$da,$f2,$00,
+  $00,$00,$c0,$c0,$f8,$cc,$f8,$00,$00,$00,$7c,$c6,$1e,$c6,$7c,$00,$00,$00,$ce,$db,$fb,$db,$ce,$00,$00,$00,$7c,$cc,
+  $7c,$6c,$cc,$00);
+const kgiWFont8Wdt: array[0..256-1] of Byte = (
+  $00,$08,$08,$07,$07,$07,$07,$24,$08,$16,$08,$08,$16,$07,$08,$08,$07,$07,$16,$24,$08,$08,$16,$08,$16,$16,$07,$07,
+  $07,$08,$08,$08,$00,$24,$15,$07,$07,$07,$07,$13,$14,$14,$08,$16,$23,$16,$32,$07,$07,$06,$06,$06,$07,$06,$06,$06,
+  $06,$06,$32,$23,$05,$16,$15,$16,$07,$06,$07,$07,$07,$07,$07,$07,$06,$14,$07,$07,$07,$07,$07,$07,$07,$07,$07,$07,
+  $06,$06,$06,$07,$07,$06,$07,$14,$07,$14,$07,$08,$23,$07,$07,$06,$07,$06,$06,$07,$07,$14,$06,$07,$14,$07,$06,$06,
+  $07,$07,$07,$06,$06,$07,$06,$07,$07,$06,$06,$06,$32,$06,$07,$07,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+  $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+  $07,$04,$00,$00,$00,$00,$00,$00,$08,$08,$08,$08,$08,$08,$08,$08,$06,$08,$08,$08,$08,$08,$08,$08,$07,$07,$07,$06,
+  $08,$07,$08,$07,$07,$07,$07,$07,$07,$07,$07,$07,$07,$07,$06,$07,$08,$08,$07,$07,$07,$08,$08,$07,$07,$07,$08,$07,
+  $07,$06,$07,$06,$08,$06,$08,$06,$06,$06,$06,$07,$07,$06,$06,$06,$06,$06,$06,$06,$08,$07,$07,$06,$07,$08,$08,$07,
+  $06,$07,$08,$06);
+
+
+function createFontTexture (const font: PByte; const fontwdt: PByte; hgt: Integer; prop: Boolean): GLuint;
 const
   Width = 16*8;
-  Height = 16*8;
+  Height = 16*16;
 var
   tex, tpp: PByte;
   b: Byte;
@@ -230,14 +618,15 @@ var
   x, y, dx, dy: Integer;
 begin
   GetMem(tex, Width*Height*4);
+  FillChar(tex^, Width*Height*4, 0);
 
   for cc := 0 to 255 do
   begin
     x := (cc mod 16)*8;
-    y := (cc div 16)*8;
-    for dy := 0 to 7 do
+    y := (cc div 16)*16;
+    for dy := 0 to hgt-1 do
     begin
-      b := font[cc*8+dy];
+      b := font[cc*hgt+dy];
       if prop then b := b shl (fontwdt[cc] shr 4);
       tpp := tex+((y+dy)*(Width*4))+x*4;
       for dx := 0 to 7 do