android抗鋸齒
1. android 抗鋸齒怎麼打開
畫筆的抗鋸齒(用於線條等)設置:
paint.setAntiAlias(true);
圖片線條(通用)的抗鋸齒需要另外設置:
canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
2. Android的paint抗鋸齒功能是什麼樣的效果paint.setAntiAlias(true
你試試就知道了,就是圖像邊緣相對清晰一點,鋸齒痕跡不那麼明顯
3. android 抗鋸齒的問題呀誰幫忙解決一下
將 paint=new Paint(Paint.FILTER_BITMAP_FLAG); 這一句中的標志位換成 ANTI_ALIAS_FLAG 試試,這個標志位意指抗鋸齒的。
4. 對比iOS 系統 Android 的字體渲染有何區別
一、渲染層級
從渲染流程上分,Skia可分為如下三個層級:
1、指令層:SkPicture、SkDeferredCanvas->SkCanvas
這一層決定需要執行哪些繪圖操作,繪圖操作的預變換矩陣,當前裁剪區域,繪圖操作產生在哪些layer上,Layer的生成與合並。
2、解析層:SkBitmapDevice->SkDraw->SkScan、SkDraw1Glyph::Proc
這一層決定繪制方式,完成坐標變換,解析出需要繪制的形體(點/線/規整矩形)並做好抗鋸齒處理,進行相關資源解析並設置好Shader。
3、渲染層:SkBlitter->SkBlitRow::Proc、SkShader::shadeSpan等
這一層進行采樣(如果需要),產生實際的繪制效果,完成顏色格式適配,進行透明度混合和抖動處理(如果需要)。 二、主要類介紹
1、SkCanvas
這是復雜度超出想像的一個類。
(1)API設計
a、創建:
在Android中,主要的創建方法是由SkBitmap創建SkCanvas:
explicit SkCanvas(const SkBitmap& bitmap);
這個方法是由bitmap創建一個SkBitmapDevice,再將這個SkBitmapDevice設定為SkCanvas的渲染目標。
5.0之後提供了一個快捷方法創建SkCanvas:
static SkCanvas* NewRasterDirect(const SkImageInfo&, void*,
size_t);
這樣Android的GraphicBuffer就不需要建一個SkBitmap和它關聯了,可以解除SkBitmap類和android
runtime的關系(雖然如此,目前Android5.0上,還是按建SkBitmap的方法去關聯GraphicBuffer)。
5.0之後引入的離屏渲染:
static SkCanvas* NewRaster(const SkImageInfo&);
創建一個SkCanvas,繪制的內容需要通過readPixels去讀取,仍然是CPU繪圖的方式。(個人覺得這個是轉入GPU硬體加速的一個比較方便的介面,不知道出於什麼考慮還是用CPU繪圖。)
b、狀態:
矩陣狀態:
矩陣決定當前繪制的幾何變換
rotate、skew、scale、translate、concat
裁剪狀態:
裁剪決定當前繪制的生效范圍
clipRect、clipRRect、clipPath、clipRegion
保存與恢復:
save、saveLayer、saveLayerAlpha、restore
c、渲染:
大部分渲染的API都可由這三個組合而成:
drawRect(矩形/圖像繪制)、drawPath(不規則圖形圖像繪制)和drawText(文本繪制)
d、像素的讀取與寫入
readPixels、writePixels
這兩個API主要由device實現,考慮到不同繪圖設備的異質性。
(2)MCRec狀態棧
fMCStack是存儲的全部狀態集,fMCRec則是當前的狀態。
在 save saveLayer saveLayerAlpha 時,會新建一個MCRec,在restore時,銷毀棧頂的MCRec。
(代碼見:SkCanvas.cpp internalSave函數,通過這段代碼可以了解一下new的各種用法~。)
每個狀態包括如下信息:
class SkCanvas::MCRec {
public:
int fFlags;//保存的狀態標識(是否保存矩陣/裁剪/圖層)
SkMatrix*
fMatrix;//矩陣指針,若這個狀態有獨立矩陣,則指向內存(fMatrixStorage),否則用上一個MCRec的fMatrix
SkRasterClip*
fRasterClip;//裁剪區域,若這個狀態有獨立裁剪區域,則指向內存(fRasterClip),否則繼承上一個的。
SkDrawFilter* fFilter;
DeviceCM* fLayer;//這個狀態所擁有的layer(需要在此MCRec銷毀時回收)
DeviceCM* fTopLayer;//這個狀態下,所需要繪制的Layer鏈表。(這些Layer不一定屬於此狀態)
......
};
DeviceCM:圖層鏈表,包裝一個SkBaseDevice,附加一個位置偏移變化的矩陣(在saveLayer時指定的坐標)。
(3)兩重循環繪制
研究Skia的人,一般來說都會被一開始的兩重循環弄暈一會,比如drawRect的代碼:
LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
while (iter.next()) {
iter.fDevice->drawRect(iter, r, looper.paint());
}
LOOPER_END
先完全展開上面的代碼:
AutoDrawLooper looper(this, paint, false, bounds);
while (looper.next(type)) {
SkDrawIter iter(this);
while (iter.next()) {
iter.fDevice->drawRect(iter, r, looper.paint());
}
}
第一重循環即 AutoDrawLooper,這個next實際上是做一個後處理,在存在 SkImageFilter
的情況下,先渲染到臨時Layer上,再將這個Layer做Filter處理後畫到當前device上。
第二重循環是SkDrawIter,這個是繪制當前狀態所依附的所有Layer。
一般情況下,這兩重循環都可以忽略,單純當它是走下流程就好了。
個人認為Skia在繪制入口SkCanvas的設計並不是很好,圖層、矩陣與裁剪存在一起,導致渲染任務難以剝離,後面GPU渲染和延遲渲染的引入都讓人感到有些生硬。
2、SkDraw、SkBlitter
這兩個類在後續章節還會提到,這里只簡單介紹:
SkDraw是CPU繪圖的實現入口,主要任務是做渲染准備(形狀確定、幾何變換、字體解析、構建圖像Shader等)。
SkBlitter 不是單獨的一個類,指代了一系列根據圖像格式、是否包含Shader等區分出來的一系列子類。
這一族類執行大塊頭的渲染任務,把像素繪制上去。
三、渲染框架設計思想分析
1、指令層與實現層分離
SkCanvas不直接執行渲染,由SkBaseDevice根據設備類型,選擇渲染方法。這樣雖然是同一套API,但可以用作GPU繪圖、pdf繪制、存儲顯示列表等各種功能。在API集上做優化,避免冗餘繪制,也因此成為可能(註:這個google雖然在嘗試,但目前看來沒有明顯效果,實現起來確實也很困難)。
2、圖=形+色的設計思想
由SkDraw和SkScan類中控制繪制的形,由SkBlitter和SkShader控制繪制的色,將繪圖操作分解為形狀與色彩兩部分,這一點和OpenGL的頂點變換——光柵——片斷著色管線相似,非常有利於擴展,各種2D圖元的繪制基本上就完全支持了。
3、性能調優集中化
將耗時的函數抽象都抽象為proc,由一個工廠製造,便於集中對這一系列函數做優化。
下面三章分別講bitmap、path和text的繪制方法
著重點分別如下:
bitmap:shader及采樣原理,混合計算原理,多格式支持方法
path:不規則圖形的繪制方式
text:文本解析方法,cache管理