// Copyright 2016 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package vector// This file contains a floating point math implementation of the vector// graphics rasterizer.import ()func floatingMax(, float32) float32 {if > {return }return}func floatingMin(, float32) float32 {if < {return }return}func floatingFloor( float32) int32 { returnint32(math.Floor(float64())) }func floatingCeil( float32) int32 { returnint32(math.Ceil(float64())) }func ( *Rasterizer) (, float32) { , := .penX, .penY .penX, .penY = , := float32(1)if > { , , , , = -1, , , , }// Horizontal line segments yield no change in coverage. Almost horizontal // segments would yield some change, in ideal math, but the computation // further below, involving 1 / (by - ay), is unstable in floating point // math, so we treat the segment as if it was perfectly horizontal.if - <= 0.000001 {return } := ( - ) / ( - ) := := floatingFloor() := floatingCeil()if > int32(.size.Y) { = int32(.size.Y) } := int32(.size.X)for ; < ; ++ { := floatingMin(float32(+1), ) - floatingMax(float32(), )// The "float32" in expressions like "float32(foo*bar)" here and below // look redundant, since foo and bar already have type float32, but are // explicit in order to disable the compiler's Fused Multiply Add (FMA) // instruction selection, which can improve performance but can result // in different rounding errors in floating point computations. // // This package aims to have bit-exact identical results across all // GOARCHes, and across pure Go code and assembly, so it disables FMA. // // See the discussion at // https://groups.google.com/d/topic/golang-dev/Sti0bl2xUXQ/discussion := + float32(*)if < 0 { = continue } := .bufF32[*:] := float32( * ) , := , if > { , = , } := floatingFloor() := float32() := floatingCeil() := float32()if <= +1 { := float32(0.5*(+)) - if := clamp(+0, ); < uint(len()) { [] += - float32(*) }if := clamp(+1, ); < uint(len()) { [] += float32( * ) } } else { := 1 / ( - ) := - := 1 - := float32(0.5 * * * ) := - + 1 := float32(0.5 * * * )if := clamp(, ); < uint(len()) { [] += float32( * ) }if == +2 {if := clamp(+1, ); < uint(len()) { [] += float32( * (1 - - )) } } else { := float32( * (1.5 - ))if := clamp(+1, ); < uint(len()) { [] += float32( * ( - )) } := float32( * )for := + 2; < -1; ++ {if := clamp(, ); < uint(len()) { [] += } } := + float32(*float32(--3))if := clamp(-1, ); < uint(len()) { [] += float32( * (1 - - )) } }if := clamp(, ); < uint(len()) { [] += float32( * ) } } = }}const (// almost256 scales a floating point value in the range [0, 1] to a uint8 // value in the range [0x00, 0xff]. // // 255 is too small. Floating point math accumulates rounding errors, so a // fully covered src value that would in ideal math be float32(1) might be // float32(1-ε), and uint8(255 * (1-ε)) would be 0xfe instead of 0xff. The // uint8 conversion rounds to zero, not to nearest. // // 256 is too big. If we multiplied by 256, below, then a fully covered src // value of float32(1) would translate to uint8(256 * 1), which can be 0x00 // instead of the maximal value 0xff. // // math.Float32bits(almost256) is 0x437fffff. almost256 = 255.99998// almost65536 scales a floating point value in the range [0, 1] to a // uint16 value in the range [0x0000, 0xffff]. // // math.Float32bits(almost65536) is 0x477fffff. almost65536 = almost256 * 256)func floatingAccumulateOpOver( []uint8, []float32) {// Sanity check that len(dst) >= len(src).iflen() < len() {return } := float32(0)for , := range { += := if < 0 { = - }if > 1 { = 1 }// This algorithm comes from the standard library's image/draw package. := uint32([]) * 0x101 := uint32(almost65536 * ) := *(0xffff-)/0xffff + [] = uint8( >> 8) }}func floatingAccumulateOpSrc( []uint8, []float32) {// Sanity check that len(dst) >= len(src).iflen() < len() {return } := float32(0)for , := range { += := if < 0 { = - }if > 1 { = 1 } [] = uint8(almost256 * ) }}func floatingAccumulateMask( []uint32, []float32) {// Sanity check that len(dst) >= len(src).iflen() < len() {return } := float32(0)for , := range { += := if < 0 { = - }if > 1 { = 1 } [] = uint32(almost65536 * ) }}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.