[Matrix LED]Bài 13: Thiết kế bộ font tiếng việt

Một trong các vấn đề cũng rất được quan tâm đó là hiển thị bộ font đầy đủ tiếng Việt. Không những hiển thị được, việc nhập liệu tiếng việt vào cũng là 1 vấn đề quan trong.

Ngay nay, chuẩn UTF-8 đã rất phổ biến, các trình dịch và phần mềm editer cũng hỗ trợ utf-8 rất nhiều. Vậy nên, ngay từ bây giờ, chúng ta sẽ thiết kế bộ font tiếng việt follow theo chuẩn UTF-8 luôn nhé !

Khả năng của kiểu mã hóa font UTF-8 là độ dài của byte mã hóa không cố định, nó có thể là 1byte, 2byte, 3 byte, 4byte và nhiều hơn nữa nếu muốn, nên nó tiết kiệm được không gian lưu trữ hơn so với unicode 32byte ! Ngoài ra nó cũng tương thích hoàn toàn với bộ mã ASCII

Nói chung, minh cũng không giới thiệu về cách mã hóa UTF-8 làm gì vì nó cũng chả cần thiết lắm. Chúng ta chỉ cần quan tấm tới việc giải mã nó là được rồi.

Ví dụ, chữ À có giá trị tương đường là 0x0000C380. Khi trình dịch biên dịch chữ À, nó sẽ chỉ lưu 2 byte 0xC380 vào bộ nhớ.
Tiếp tục, chữ có giá trị tương đương 0x00E1BAAF. Khi trình dịch biên dịch chữ , nó sẽ lưu 3 byte 0xE1BAAF và bộ nhớ

Byte đầu tiên (cao nhất) chính là cơ sở để ta xác định độ dài của chữ cần giải mã.

  • Nếu byte đầu tiên có dạng 0xxx xxxx thì => chữ này chiếm 1 byte thôi
  • Nếu byte đầu tiên có dạng 110x xxxx thì => chữ này chiếm 2 byte.
  • Nếu byte đầu tiên có dạng 1110 xxxx thì => chữ này đang chiếm 3 byte
  • Nếu byte đầu tiên có dạng 1111 0xxx thì => chữ này đang chiếm 4 byte

Mình sẽ đi vào ví dụ ngay:

Trong bộ nhớ của chip có lưu 1 đoạn mã hex như sau:
0x56 0x69 0xe1 0xbb 0x87 0x74 0x20 0x4e 0x61 0x6d 0x20 0x56 0xc3 0xb4 0x20 0xc4 0x90 0xe1 0xbb 0x8b 0x63 0x68 0x20 0x21
Hỏi: Em hãy chuyển đoạn mã hex trên thành văn bản, biết nó được mã hóa UTF-8

  • Set byte đầu tiên 0x56(hex) = 0101.0110(bin) => nó có dạng 0xxx.xxx nên nó được mã hóa 1 byte => tra bảng ASCII 0x56= V
  • Set byte tiếp theo 0x69(hex) = 0100.0101 (bin) => nó có dạng 0xxx.xxx nên nó được mã hóa 1 byte => tra bảng ASCII 0x69 = i
  • Set byte tiếp theo 0xe1(hex) = 1110.0001 (bin) => nó có dạng 1110.xxxx nên nó được mã hóa 3 byte, ta lập tực ghép 2 byte phía sau nó thành 0xE1BB87 => tra bảng UTF-8 => 0xE1BB87 =
  • Tiếp tục, bỏ qua 2 byte đã ghép nhảy tới byte 0x74 = 0111.0100 => có dạng 0xxx.xxx nên tra bảng ASCII được chữ t
  • ……………………………………. Làm tương tự như trên, kết quả là Việt Nam Vô Địch !

Các bạn thử giải mã hết để hiểu kĩ hơn về cách giải mã utf8 nhé ! Dưới đây là bảng tra UTF-8 cho các kí tự tiếng Việt.

Thiết kết bộ mã tiếng việt

Theo bộ mã ASCII chúng ta có các kí tự 0->127 thuộc dải mã này, tuy nhiên từ 0 đến 32 thì là các mã hệ thống, không có khả năng hiển thị nên mình sẽ tận dụng luôn.
Bố cục thứ tự font mình sẽ thiết kế như sau:
Vị trí 0 là NULL nên mình không xài, bắt đầu từ vị trí 1 sẽ lưu chữ À, tiếp tới 2 sẽ là Á … cho tới 31 là chữ Í -> tiếp tới 32 đến 127 là mã ASCII -> tiếp tục từ 127 đến 229 là các kí tự tiếng Việt còn lại -> từ 229 trở đi là các kí tự đặc biệt, icon …

Thứ tự dấu là: Huyền Sắc Hỏi Ngã Nặng

Mình sẽ liệt kế tất cả các kí tự theo thứ tự bắt đầu từ 0 ra như sau:

