pub struct Surface {
pub width: u32,
pub height: u32,
pub pixels: Vec<u32>,
pub clip: Option<Arc<ClipMask>>,
}Expand description
Canvas のバッキングストア(ARGB8888 のピクセル配列)。
画面へ直接描かず、まずここへ描く。<canvas> は
「レイアウトで決まった矩形へ、自分のピクセルを貼る」要素なので、
画面座標ではなくキャンバス内座標で完結させる必要がある。
Fields§
§width: u32§height: u32§pixels: Vec<u32>長さは width * height。各要素は 0xAARRGGBB。
clip: Option<Arc<ClipMask>>有効なクリップ領域。None なら全面に描ける。
状態側(DrawState)が持ち主で、描画の直前に sync_clip で写す。
塗りの実装すべてが最後は blend_pixel を通るので、
ここで一度だけ見れば経路の取りこぼしが起きない。
Implementations§
Source§impl Surface
impl Surface
Sourcepub fn new(width: u32, height: u32) -> Option<Self>
pub fn new(width: u32, height: u32) -> Option<Self>
透明で初期化した面を作る。
面積が過大な場合は None(ヒープを食い潰さないための上限)。
実サイトの canvas は大きくても数千×数千なので、
4096×4096(約 64MB)を上限とする。
Sourcepub fn blend_pixel(&mut self, x: i32, y: i32, argb: u32)
pub fn blend_pixel(&mut self, x: i32, y: i32, argb: u32)
1 ピクセルを source-over で合成する。範囲外は黙って無視する。
Sourcepub fn fill_rect(
&mut self,
x: i32,
y: i32,
w: i32,
h: i32,
argb: u32,
replace: bool,
)
pub fn fill_rect( &mut self, x: i32, y: i32, w: i32, h: i32, argb: u32, replace: bool, )
矩形を塗りつぶす(clearRect は argb=0 かつ replace=true で使う)。
replace が真なら合成せず上書きする(clearRect の意味論)。
Sourcepub fn fill_path(&mut self, subpaths: &[SubPath], rule: FillRule, argb: u32)
pub fn fill_path(&mut self, subpaths: &[SubPath], rule: FillRule, argb: u32)
パスを塗りつぶす。
走査線はピクセル中心(y + 0.5)で判定する。境界ちょうどの
走査線を使うと、隣り合う図形の継ぎ目に隙間や二重塗りが出る。
Sourcepub fn stroke_path(&mut self, subpaths: &[SubPath], argb: u32)
pub fn stroke_path(&mut self, subpaths: &[SubPath], argb: u32)
折れ線を線幅 1 で描く(stroke の最小実装)。
線幅・線端・線結合は未対応。まず「線が見える」ところまでを担保する。
Source§impl Surface
impl Surface
Sourcepub fn stroke_path_width(&mut self, subpaths: &[SubPath], argb: u32, width: f32)
pub fn stroke_path_width(&mut self, subpaths: &[SubPath], argb: u32, width: f32)
線幅つきで折れ線を描く。
各線分を「線幅ぶんの太さを持つ四角形」に展開して塗る。
線端・線結合(lineCap/lineJoin)は未対応で、
結合部には円を置いて隙間を埋める(round 相当の近似)。
§なぜ四角形へ展開するか
Bresenham を平行にずらして何本も引く方法は、斜線で
太さが不均一になる(見た目が痩せる)。線分に垂直な方向へ
幅の半分ずつ広げた四角形を塗れば、角度によらず一定の太さになる。
線幅つきで折れ線を描く(線端 Butt・結合 Round)。
線端・結合を選ぶ場合は stroke_path_styled を使う。
Source§impl Surface
impl Surface
Sourcepub fn stroke_path_styled(
&mut self,
subpaths: &[SubPath],
argb: u32,
width: f32,
cap: LineCap,
join: LineJoin,
miter_limit: f32,
)
pub fn stroke_path_styled( &mut self, subpaths: &[SubPath], argb: u32, width: f32, cap: LineCap, join: LineJoin, miter_limit: f32, )
線端・結合を指定して折れ線を描く。
stroke_path_width は端 Butt・結合 Round でこれを呼ぶ。
Sourcefn fill_joint(
&mut self,
prev: (f32, f32),
cur: (f32, f32),
next: (f32, f32),
half: f32,
argb: u32,
join: LineJoin,
limit: f32,
)
fn fill_joint( &mut self, prev: (f32, f32), cur: (f32, f32), next: (f32, f32), half: f32, argb: u32, join: LineJoin, limit: f32, )
結合部 1 箇所を埋める。
fn fill_quad( &mut self, a: (f32, f32), b: (f32, f32), c: (f32, f32), d: (f32, f32), argb: u32, )
fn fill_tri(&mut self, a: (f32, f32), b: (f32, f32), c: (f32, f32), argb: u32)
Source§impl Surface
impl Surface
Sourcepub fn draw_image(
&mut self,
src: &ImageSource<'_>,
spec: &BlitSpec,
m: &Matrix,
alpha: f32,
)
pub fn draw_image( &mut self, src: &ImageSource<'_>, spec: &BlitSpec, m: &Matrix, alpha: f32, )
画像を現在の変換のもとで転送する(drawImage)。
§なぜ逆変換で引くか
転送元を 1 画素ずつ変換先へ「押し出す」と、拡大時に隙間が空き 回転時には縞が出る。転送先の画素ごとに逆変換で元を引くと、 どの倍率・角度でも穴が空かない。
変換が退化している(面積 0 に潰れる)場合は何もしない。
Source§impl Surface
impl Surface
Sourcepub fn draw_glyph(
&mut self,
g: &GlyphBitmap<'_>,
pen_x: f32,
pen_y: f32,
argb: u32,
m: &Matrix,
)
pub fn draw_glyph( &mut self, g: &GlyphBitmap<'_>, pen_x: f32, pen_y: f32, argb: u32, m: &Matrix, )
字形を 1 つ描く。
字形は軸に沿ったビットマップだが、現在の変換の下で置きたい。
アルファを色に載せた画像として draw_image に通すことで、
回転・拡大も転送と同じ経路で扱える(別実装を増やさない)。