特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接" N, v0 n T' {! l2 L
第26章 抗锯齿基础介绍
" g& a2 \# f- k2 X/ m" _* h 本期教程主要是跟大家讲解一下抗锯齿,关于抗锯齿,在第16章讲解字体显示的时候也讲了点。本期教程就是跟大家详细的讲解一下抗锯齿方面的知识。 线条由一系列必须位于显示坐标处的像素近似构成。因此,可能看起来呈锯齿状,尤其是近似水平线或近似垂直线。这种现象称为锯齿(aliasing)。抗锯齿是对线条和曲线进行平滑处理。可以减少不完全水平或垂直的线条的楼梯状锯齿。STemWin支持不同的抗锯齿质量、无锯齿字体和高分辨率坐标。 26. 1 介绍 26. 2 抗锯齿API函数实例演示 26. 3 总结 26.1 介绍 抗锯齿通过使背景色与前景色相“混合”的方法来平滑曲线和对角线。背景色与前景色之间使用的阴影越多,抗锯齿效果越好 (计算时间越长)。 26.1.1 抗锯齿质量 抗锯齿处理的质量由GUI_AA_SetFactor()函数设定,通过下面的截图给大家介绍一下抗锯齿因子与对应结果之间的关系。 2 t* M6 i$ q5 T5 Q1 N
第一条线未经抗锯齿处理(因子1)。第二条线以因子2进行了抗锯齿处理。也就是说,从前景到背景的阴影数为2 x 2 = 4。下一条线以抗锯齿因子3绘制,因而有3 x 3 = 9个阴影,如此等等,不一而足。因子4足以处理多数应用。进一步增加抗锯齿因素不会大幅改善结果,但会增加计算时间。 26.1.2 抗锯齿字体 在前面第16章介绍字体的时候讲解过2bpp和4bpp字体显示效果,下面再给大家展示下不使用抗锯齿和使用两种抗锯齿下字母C的显示效果: 4 M: i/ a* H" j
无锯齿字体可以通过STemWin字体转换器创建。使用无锯齿字体的一般目的是改进文字的外观。虽然高质量抗锯齿比低质量搞锯齿处理看起来更好美观,但计算时间和存储器占用量也会相应增加。低质量(2bpp)字体需要两倍于无抗锯齿处理(1bpp)字体的存储器容量;高质量(4bpp)字体则需要四倍的存储器容量。 26.1.3 高分辨率坐标 在使用抗锯齿法绘制项目时,使用的是与常规 (无抗锯齿处理)绘图程序相同的坐标。这是默认模式。在函数参数中无需考虑抗锯齿因子。例如,要从(50, 100)到(100, 50)绘制一条抗锯齿线条,则需写入以下代码: GUI_AA_DrawLine(50, 100, 100, 50); 借助STemWin的高分辨率功能,大家可以使用取决于抗锯齿因子和显示尺寸的虚拟空间。使用高分辨率坐标的优势在于,项目不但可以置于显示器的物理位置上,而且可以置于物理位置之间。 下图展示的是一个高分辨率像素的虚拟空间,其抗锯齿因素为3: # m# Q# ?4 A- r! H. O
以抗锯齿因子3,从像素(50,100)到像素(100, 50)绘制一条高分辨率线条,则需写入以下代码: GUI_AA_DrawLine(150, 300, 300, 150); 高分辨率坐标必须通过GUI_AA_EnableHiRes()程序启用,并用GUI_AA_DisableHiRes()禁用。 26.2 抗锯齿API函数实例演示 STemWin支持的抗锯齿函数主要如下: 0 a! F; p8 T* p6 g
26.2.1 函数GUI_AA_DrawArc模拟器上运行代码如下: - #include "GUI.h"2 G. |# {7 u% M
- - q! Q7 s: _. t; z/ a4 i
- void MainTask(void)# o% Y: T! O2 g$ }" s2 z
- {
1 T9 L! a3 x" n7 u8 K5 A/ _ - GUI_Init();
. F) V( W: h( p' a5 S8 _ - . y% S! h; z% B7 T5 A. M* X" R
- /* 设置画笔粗细 */* k& S# g( _. ^! j$ `) W
- GUI_SetPenSize(4);
- g- @5 A, I7 i V' C - GUI_SetColor(GUI_RED);
9 v, t6 V! o! U8 r) [# F. a* \+ a -
8 ]- F: O9 E- f' { - /* 使能高分辨率 */& L D1 _; g( o% p
- GUI_AA_EnableHiRes();+ V; d* _* {5 e9 E# B
- - V- `0 I) Z: Q
- /* 抗锯齿因数选择1 */' {6 p o* C: E5 r
- GUI_AA_SetFactor(1);
$ l+ w$ Q" Y5 U+ Z& A+ z1 q: @ - GUI_AA_DrawArc(50,120,50,50,0,180);' ^# m _1 N2 G0 y4 [/ j
- 4 G4 y; }) A1 f- @$ W9 {7 Q
- /* 抗锯齿因数选择3 */
! C) N( u& S/ b& C4 u9 P - GUI_AA_SetFactor(3);! t3 }# d' x0 F9 t' t. i
- GUI_AA_DrawArc(160*3,120*3,50*3,50*3,0,180);
u& l" A+ F: p - # v; ~. m0 E7 \7 f9 C3 x2 v. [
- /* 抗锯齿因数选择3 */' F/ L0 a! l4 H L0 h
- GUI_AA_SetFactor(6);2 ?" r2 M, C! z: Z( a
- GUI_AA_DrawArc(270*6,120*6,50*6,50*6,0,180);
8 n0 p h; ?7 W/ | -
; X- f' b: S2 z) \4 n: ?, n - while(1)
J+ B- x: [& [( n. M - {
+ [( h2 h: ]0 h7 L) @ - GUI_Delay(100);
G$ C+ v% g i* Q" V) Y - }
/ P9 h% h1 k$ A# |3 w: f# O1 j2 | - }
复制代码 要注意选择了抗锯齿因数后,绘制是得乘以相应的因数。 显示效果如下:
* [* M9 J, [0 E% w, c; V! C26.2.2 函数GUI_AA_DrawLine 模拟器上运行程序如下: - #include "GUI.h"
% u5 s$ \+ v7 h0 Z -
; r8 @1 o3 t/ P1 p {- M: M& x - void MainTask(void)
0 k9 x% n% g: ?$ S/ {' J# B+ ? - {
( M# s( X% J: i5 x- C1 c - GUI_Init();
* V2 A' R# c0 X a" M; d) P -
* X, h: L' W9 ?) g - /* 设置画笔粗细 */
: `# W6 b7 U! C - GUI_SetPenSize(40);
' s0 w# A2 Y/ _0 [( n - GUI_SetColor(GUI_RED);1 a9 X- L! t% S5 p6 {) b
-
% S2 i, y8 C$ q1 | - /* 使能高分辨率 */
5 s! e- O G, |- m4 A, t - GUI_AA_EnableHiRes();" d, N2 P% z3 L+ l# u i/ X
-
3 I- ^. p- h0 I3 ]1 T - /* 抗锯齿因数选择1 */
' D, v( f" s9 ]- ?9 ~" y - GUI_AA_SetFactor(1);
& B( V9 U8 t* K* y. z6 Y - GUI_AA_DrawLine(50,40,50,120);* }' `! u2 Y6 }$ Z( U" F$ X, l! ]3 _- B
- # j( |7 i0 g+ |; {3 }
- /* 抗锯齿因数选择3 */" l7 Q! N0 r1 n( ^
- GUI_AA_SetFactor(3);
$ X. H6 d6 v @6 w - GUI_AA_DrawLine(150*3,40*3,150*3,120*3);" I- H& n; k/ w" o5 J+ |, R, D
- ) ?* U' ~( P5 K4 }
- /* 抗锯齿因数选择3 */
4 |) h' E; G% J3 Z - GUI_AA_SetFactor(6);
' ^/ X2 p) B7 Q( l - GUI_AA_DrawLine(250*6,40*6,250*6,120*6);6 e) g6 x* S2 O. W/ [% N; D4 u
- . Y# H8 L4 z" s# n" o
- while(1)# V& m+ {* m- J7 A
- {$ Z! j7 V: d% w7 X
- GUI_Delay(100);
. r! Y% n# k, V2 q L - }
: i; b! v! v8 v# \, E+ f - }
复制代码实际效果如下:
5 N: T+ d5 a( @; i. X2 }# X& {* S26.2.3 函数GUI_AA_DrawPolyOutline 模拟器上运行代码如下: - #define countof(Array) (sizeof(Array) / sizeof(Array[0]))
4 P$ x( |. [# k* X; L! I -
- z6 I$ i" P8 M" a8 `7 E - static GUI_POINT aPoints[] = {0 M. N9 a$ X# z) p6 l$ @
- { 0, 0 },9 \3 C0 m4 Y( R# g
- { 15, 30 },
& ]. f, z" X3 d+ w$ L# O5 L( V. B - { 0, 20 },
) e. V( o3 J0 ] - {-15, 30 }2 |! f4 _4 L, j$ M# a
- };+ ?; w, F4 y& M3 U9 `
- ) f8 Z5 h0 ^' G/ u8 Z! m0 v2 s
- void MainTask(void)
$ X- m( D. `7 h& y: k+ V - {
k; m9 R, T4 c - GUI_Init();0 z6 G* D; Q3 h. O( O& Q5 e: u: h7 i7 B N
- 2 ?( h5 {7 X' C+ u$ {
- GUI_SetPenSize(10);
& \0 J$ e4 q. g$ g - GUI_SetColor(GUI_RED);
; a& Q6 h# c/ b: |/ Y, s -
$ } A/ Q3 W. G1 x% l - GUI_AA_DrawPolyOutline(aPoints, countof(aPoints), 3, 150, 40);
. Y* ?5 l( I9 y/ ?( S. y. s -
; B( T) @3 T0 X& K) o8 T$ X - while(1)4 t) Y6 X) s' }
- {
* {1 m& a% `& o7 B$ H2 S. L - GUI_Delay(100);* m* m% F) u3 O5 V
- }1 d* N- l/ _! U, w
- }
复制代码 使用这个函数要注意:通过连接终点和起点,可使绘制的多线条自动闭合。起点不得再次指定为终点。 如果采用高分辨率模式,则必须使用高分辨率坐标。否则,必须指定为像素值。默认情况下,该函数处理的定义点不超过10个。如果多边形由10个以的点构成,则必须使用GUI_AA_DrawPolyOutlineEx()函数。 实际效果如下:
" m% f; n1 d) F& A& b, A26.2.4 函数GUI_AA_DrawRoundedRect 模拟器上运行的代码如下: - #include "GUI.h"6 }" ]8 ^$ M7 b
-
% A1 [) e& n& a6 ` - void MainTask(void)" @9 V; |0 q, y/ e5 E4 j& Z v% b8 A
- {; v( @( _$ M; Z
- GUI_Init();
& _5 \, x q& W4 d# F7 R0 y - GUI_SetBkColor(GUI_WHITE);
0 O1 Q2 \$ B) ]; Q3 y8 `+ M - GUI_Clear();
# _9 t$ Y+ j( @ }# u. t- W3 T) E) m - GUI_SetColor(GUI_DARKBLUE);# [9 B- x) q; d- ?" C; Q8 u
- GUI_SetPenSize(5);& T% U! F, M l* c/ @
- GUI_AA_DrawRoundedRect(10, 10, 50, 50, 5);
" B2 K0 v$ O6 _& x& ^8 P, K- I - 8 x8 h& d, D. l- G) m# w5 _
- while(1)
$ c' p9 V, P# n) _& j - {
. S7 s0 {1 d" M - GUI_Delay(100);
' ~' A$ G% [+ l4 P - }
+ h0 a* K8 I- x( b) ` - }
复制代码实际显示效果如下: 26.2.5 函数GUI_AA_FillCircle 模拟器上运行的代码如下: - #include "GUI.h", V: `& g- c: h
-
- h! D- @2 o* g5 w4 N& {+ K% ]3 M9 C - void MainTask(void)% v. F$ C' e2 s9 [* ]. `: E. c
- {
8 ?+ h3 z1 |+ j' G' W9 c - GUI_Init();
( S! o4 w- _) n* {9 e/ l) ?0 `1 b - GUI_AA_EnableHiRes();
, L+ e" b" X ]) x3 i+ l - GUI_SetBkColor(GUI_WHITE);
1 ^# i4 Y9 @8 }) R) n - GUI_Clear();$ F- p( H% s2 m3 J0 r$ ~
- GUI_SetColor(GUI_DARKBLUE);, C, C$ t. J8 u3 p% C% O: d
- GUI_SetPenSize(5);0 O- n, G" _* b g2 `" J% ]
- GUI_AA_SetFactor(3);
$ ]1 ^. b7 K' B/ b( z - GUI_AA_FillCircle(160*3, 120*3, 80*3);& S/ b1 z+ Z. q& \# J- t
- q1 v2 K/ Q3 f, S# m# o
- while(1)5 S8 ?3 `( d# G& s2 L+ h
- {4 I9 x% Y+ s+ h) }
- GUI_Delay(100);
3 g2 m+ y. m% O - }0 p' \ @' G2 M. [
- }
复制代码实际显示效果如下: 26.2.6 函数GUI_AA_FillPolygon 模拟器上运行的代码如下: - #include "GUI.h"* {$ C2 H7 z$ K/ n* g7 J
- 2 @* O, |8 w6 W$ \: e& Q. J7 O0 u I& o
- #define countof(Array) (sizeof(Array) / sizeof(Array[0]))& ~4 T/ e* i: A9 u
- ; Z9 o. Q6 B6 p N# c P
- static GUI_POINT aPoints[] = { (1)2 Z5 s# z1 [$ ? i3 {& E; m
- { 0, 0 },
v5 ]4 Z/ {5 u7 j - { 70, -30 },9 d+ R& z7 Y2 p9 y$ P9 e% z9 Y" B
- { 0, 50 },
! T, }( U M; W7 ~/ |* F - {-70, -30 }
! u" |9 S0 F$ @ - };1 I" g6 s/ G- U
- , E# v8 t3 q$ H# \
- void MainTask(void)! v- Y& [1 v9 m
- {& G8 M# W+ f, u6 U
- GUI_Init();& j, J0 |3 {5 i5 v& X
-
8 ]% g3 g; ~3 U6 u8 U* C5 x# n1 v - GUI_SetPenSize(10);
2 a: |: U* d, T2 K8 M9 i - GUI_SetColor(GUI_RED);
( j9 m% C# F4 u) x1 H* _3 d) b4 \ - 1 R6 E( Q4 e+ H" C: t u& _
- GUI_AA_FillPolygon(aPoints, countof(aPoints), 150, 40);
. ]8 |" `8 A! N8 C6 G) [' s2 O - 1 W2 f6 _8 ~% g3 \
- while(1)
4 C. g9 F# x# O - {! G* G S; y% ?/ r1 K
- GUI_Delay(100);1 _! o3 V# v5 E, W* I% R
- }& L( g/ u% P$ n* g
- }
复制代码1. 这些坐标点是相对于函数GUI_AA_FillPolygon中的X,Y坐标而言的。 实际运行效果如下:
! n) m+ F6 s/ j. \, c8 O4 B! e& J& t26.2.7 函数GUI_AA_FillRoundedRect 模拟器上运行的代码如下: - #include "GUI.h"( w* u3 n& u- [( S M
- - _ |8 @/ q6 d" C( j
- void MainTask(void) {
! W" @: G& _) K4 X - GUI_Init();
5 _; I n* X& @) z0 c0 V& a8 S. u$ h - GUI_SetBkColor(GUI_WHITE);# m2 Z6 r1 r, K6 y' b" S2 A
- GUI_Clear();
2 U: K' P" a4 }# w- V# G - GUI_SetColor(GUI_DARKBLUE);, t: n' i" F1 l" R; W$ U
- GUI_AA_FillRoundedRect(10, 10, 54, 54, 5);
7 ^% e6 L$ m/ ? - while (1);
% T( Q! S1 {. I9 Q7 B- @1 R- @/ r - {
$ F9 L( C8 L5 }( U( O z6 _ - }
8 ]8 [9 E8 q; C$ ]/ W0 E3 e - }
复制代码实际显示效果如下:
5 L+ K: o4 e9 K& o26.3 总结 本期教程就跟大家讲这么多,下期教程再跟大家详细的讲解两个抗锯齿相关的应用例子。 / h4 }/ b1 C/ i
|