From fef632c71084b1574d8d6341f47cb19e04f5ede4 Mon Sep 17 00:00:00 2001 From: Ketmar Dark Date: Tue, 3 Oct 2017 12:10:24 +0300 Subject: [PATCH] FlexUI: added 8/14/16 winN/winN-prop fonts; removed horizontal wrapping 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 | 9 + src/flexui/fui_ctls.pas | 286 ++++++++++----- src/flexui/fui_flexlay.pas | 621 ++++++++++---------------------- src/flexui/fui_gfx_gl.pas | 20 +- src/flexui/fui_gfx_gl_fonts.inc | 399 +++++++++++++++++++- 5 files changed, 787 insertions(+), 548 deletions(-) diff --git a/src/flexui/fui_common.pas b/src/flexui/fui_common.pas index 744ddff..0c80915 100644 --- a/src/flexui/fui_common.pas +++ b/src/flexui/fui_common.pas @@ -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; diff --git a/src/flexui/fui_ctls.pas b/src/flexui/fui_ctls.pas index 7969a26..7f722fe 100644 --- a/src/flexui/fui_ctls.pas +++ b/src/flexui/fui_ctls.pas @@ -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'); diff --git a/src/flexui/fui_flexlay.pas b/src/flexui/fui_flexlay.pas index fb470c4..a941f55 100644 --- a/src/flexui/fui_flexlay.pas +++ b/src/flexui/fui_flexlay.pas @@ -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. diff --git a/src/flexui/fui_gfx_gl.pas b/src/flexui/fui_gfx_gl.pas index f70e789..1f08d3a 100644 --- a/src/flexui/fui_gfx_gl.pas +++ b/src/flexui/fui_gfx_gl.pas @@ -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; diff --git a/src/flexui/fui_gfx_gl_fonts.inc b/src/flexui/fui_gfx_gl_fonts.inc index c3372e2..b520d47 100644 --- a/src/flexui/fui_gfx_gl_fonts.inc +++ b/src/flexui/fui_gfx_gl_fonts.inc @@ -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 -- 2.29.2