NULL À Á Ả Ã Ạ Ă Ằ Ắ Ẳ Ẵ Ặ Â Ầ Ấ Ẩ Ẫ Ậ Đ È É Ẻ Ẽ Ẹ Ê Ề Ế Ể Ễ Ệ Ì Í (CÁCH) ! ” # $ % & ‘ ( ) * + , – . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ Ỉ Ĩ Ị Ò Ó Ỏ Õ Ọ Ô Ồ Ố Ổ Ỗ Ộ Ơ Ờ Ớ Ở Ỡ Ợ Ù Ú Ủ Ũ Ụ Ư Ừ Ứ Ử Ữ Ự Ỳ Ý Ỷ Ỹ Ỵ à á ả ã ạ ă ằ ắ ẳ ẵ ặ â ầ ấ ẩ ẫ ậ đ è é ẻ ẽ ẹ ê ề ế ể ễ ệ ì í ỉ ĩ ị ò ó ỏ õ ọ ô ò ố ổ ỗ ộ ơ ờ ớ ở ỡ ợ ù ú ủ ũ ụ ư ừ ứ ử ữ ự ỳ ý ỷ ỹ ỵ ° ❤ 🔊 🕒 ☀ 🌙 ☁ ⏰ 🔟 🔧

Chương trình giải mã UTF-8

Giải thích: đầu tiên mình sẽ check byte đó có nằm trong vùng của ASCII không, nếu đúng thì thoát luôn không cần giải mã nữa vì ta đã làm bộ font tương thích hoàn toàn ASCII rồi ! Ngược lại nếu không phải thì tức là đây là 1 byte bắt đầu của 1 kí tự UTF-8 , công việc là check xem kí tự này chiếm mấy byte bộ nhớ rồi ghép nối các byte rời rạc thành byte lớn kiểu long, sau đó thì tra bảng UTF8_table xem nó trùng với mã nào

Chú ý: Do UTF8_table chúng ta thiết kế bắt dầu từ 0 và liền mạch, còn vị trị thực tế của font lại bắt đầu từ 1 và tới 31 thì ngắt quãng (để nhường cho mã ascii và kí tự NULL) nên lúc return ở dòng 37 và 39 mình có căn chỉnh lại cho khớp !

Thiết kết bộ font tiếng việt

OK. Chúng ta đã đì dai xong bộ mã, giờ đến phần tạo font

Các bạn tạo mã bằng photoshop hoặc pain rồi lưu lại thành file ảnh. Sau đó dùng phần mềm này của để sinh mã hex nhé !

Mình dùng photoshop để tạo bộ font có kích cỡ 16×16 rồi lưu thành file ảnh

Sau khi có đầy đủ file ảnh của bộ font thì dùng phần mềm để convert sang mã hex nhé !

Giao diện phần mềm

Các bạn chọn ảnh cần chuyển, tích chọn matrix mono rồi ấn Chuyển đổi là sẽ có mã HEX sinh ra.

Note: Mã hex sinh theo chiều ngang, bit bên trái là bit cao

Còn đây là bộ FONT 16×16 mà mình đã tạo được

Xây dựng chương trình vẽ font ra màn hình

Ta đã có Hàm Matrix_setpx có nhiệm vụ vẽ màu lên pixel x,y

Hàm read_font16 có nhiệm vụ hỏi xem ở tọa độ x,y của font chữ có màu gì, ở đây màu là trắng hoặc đen tương ứng 0 hoặc 1

Hàm put_font16 để in ra 1 kí tự ở tọa độ x,y

Cuối cùng là hàm sendString_font16 để in 1 chuỗi văn bản UTF-8 ra màn hình

Và đây là thành quả của mình !

sendString_font16(0,0,”Xin Chào”,RED);
sendString_font16(0,8,”❤🕒🔧🔊”,CYAN);
sendString_font_min(0,8,”Test Font Tiếng Việt”,GREEN);

Kích hoạt chế độ gõ UTF-8 ở 1 số phần mềm lập trình

Arduino IDE được kích hoạt sẵn rồi, không cài gì thêm cả

KeilC thì bạn vào config để bật UTF-8 encoding lên nhé:

Nếu không thấy thì vào chỗ này

IAR cũng tương tự:

IAR thì ấn chuột phải vào vùng làm việc rồi vào Options
Sau đó chọn UTF-8 nhé

 

Từ tác giả:

Nếu có bất kì thắc mắc nào trong bài viết, vui lòng để lại comment dưới mỗi bài ! Mình sẽ không trả lời thắc mắc của các bạn ở facebook hay email !

Giới thiệu Đào Nguyện 58 bài viết
DIY,chế cháo, viết blog chia sẽ kiến thức về lập trình,điện tử - IoT. Rất mong được giao lưu, kết bạn với các bạn cùng đam mê. Địa chỉ Facebook: https://www.facebook.com/nguyendao207

6 bình luận

  1. Chào Đào Nguyện, tôi có copy font UTF-8 của bạn gắn vào chương trình quét led ma trận của tôi sử dụng ESP8266 ra MAX7219 led ma trận để muốn hiển thị ngày tháng bắng tiếng việt, nhưng cài váo thì báo lỗi expected ‘,’ or ‘;’ before ‘unsigned’ khi biên dịch, vậy có cách nào giúp chú

Để lại bình luận