Fun With Unicode Glyphs

Share your advanced PureBasic knowledge/code with the community.
User avatar
bgeraghty
User
User
Posts: 52
Joined: Wed Apr 02, 2014 12:45 am
Location: irc.ibotched.it:+6697
Contact:

Fun With Unicode Glyphs

Post by bgeraghty »

Hello!

With PureBasic going Unicode-Exclusive, I've been looking into interesting ways to utilize the massive character set that is Unicode. While this a bit limited on Windows+Console as Unicode is kind of a gray-area there, there are quite a few possibilities from "Ascii"-Art to something like a game, which would rely only on unicode-glyphs and not any graphics if sticking to a custom font, or one that supports some or all of the unicode set.

Here's a little desktop toy app that uses some unicode box-drawing characters to form a retro-digital clock face. The sound lines are commented out so I don't need to transfer those, you can plug in your own if you want to use it that way. The only things used are a main window, and 5 Text Gadgets (No buttons, no graphics, etc.) https://streamable.com/icn9i9

Code: Select all

EnableExplicit
Enumeration Gadget_List
  #MainWindow=0
  #Clock_Face
  #MenuBttn_1
  #MenuBttn_2
  #MenuBttn_3
  #MenuBttn_4
  #Gadget_Max
EndEnumeration  
Enumeration Output_Font
  #Thin=1
  #Thick
  #Double
EndEnumeration 
Global Dim Gadgets.i(#Gadget_Max) : InitSound()
Global Font,h12=#False,CentiSecond=0,LastSecond$="",Quit=0,CurrentFont=#Thin
;Global S1=LoadSound(#PB_Any,"Tick1.wav")
;Global S2=LoadSound(#PB_Any,"Alarm.wav")
;Global S3=LoadSound(#PB_Any,"Exit.wav")
Global ActiveColor=RGB(255,0,0),InActiveCol=RGB(100,0,0)
Global AlarmTime.s="",AlarmMode.b=#False,Alarmed.b=#False
Global Dim AnalogDig_Sm.s(12,5)
Macro ThinFont()
  AnalogDig_Sm(00,00)=" ── ":AnalogDig_Sm(01,00)="    ":AnalogDig_Sm(02,00)=" ── ":AnalogDig_Sm(03,00)=" ── ":AnalogDig_Sm(04,00)="    ":AnalogDig_Sm(05,00)=" ── "
  AnalogDig_Sm(00,01)="│  │":AnalogDig_Sm(01,01)="   │":AnalogDig_Sm(02,01)="   │":AnalogDig_Sm(03,01)="   │":AnalogDig_Sm(04,01)="│  │":AnalogDig_Sm(05,01)="│   "
  AnalogDig_Sm(00,02)="    ":AnalogDig_Sm(01,02)="    ":AnalogDig_Sm(02,02)=" ── ":AnalogDig_Sm(03,02)=" ── ":AnalogDig_Sm(04,02)=" ── ":AnalogDig_Sm(05,02)=" ── "
  AnalogDig_Sm(00,03)="│  │":AnalogDig_Sm(01,03)="   │":AnalogDig_Sm(02,03)="│   ":AnalogDig_Sm(03,03)="   │":AnalogDig_Sm(04,03)="   │":AnalogDig_Sm(05,03)="   │"
  AnalogDig_Sm(00,04)=" ── ":AnalogDig_Sm(01,04)="    ":AnalogDig_Sm(02,04)=" ── ":AnalogDig_Sm(03,04)=" ── ":AnalogDig_Sm(04,04)="    ":AnalogDig_Sm(05,04)=" ── "
  AnalogDig_Sm(06,00)=" ── ":AnalogDig_Sm(07,00)=" ── ":AnalogDig_Sm(08,00)=" ── ":AnalogDig_Sm(09,00)=" ── ":AnalogDig_Sm(10,00)=" " :AnalogDig_Sm(11,00)=" "
  AnalogDig_Sm(06,01)="│   ":AnalogDig_Sm(07,01)="   │":AnalogDig_Sm(08,01)="│  │":AnalogDig_Sm(09,01)="│  │":AnalogDig_Sm(10,01)="•" :AnalogDig_Sm(11,01)=" "
  AnalogDig_Sm(06,02)=" ── ":AnalogDig_Sm(07,02)="    ":AnalogDig_Sm(08,02)=" ── ":AnalogDig_Sm(09,02)=" ── ":AnalogDig_Sm(10,02)=" " :AnalogDig_Sm(11,02)=" "
  AnalogDig_Sm(06,03)="│  │":AnalogDig_Sm(07,03)="   │":AnalogDig_Sm(08,03)="│  │":AnalogDig_Sm(09,03)="   │":AnalogDig_Sm(10,03)="•" :AnalogDig_Sm(11,03)=" "
  AnalogDig_Sm(06,04)=" ── ":AnalogDig_Sm(07,04)="    ":AnalogDig_Sm(08,04)=" ── ":AnalogDig_Sm(09,04)=" ── ":AnalogDig_Sm(10,04)=" " :AnalogDig_Sm(11,04)="•"
EndMacro
Macro ThickFont()
  AnalogDig_Sm(00,00)=" ━━ ":AnalogDig_Sm(01,00)="    ":AnalogDig_Sm(02,00)=" ━━ ":AnalogDig_Sm(03,00)=" ━━ ":AnalogDig_Sm(04,00)="    ":AnalogDig_Sm(05,00)=" ━━ "
  AnalogDig_Sm(00,01)="┃  ┃":AnalogDig_Sm(01,01)="   ┃":AnalogDig_Sm(02,01)="   ┃":AnalogDig_Sm(03,01)="   ┃":AnalogDig_Sm(04,01)="┃  ┃":AnalogDig_Sm(05,01)="┃   "
  AnalogDig_Sm(00,02)="    ":AnalogDig_Sm(01,02)="    ":AnalogDig_Sm(02,02)=" ━━ ":AnalogDig_Sm(03,02)=" ━━ ":AnalogDig_Sm(04,02)=" ━━ ":AnalogDig_Sm(05,02)=" ━━ "
  AnalogDig_Sm(00,03)="┃  ┃":AnalogDig_Sm(01,03)="   ┃":AnalogDig_Sm(02,03)="┃   ":AnalogDig_Sm(03,03)="   ┃":AnalogDig_Sm(04,03)="   ┃":AnalogDig_Sm(05,03)="   ┃"
  AnalogDig_Sm(00,04)=" ━━ ":AnalogDig_Sm(01,04)="    ":AnalogDig_Sm(02,04)=" ━━ ":AnalogDig_Sm(03,04)=" ━━ ":AnalogDig_Sm(04,04)="    ":AnalogDig_Sm(05,04)=" ━━ "
  AnalogDig_Sm(06,00)=" ━━ ":AnalogDig_Sm(07,00)=" ━━ ":AnalogDig_Sm(08,00)=" ━━ ":AnalogDig_Sm(09,00)=" ━━ ":AnalogDig_Sm(10,00)=" " :AnalogDig_Sm(11,00)=" "
  AnalogDig_Sm(06,01)="┃   ":AnalogDig_Sm(07,01)="   ┃":AnalogDig_Sm(08,01)="┃  ┃":AnalogDig_Sm(09,01)="┃  ┃":AnalogDig_Sm(10,01)="•" :AnalogDig_Sm(11,01)=" "
  AnalogDig_Sm(06,02)=" ━━ ":AnalogDig_Sm(07,02)="    ":AnalogDig_Sm(08,02)=" ━━ ":AnalogDig_Sm(09,02)=" ━━ ":AnalogDig_Sm(10,02)=" " :AnalogDig_Sm(11,02)=" "
  AnalogDig_Sm(06,03)="┃  ┃":AnalogDig_Sm(07,03)="   ┃":AnalogDig_Sm(08,03)="┃  ┃":AnalogDig_Sm(09,03)="   ┃":AnalogDig_Sm(10,03)="•" :AnalogDig_Sm(11,03)=" "
  AnalogDig_Sm(06,04)=" ━━ ":AnalogDig_Sm(07,04)="    ":AnalogDig_Sm(08,04)=" ━━ ":AnalogDig_Sm(09,04)=" ━━ ":AnalogDig_Sm(10,04)=" " :AnalogDig_Sm(11,04)="•"
EndMacro  
Macro DoubleFont()
  AnalogDig_Sm(00,00)=" ══ ":AnalogDig_Sm(01,00)="    ":AnalogDig_Sm(02,00)=" ══ ":AnalogDig_Sm(03,00)=" ══ ":AnalogDig_Sm(04,00)="    ":AnalogDig_Sm(05,00)=" ══ "
  AnalogDig_Sm(00,01)="║  ║":AnalogDig_Sm(01,01)="   ║":AnalogDig_Sm(02,01)="   ║":AnalogDig_Sm(03,01)="   ║":AnalogDig_Sm(04,01)="║  ║":AnalogDig_Sm(05,01)="║   "
  AnalogDig_Sm(00,02)="    ":AnalogDig_Sm(01,02)="    ":AnalogDig_Sm(02,02)=" ══ ":AnalogDig_Sm(03,02)=" ══ ":AnalogDig_Sm(04,02)=" ══ ":AnalogDig_Sm(05,02)=" ══ "
  AnalogDig_Sm(00,03)="║  ║":AnalogDig_Sm(01,03)="   ║":AnalogDig_Sm(02,03)="║   ":AnalogDig_Sm(03,03)="   ║":AnalogDig_Sm(04,03)="   ║":AnalogDig_Sm(05,03)="   ║"
  AnalogDig_Sm(00,04)=" ══ ":AnalogDig_Sm(01,04)="    ":AnalogDig_Sm(02,04)=" ══ ":AnalogDig_Sm(03,04)=" ══ ":AnalogDig_Sm(04,04)="    ":AnalogDig_Sm(05,04)=" ══ "
  AnalogDig_Sm(06,00)=" ══ ":AnalogDig_Sm(07,00)=" ══ ":AnalogDig_Sm(08,00)=" ══ ":AnalogDig_Sm(09,00)=" ══ ":AnalogDig_Sm(10,00)=" " :AnalogDig_Sm(11,00)=" "
  AnalogDig_Sm(06,01)="║   ":AnalogDig_Sm(07,01)="   ║":AnalogDig_Sm(08,01)="║  ║":AnalogDig_Sm(09,01)="║  ║":AnalogDig_Sm(10,01)="•" :AnalogDig_Sm(11,01)=" "
  AnalogDig_Sm(06,02)=" ══ ":AnalogDig_Sm(07,02)="    ":AnalogDig_Sm(08,02)=" ══ ":AnalogDig_Sm(09,02)=" ══ ":AnalogDig_Sm(10,02)=" " :AnalogDig_Sm(11,02)=" "
  AnalogDig_Sm(06,03)="║  ║":AnalogDig_Sm(07,03)="   ║":AnalogDig_Sm(08,03)="║  ║":AnalogDig_Sm(09,03)="   ║":AnalogDig_Sm(10,03)="•" :AnalogDig_Sm(11,03)=" "
  AnalogDig_Sm(06,04)=" ══ ":AnalogDig_Sm(07,04)="    ":AnalogDig_Sm(08,04)=" ══ ":AnalogDig_Sm(09,04)=" ══ ":AnalogDig_Sm(10,04)=" " :AnalogDig_Sm(11,04)="•"
EndMacro  
Procedure.s DigitPrintSM(ValAsStr.s,DateMode.b=#False)
  Define DX,DY,Result$=" "
  Dim Seq.i(Len(ValAsStr))
  For DX=0 To Len(ValAsStr)-1
    Define C$=Mid(ValAsStr,DX+1,1)
    If (C$<>"") And
       ((Bool(Val(C$)<>0)) Or (C$="0"))
      Seq(DX)=Val(C$)
    ElseIf C$ = ":":Seq(DX)=10
    ElseIf C$ = ".":Seq(DX)=11
    EndIf
  Next
  For DY = 0 To ArraySize(AnalogDig_Sm(),2)-1
    For DX=0 To Len(ValAsStr)-1
      Result$+AnalogDig_Sm(Seq(DX),DY)+Space(1)
    Next
    Result$=Result$+#CRLF$+" "
  Next
  ProcedureReturn Result$
EndProcedure
Procedure AlarmGo(*Null)
  AlarmMode=#True
  While AlarmMode
    ;PlaySound(S2,#PB_Sound_MultiChannel,100)
    SetGadgetColor(Gadgets(#MenuBttn_2),#PB_Gadget_FrontColor,InActiveCol)
    SetGadgetColor(Gadgets(#MenuBttn_2),#PB_Gadget_BackColor,#Red)
    SetGadgetColor(Gadgets(#Clock_Face),#PB_Gadget_FrontColor,InActiveCol)
    Delay(1000)
    ;PlaySound(S2,#PB_Sound_MultiChannel,100)
    SetGadgetColor(Gadgets(#MenuBttn_2),#PB_Gadget_FrontColor,ActiveColor)
    SetGadgetColor(Gadgets(#MenuBttn_2),#PB_Gadget_BackColor,#Black)
    SetGadgetColor(Gadgets(#Clock_Face),#PB_Gadget_FrontColor,#Red)
    Delay(1000)
  Wend
EndProcedure  
Procedure AlarmSet(*Null)
  AlarmTime=""
  Protected CurrH$=FormatDate("%hh",Date()),
            CurrM$=FormatDate("%ii",Date()),
            DefAT$
  If Val(CurrM$) <= 55
    DefAT$=CurrH$+":"+RSet(Str(Val(CurrM$)+5),2,"0")
  Else
    DefAT$=RSet(Str(Val(CurrH$)+1),2,"0")+":05"
  EndIf
  AlarmTime=InputRequester("Choose Time For Alarm","Use 24-Hour Format (18:24 for 6:24pm etc)",DefAt$)
  If Trim(AlarmTime)<>"": 
    Alarmed=#True
    SetGadgetColor(Gadgets(#MenuBttn_2),#PB_Gadget_FrontColor,ActiveColor)
  EndIf
EndProcedure
Procedure.s TimeSmall()
  Define CS=0,CS$,Second$=FormatDate("%ss",Date())
  If Second$ <> LastSecond$
    LastSecond$=Second$
    CentiSecond=ElapsedMilliseconds()
    If Not AlarmMode
      ;PlaySound(S1,#PB_Sound_MultiChannel,40)
    EndIf  
  EndIf 
  CS=ElapsedMilliseconds()-CentiSecond
  Define Hour.s=FormatDate("%hh",Date())
  If h12
    Define iHr.i=Val(Hour)
    If iHr > 12 
      iHr-12 : Hour=RSet(Str(iHr),2,"0")
    EndIf
  EndIf
  CS$=RSet(Str((CS/10)*0.6),2,"0")
  Define Result$=DigitPrintSM(Hour+FormatDate(":%ii:%ss:",Date())+CS$)
  If Alarmed And AlarmTime=FormatDate("%hh:%ii",Date())
    CreateThread(@AlarmGo(),#Null) : Alarmed=#False 
  EndIf
  ProcedureReturn Left(Result$,Len(Result$)-2)
EndProcedure  
Procedure TimeThread(*Null)
  Repeat
    If Not Quit
      SetGadgetText(Gadgets(#Clock_Face),TimeSmall()):Delay(55)
    EndIf   
  ForEver 
EndProcedure
Procedure LoadArtFont(FontID)
  Select FontID
    Case #Thin
      ThinFont()
    Case #Thick
      ThickFont()
    Case #Double
      DoubleFont()
  EndSelect 
EndProcedure
Procedure CycleDisplayFont(*Null)
  Select CurrentFont
    Case #Thin  :CurrentFont=#Thick
    Case #Thick :CurrentFont=#Double
    Case #Double:CurrentFont=#Thin
  EndSelect
  LoadArtFont(CurrentFont)
EndProcedure  
Procedure BrokenDissolve(*Null)
  Protected X,Y,Z
  Dim RS.s(5)
  RS(0)="⚠⏳☏▒!"
  RS(1)="=⛏∩░☔"
  RS(2)="▒☣∑$&"
  RS(3)="░☕⏏]☔"
  RS(4)="☢*░☘↊"
  Repeat 
    X=Random(9,0):Y=Random(4,0):Z=Random(4,0)
    AnalogDig_Sm(X,Y)=RS(Z)
    Delay(10)
  ForEver
EndProcedure
Procedure QuitClean(*Null)
  Protected Ct1
  ;PlaySound(S3,#PB_Sound_MultiChannel,100)
  CreateThread(@BrokenDissolve(),#Null)
  For Ct1=0 To 2
    SetGadgetColor(Gadgets(#MenuBttn_4),#PB_Gadget_FrontColor,InactiveCol)
    Delay(255)
    SetGadgetColor(Gadgets(#MenuBttn_4),#PB_Gadget_FrontColor,ActiveColor)
    Delay(255)
  Next
  Quit=1
EndProcedure
Procedure.i SetWindowTransparency(Window.i, transparency.i);0-255
  If IsWindow(Window) 
    Protected WindowID = WindowID(Window)
    SetWindowLongPtr_(WindowID,#GWL_EXSTYLE,#WS_EX_LAYERED)
    SetLayeredWindowAttributes_(WindowID,0,transparency,#LWA_ALPHA)
  EndIf 
EndProcedure
ThinFont()
Gadgets(#MainWindow)=OpenWindow(#PB_Any, 200, 200, 500, 125,"",#PB_Window_BorderLess) 
SetWindowColor(Gadgets(#MainWindow),#Black) : StickyWindow(Gadgets(#MainWindow),1) : SetWindowTransparency(Gadgets(#MainWindow),200)
Gadgets(#Clock_Face)=TextGadget(#PB_Any,5,0,480,100,TimeSmall())
Gadgets(#MenuBttn_1)=TextGadget(#PB_Any,000,100,120,20,"☀/☾",#PB_Text_Center|#SS_NOTIFY)
Gadgets(#MenuBttn_2)=TextGadget(#PB_Any,120,100,120,20,"⏰",#PB_Text_Center|#SS_NOTIFY)
Gadgets(#MenuBttn_3)=TextGadget(#PB_Any,240,100,120,20,"⚙",#PB_Text_Center|#SS_NOTIFY)
Gadgets(#MenuBttn_4)=TextGadget(#PB_Any,360,100,120,20,"☠",#PB_Text_Center|#SS_NOTIFY)
Font=LoadFont(#PB_Any,"Consolas",14)
SetGadgetFont(Gadgets(#Clock_Face),FontID(Font))
SetGadgetFont(Gadgets(#MenuBttn_1),FontID(Font))
SetGadgetFont(Gadgets(#MenuBttn_2),FontID(Font))
SetGadgetFont(Gadgets(#MenuBttn_3),FontID(Font))
SetGadgetFont(Gadgets(#MenuBttn_4),FontID(Font))
SetGadgetColor(Gadgets(#Clock_Face),#PB_Gadget_BackColor,#Black)
SetGadgetColor(Gadgets(#Clock_Face),#PB_Gadget_FrontColor,ActiveColor)
SetGadgetColor(Gadgets(#MenuBttn_1),#PB_Gadget_BackColor,#Black)
SetGadgetColor(Gadgets(#MenuBttn_1),#PB_Gadget_FrontColor,InActiveCol)
SetGadgetColor(Gadgets(#MenuBttn_2),#PB_Gadget_BackColor,#Black)
SetGadgetColor(Gadgets(#MenuBttn_2),#PB_Gadget_FrontColor,InActiveCol)
SetGadgetColor(Gadgets(#MenuBttn_3),#PB_Gadget_BackColor,#Black)
SetGadgetColor(Gadgets(#MenuBttn_3),#PB_Gadget_FrontColor,ActiveColor)
SetGadgetColor(Gadgets(#MenuBttn_4),#PB_Gadget_BackColor,#Black)
SetGadgetColor(Gadgets(#MenuBttn_4),#PB_Gadget_FrontColor,ActiveColor)
CreateThread(@TimeThread(),#Null)
Repeat
  Select WaitWindowEvent()
    Case #WM_LBUTTONDOWN 
      SendMessage_(WindowID(Gadgets(#MainWindow)), #WM_NCLBUTTONDOWN, #HTCAPTION, 0) 
    Case #PB_Event_Gadget
      Select EventGadget()
        Case Gadgets(#MenuBttn_1)
          If h12 : h12=#False : SetGadgetColor(Gadgets(#MenuBttn_1),#PB_Gadget_FrontColor,InActiveCol) 
          Else : h12=#True : SetGadgetColor(Gadgets(#MenuBttn_1),#PB_Gadget_FrontColor,ActiveColor) : EndIf
        Case Gadgets(#MenuBttn_2)  
          If AlarmMode 
            AlarmMode=#False
            SetGadgetColor(Gadgets(#Clock_Face),#PB_Gadget_FrontColor,ActiveColor)
            SetGadgetColor(Gadgets(#MenuBttn_2),#PB_Gadget_FrontColor,InActiveCol)
          ElseIf Alarmed
            Alarmed=#False
            SetGadgetColor(Gadgets(#MenuBttn_2),#PB_Gadget_FrontColor,InActiveCol)
          Else
            CreateThread(@AlarmSet(),#Null)
          EndIf
        Case Gadgets(#MenuBttn_3)
          CreateThread(@CycleDisplayFont(),#Null)
        Case Gadgets(#MenuBttn_4)
          CreateThread(@QuitClean(),#Null)
      EndSelect
    Case #PB_Event_CloseWindow
      Quit=1
  EndSelect    
Until Quit
End
Note: this was done originally using Unifont as the base-font, but is modified to work with Consolas which should be built-in to Windows. Unifont looks a little better but is a 12MB+ TTF Font.

Anybody else have any ideas for making Unicode characters do things they weren't necessarily designed to?
SolveMyIssue_() - No QuickHelp available.
User avatar
jacdelad
Addict
Addict
Posts: 1431
Joined: Wed Feb 03, 2021 12:46 pm
Location: Planet Riesa
Contact:

Re: Fun With Unicode Glyphs

Post by jacdelad »

Hehe, nice!
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
User avatar
SPH
Enthusiast
Enthusiast
Posts: 268
Joined: Tue Jan 04, 2011 6:21 pm

Re: Fun With Unicode Glyphs

Post by SPH »

Nice ! (brice ?) 🤗
http://HexaScrabble.com/
!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Portable LENOVO ideapad 110-17ACL 64 bits
Version de PB : 5.73LTS - 32 bits
Fred
Administrator
Administrator
Posts: 16616
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Fun With Unicode Glyphs

Post by Fred »

Cool stuff
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Fun With Unicode Glyphs

Post by Mijikai »

Nice :D
Thanks for sharing, i especially like the terminat(or)ion effect 8)
User avatar
minimy
Enthusiast
Enthusiast
Posts: 344
Joined: Mon Jul 08, 2013 8:43 pm

Re: Fun With Unicode Glyphs

Post by minimy »

Nice demo! I like old school retro software. :mrgreen:
Thanks for share
If translation=Error: reply="Sorry, Im Spanish": Endif
Post Reply