mirror of
https://github.com/muun/recovery.git
synced 2025-11-13 07:11:45 -05:00
Release v2.2.0
This commit is contained in:
193
vendor/golang.org/x/image/riff/riff.go
generated
vendored
Normal file
193
vendor/golang.org/x/image/riff/riff.go
generated
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
// Copyright 2014 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 riff implements the Resource Interchange File Format, used by media
|
||||
// formats such as AVI, WAVE and WEBP.
|
||||
//
|
||||
// A RIFF stream contains a sequence of chunks. Each chunk consists of an 8-byte
|
||||
// header (containing a 4-byte chunk type and a 4-byte chunk length), the chunk
|
||||
// data (presented as an io.Reader), and some padding bytes.
|
||||
//
|
||||
// A detailed description of the format is at
|
||||
// http://www.tactilemedia.com/info/MCI_Control_Info.html
|
||||
package riff // import "golang.org/x/image/riff"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
)
|
||||
|
||||
var (
|
||||
errMissingPaddingByte = errors.New("riff: missing padding byte")
|
||||
errMissingRIFFChunkHeader = errors.New("riff: missing RIFF chunk header")
|
||||
errListSubchunkTooLong = errors.New("riff: list subchunk too long")
|
||||
errShortChunkData = errors.New("riff: short chunk data")
|
||||
errShortChunkHeader = errors.New("riff: short chunk header")
|
||||
errStaleReader = errors.New("riff: stale reader")
|
||||
)
|
||||
|
||||
// u32 decodes the first four bytes of b as a little-endian integer.
|
||||
func u32(b []byte) uint32 {
|
||||
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
|
||||
}
|
||||
|
||||
const chunkHeaderSize = 8
|
||||
|
||||
// FourCC is a four character code.
|
||||
type FourCC [4]byte
|
||||
|
||||
// LIST is the "LIST" FourCC.
|
||||
var LIST = FourCC{'L', 'I', 'S', 'T'}
|
||||
|
||||
// NewReader returns the RIFF stream's form type, such as "AVI " or "WAVE", and
|
||||
// its chunks as a *Reader.
|
||||
func NewReader(r io.Reader) (formType FourCC, data *Reader, err error) {
|
||||
var buf [chunkHeaderSize]byte
|
||||
if _, err := io.ReadFull(r, buf[:]); err != nil {
|
||||
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
||||
err = errMissingRIFFChunkHeader
|
||||
}
|
||||
return FourCC{}, nil, err
|
||||
}
|
||||
if buf[0] != 'R' || buf[1] != 'I' || buf[2] != 'F' || buf[3] != 'F' {
|
||||
return FourCC{}, nil, errMissingRIFFChunkHeader
|
||||
}
|
||||
return NewListReader(u32(buf[4:]), r)
|
||||
}
|
||||
|
||||
// NewListReader returns a LIST chunk's list type, such as "movi" or "wavl",
|
||||
// and its chunks as a *Reader.
|
||||
func NewListReader(chunkLen uint32, chunkData io.Reader) (listType FourCC, data *Reader, err error) {
|
||||
if chunkLen < 4 {
|
||||
return FourCC{}, nil, errShortChunkData
|
||||
}
|
||||
z := &Reader{r: chunkData}
|
||||
if _, err := io.ReadFull(chunkData, z.buf[:4]); err != nil {
|
||||
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
||||
err = errShortChunkData
|
||||
}
|
||||
return FourCC{}, nil, err
|
||||
}
|
||||
z.totalLen = chunkLen - 4
|
||||
return FourCC{z.buf[0], z.buf[1], z.buf[2], z.buf[3]}, z, nil
|
||||
}
|
||||
|
||||
// Reader reads chunks from an underlying io.Reader.
|
||||
type Reader struct {
|
||||
r io.Reader
|
||||
err error
|
||||
|
||||
totalLen uint32
|
||||
chunkLen uint32
|
||||
|
||||
chunkReader *chunkReader
|
||||
buf [chunkHeaderSize]byte
|
||||
padded bool
|
||||
}
|
||||
|
||||
// Next returns the next chunk's ID, length and data. It returns io.EOF if there
|
||||
// are no more chunks. The io.Reader returned becomes stale after the next Next
|
||||
// call, and should no longer be used.
|
||||
//
|
||||
// It is valid to call Next even if all of the previous chunk's data has not
|
||||
// been read.
|
||||
func (z *Reader) Next() (chunkID FourCC, chunkLen uint32, chunkData io.Reader, err error) {
|
||||
if z.err != nil {
|
||||
return FourCC{}, 0, nil, z.err
|
||||
}
|
||||
|
||||
// Drain the rest of the previous chunk.
|
||||
if z.chunkLen != 0 {
|
||||
want := z.chunkLen
|
||||
var got int64
|
||||
got, z.err = io.Copy(ioutil.Discard, z.chunkReader)
|
||||
if z.err == nil && uint32(got) != want {
|
||||
z.err = errShortChunkData
|
||||
}
|
||||
if z.err != nil {
|
||||
return FourCC{}, 0, nil, z.err
|
||||
}
|
||||
}
|
||||
z.chunkReader = nil
|
||||
if z.padded {
|
||||
if z.totalLen == 0 {
|
||||
z.err = errListSubchunkTooLong
|
||||
return FourCC{}, 0, nil, z.err
|
||||
}
|
||||
z.totalLen--
|
||||
_, z.err = io.ReadFull(z.r, z.buf[:1])
|
||||
if z.err != nil {
|
||||
if z.err == io.EOF {
|
||||
z.err = errMissingPaddingByte
|
||||
}
|
||||
return FourCC{}, 0, nil, z.err
|
||||
}
|
||||
}
|
||||
|
||||
// We are done if we have no more data.
|
||||
if z.totalLen == 0 {
|
||||
z.err = io.EOF
|
||||
return FourCC{}, 0, nil, z.err
|
||||
}
|
||||
|
||||
// Read the next chunk header.
|
||||
if z.totalLen < chunkHeaderSize {
|
||||
z.err = errShortChunkHeader
|
||||
return FourCC{}, 0, nil, z.err
|
||||
}
|
||||
z.totalLen -= chunkHeaderSize
|
||||
if _, z.err = io.ReadFull(z.r, z.buf[:chunkHeaderSize]); z.err != nil {
|
||||
if z.err == io.EOF || z.err == io.ErrUnexpectedEOF {
|
||||
z.err = errShortChunkHeader
|
||||
}
|
||||
return FourCC{}, 0, nil, z.err
|
||||
}
|
||||
chunkID = FourCC{z.buf[0], z.buf[1], z.buf[2], z.buf[3]}
|
||||
z.chunkLen = u32(z.buf[4:])
|
||||
if z.chunkLen > z.totalLen {
|
||||
z.err = errListSubchunkTooLong
|
||||
return FourCC{}, 0, nil, z.err
|
||||
}
|
||||
z.padded = z.chunkLen&1 == 1
|
||||
z.chunkReader = &chunkReader{z}
|
||||
return chunkID, z.chunkLen, z.chunkReader, nil
|
||||
}
|
||||
|
||||
type chunkReader struct {
|
||||
z *Reader
|
||||
}
|
||||
|
||||
func (c *chunkReader) Read(p []byte) (int, error) {
|
||||
if c != c.z.chunkReader {
|
||||
return 0, errStaleReader
|
||||
}
|
||||
z := c.z
|
||||
if z.err != nil {
|
||||
if z.err == io.EOF {
|
||||
return 0, errStaleReader
|
||||
}
|
||||
return 0, z.err
|
||||
}
|
||||
|
||||
n := int(z.chunkLen)
|
||||
if n == 0 {
|
||||
return 0, io.EOF
|
||||
}
|
||||
if n < 0 {
|
||||
// Converting uint32 to int overflowed.
|
||||
n = math.MaxInt32
|
||||
}
|
||||
if n > len(p) {
|
||||
n = len(p)
|
||||
}
|
||||
n, err := z.r.Read(p[:n])
|
||||
z.totalLen -= uint32(n)
|
||||
z.chunkLen -= uint32(n)
|
||||
if err != io.EOF {
|
||||
z.err = err
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
403
vendor/golang.org/x/image/vp8/decode.go
generated
vendored
Normal file
403
vendor/golang.org/x/image/vp8/decode.go
generated
vendored
Normal file
@@ -0,0 +1,403 @@
|
||||
// Copyright 2011 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 vp8 implements a decoder for the VP8 lossy image format.
|
||||
//
|
||||
// The VP8 specification is RFC 6386.
|
||||
package vp8 // import "golang.org/x/image/vp8"
|
||||
|
||||
// This file implements the top-level decoding algorithm.
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"image"
|
||||
"io"
|
||||
)
|
||||
|
||||
// limitReader wraps an io.Reader to read at most n bytes from it.
|
||||
type limitReader struct {
|
||||
r io.Reader
|
||||
n int
|
||||
}
|
||||
|
||||
// ReadFull reads exactly len(p) bytes into p.
|
||||
func (r *limitReader) ReadFull(p []byte) error {
|
||||
if len(p) > r.n {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
n, err := io.ReadFull(r.r, p)
|
||||
r.n -= n
|
||||
return err
|
||||
}
|
||||
|
||||
// FrameHeader is a frame header, as specified in section 9.1.
|
||||
type FrameHeader struct {
|
||||
KeyFrame bool
|
||||
VersionNumber uint8
|
||||
ShowFrame bool
|
||||
FirstPartitionLen uint32
|
||||
Width int
|
||||
Height int
|
||||
XScale uint8
|
||||
YScale uint8
|
||||
}
|
||||
|
||||
const (
|
||||
nSegment = 4
|
||||
nSegmentProb = 3
|
||||
)
|
||||
|
||||
// segmentHeader holds segment-related header information.
|
||||
type segmentHeader struct {
|
||||
useSegment bool
|
||||
updateMap bool
|
||||
relativeDelta bool
|
||||
quantizer [nSegment]int8
|
||||
filterStrength [nSegment]int8
|
||||
prob [nSegmentProb]uint8
|
||||
}
|
||||
|
||||
const (
|
||||
nRefLFDelta = 4
|
||||
nModeLFDelta = 4
|
||||
)
|
||||
|
||||
// filterHeader holds filter-related header information.
|
||||
type filterHeader struct {
|
||||
simple bool
|
||||
level int8
|
||||
sharpness uint8
|
||||
useLFDelta bool
|
||||
refLFDelta [nRefLFDelta]int8
|
||||
modeLFDelta [nModeLFDelta]int8
|
||||
perSegmentLevel [nSegment]int8
|
||||
}
|
||||
|
||||
// mb is the per-macroblock decode state. A decoder maintains mbw+1 of these
|
||||
// as it is decoding macroblocks left-to-right and top-to-bottom: mbw for the
|
||||
// macroblocks in the row above, and one for the macroblock to the left.
|
||||
type mb struct {
|
||||
// pred is the predictor mode for the 4 bottom or right 4x4 luma regions.
|
||||
pred [4]uint8
|
||||
// nzMask is a mask of 8 bits: 4 for the bottom or right 4x4 luma regions,
|
||||
// and 2 + 2 for the bottom or right 4x4 chroma regions. A 1 bit indicates
|
||||
// that region has non-zero coefficients.
|
||||
nzMask uint8
|
||||
// nzY16 is a 0/1 value that is 1 if the macroblock used Y16 prediction and
|
||||
// had non-zero coefficients.
|
||||
nzY16 uint8
|
||||
}
|
||||
|
||||
// Decoder decodes VP8 bitstreams into frames. Decoding one frame consists of
|
||||
// calling Init, DecodeFrameHeader and then DecodeFrame in that order.
|
||||
// A Decoder can be re-used to decode multiple frames.
|
||||
type Decoder struct {
|
||||
// r is the input bitsream.
|
||||
r limitReader
|
||||
// scratch is a scratch buffer.
|
||||
scratch [8]byte
|
||||
// img is the YCbCr image to decode into.
|
||||
img *image.YCbCr
|
||||
// mbw and mbh are the number of 16x16 macroblocks wide and high the image is.
|
||||
mbw, mbh int
|
||||
// frameHeader is the frame header. When decoding multiple frames,
|
||||
// frames that aren't key frames will inherit the Width, Height,
|
||||
// XScale and YScale of the most recent key frame.
|
||||
frameHeader FrameHeader
|
||||
// Other headers.
|
||||
segmentHeader segmentHeader
|
||||
filterHeader filterHeader
|
||||
// The image data is divided into a number of independent partitions.
|
||||
// There is 1 "first partition" and between 1 and 8 "other partitions"
|
||||
// for coefficient data.
|
||||
fp partition
|
||||
op [8]partition
|
||||
nOP int
|
||||
// Quantization factors.
|
||||
quant [nSegment]quant
|
||||
// DCT/WHT coefficient decoding probabilities.
|
||||
tokenProb [nPlane][nBand][nContext][nProb]uint8
|
||||
useSkipProb bool
|
||||
skipProb uint8
|
||||
// Loop filter parameters.
|
||||
filterParams [nSegment][2]filterParam
|
||||
perMBFilterParams []filterParam
|
||||
|
||||
// The eight fields below relate to the current macroblock being decoded.
|
||||
//
|
||||
// Segment-based adjustments.
|
||||
segment int
|
||||
// Per-macroblock state for the macroblock immediately left of and those
|
||||
// macroblocks immediately above the current macroblock.
|
||||
leftMB mb
|
||||
upMB []mb
|
||||
// Bitmasks for which 4x4 regions of coeff contain non-zero coefficients.
|
||||
nzDCMask, nzACMask uint32
|
||||
// Predictor modes.
|
||||
usePredY16 bool // The libwebp C code calls this !is_i4x4_.
|
||||
predY16 uint8
|
||||
predC8 uint8
|
||||
predY4 [4][4]uint8
|
||||
|
||||
// The two fields below form a workspace for reconstructing a macroblock.
|
||||
// Their specific sizes are documented in reconstruct.go.
|
||||
coeff [1*16*16 + 2*8*8 + 1*4*4]int16
|
||||
ybr [1 + 16 + 1 + 8][32]uint8
|
||||
}
|
||||
|
||||
// NewDecoder returns a new Decoder.
|
||||
func NewDecoder() *Decoder {
|
||||
return &Decoder{}
|
||||
}
|
||||
|
||||
// Init initializes the decoder to read at most n bytes from r.
|
||||
func (d *Decoder) Init(r io.Reader, n int) {
|
||||
d.r = limitReader{r, n}
|
||||
}
|
||||
|
||||
// DecodeFrameHeader decodes the frame header.
|
||||
func (d *Decoder) DecodeFrameHeader() (fh FrameHeader, err error) {
|
||||
// All frame headers are at least 3 bytes long.
|
||||
b := d.scratch[:3]
|
||||
if err = d.r.ReadFull(b); err != nil {
|
||||
return
|
||||
}
|
||||
d.frameHeader.KeyFrame = (b[0] & 1) == 0
|
||||
d.frameHeader.VersionNumber = (b[0] >> 1) & 7
|
||||
d.frameHeader.ShowFrame = (b[0]>>4)&1 == 1
|
||||
d.frameHeader.FirstPartitionLen = uint32(b[0])>>5 | uint32(b[1])<<3 | uint32(b[2])<<11
|
||||
if !d.frameHeader.KeyFrame {
|
||||
return d.frameHeader, nil
|
||||
}
|
||||
// Frame headers for key frames are an additional 7 bytes long.
|
||||
b = d.scratch[:7]
|
||||
if err = d.r.ReadFull(b); err != nil {
|
||||
return
|
||||
}
|
||||
// Check the magic sync code.
|
||||
if b[0] != 0x9d || b[1] != 0x01 || b[2] != 0x2a {
|
||||
err = errors.New("vp8: invalid format")
|
||||
return
|
||||
}
|
||||
d.frameHeader.Width = int(b[4]&0x3f)<<8 | int(b[3])
|
||||
d.frameHeader.Height = int(b[6]&0x3f)<<8 | int(b[5])
|
||||
d.frameHeader.XScale = b[4] >> 6
|
||||
d.frameHeader.YScale = b[6] >> 6
|
||||
d.mbw = (d.frameHeader.Width + 0x0f) >> 4
|
||||
d.mbh = (d.frameHeader.Height + 0x0f) >> 4
|
||||
d.segmentHeader = segmentHeader{
|
||||
prob: [3]uint8{0xff, 0xff, 0xff},
|
||||
}
|
||||
d.tokenProb = defaultTokenProb
|
||||
d.segment = 0
|
||||
return d.frameHeader, nil
|
||||
}
|
||||
|
||||
// ensureImg ensures that d.img is large enough to hold the decoded frame.
|
||||
func (d *Decoder) ensureImg() {
|
||||
if d.img != nil {
|
||||
p0, p1 := d.img.Rect.Min, d.img.Rect.Max
|
||||
if p0.X == 0 && p0.Y == 0 && p1.X >= 16*d.mbw && p1.Y >= 16*d.mbh {
|
||||
return
|
||||
}
|
||||
}
|
||||
m := image.NewYCbCr(image.Rect(0, 0, 16*d.mbw, 16*d.mbh), image.YCbCrSubsampleRatio420)
|
||||
d.img = m.SubImage(image.Rect(0, 0, d.frameHeader.Width, d.frameHeader.Height)).(*image.YCbCr)
|
||||
d.perMBFilterParams = make([]filterParam, d.mbw*d.mbh)
|
||||
d.upMB = make([]mb, d.mbw)
|
||||
}
|
||||
|
||||
// parseSegmentHeader parses the segment header, as specified in section 9.3.
|
||||
func (d *Decoder) parseSegmentHeader() {
|
||||
d.segmentHeader.useSegment = d.fp.readBit(uniformProb)
|
||||
if !d.segmentHeader.useSegment {
|
||||
d.segmentHeader.updateMap = false
|
||||
return
|
||||
}
|
||||
d.segmentHeader.updateMap = d.fp.readBit(uniformProb)
|
||||
if d.fp.readBit(uniformProb) {
|
||||
d.segmentHeader.relativeDelta = !d.fp.readBit(uniformProb)
|
||||
for i := range d.segmentHeader.quantizer {
|
||||
d.segmentHeader.quantizer[i] = int8(d.fp.readOptionalInt(uniformProb, 7))
|
||||
}
|
||||
for i := range d.segmentHeader.filterStrength {
|
||||
d.segmentHeader.filterStrength[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
|
||||
}
|
||||
}
|
||||
if !d.segmentHeader.updateMap {
|
||||
return
|
||||
}
|
||||
for i := range d.segmentHeader.prob {
|
||||
if d.fp.readBit(uniformProb) {
|
||||
d.segmentHeader.prob[i] = uint8(d.fp.readUint(uniformProb, 8))
|
||||
} else {
|
||||
d.segmentHeader.prob[i] = 0xff
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parseFilterHeader parses the filter header, as specified in section 9.4.
|
||||
func (d *Decoder) parseFilterHeader() {
|
||||
d.filterHeader.simple = d.fp.readBit(uniformProb)
|
||||
d.filterHeader.level = int8(d.fp.readUint(uniformProb, 6))
|
||||
d.filterHeader.sharpness = uint8(d.fp.readUint(uniformProb, 3))
|
||||
d.filterHeader.useLFDelta = d.fp.readBit(uniformProb)
|
||||
if d.filterHeader.useLFDelta && d.fp.readBit(uniformProb) {
|
||||
for i := range d.filterHeader.refLFDelta {
|
||||
d.filterHeader.refLFDelta[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
|
||||
}
|
||||
for i := range d.filterHeader.modeLFDelta {
|
||||
d.filterHeader.modeLFDelta[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
|
||||
}
|
||||
}
|
||||
if d.filterHeader.level == 0 {
|
||||
return
|
||||
}
|
||||
if d.segmentHeader.useSegment {
|
||||
for i := range d.filterHeader.perSegmentLevel {
|
||||
strength := d.segmentHeader.filterStrength[i]
|
||||
if d.segmentHeader.relativeDelta {
|
||||
strength += d.filterHeader.level
|
||||
}
|
||||
d.filterHeader.perSegmentLevel[i] = strength
|
||||
}
|
||||
} else {
|
||||
d.filterHeader.perSegmentLevel[0] = d.filterHeader.level
|
||||
}
|
||||
d.computeFilterParams()
|
||||
}
|
||||
|
||||
// parseOtherPartitions parses the other partitions, as specified in section 9.5.
|
||||
func (d *Decoder) parseOtherPartitions() error {
|
||||
const maxNOP = 1 << 3
|
||||
var partLens [maxNOP]int
|
||||
d.nOP = 1 << d.fp.readUint(uniformProb, 2)
|
||||
|
||||
// The final partition length is implied by the remaining chunk data
|
||||
// (d.r.n) and the other d.nOP-1 partition lengths. Those d.nOP-1 partition
|
||||
// lengths are stored as 24-bit uints, i.e. up to 16 MiB per partition.
|
||||
n := 3 * (d.nOP - 1)
|
||||
partLens[d.nOP-1] = d.r.n - n
|
||||
if partLens[d.nOP-1] < 0 {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if n > 0 {
|
||||
buf := make([]byte, n)
|
||||
if err := d.r.ReadFull(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
for i := 0; i < d.nOP-1; i++ {
|
||||
pl := int(buf[3*i+0]) | int(buf[3*i+1])<<8 | int(buf[3*i+2])<<16
|
||||
if pl > partLens[d.nOP-1] {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
partLens[i] = pl
|
||||
partLens[d.nOP-1] -= pl
|
||||
}
|
||||
}
|
||||
|
||||
// We check if the final partition length can also fit into a 24-bit uint.
|
||||
// Strictly speaking, this isn't part of the spec, but it guards against a
|
||||
// malicious WEBP image that is too large to ReadFull the encoded DCT
|
||||
// coefficients into memory, whether that's because the actual WEBP file is
|
||||
// too large, or whether its RIFF metadata lists too large a chunk.
|
||||
if 1<<24 <= partLens[d.nOP-1] {
|
||||
return errors.New("vp8: too much data to decode")
|
||||
}
|
||||
|
||||
buf := make([]byte, d.r.n)
|
||||
if err := d.r.ReadFull(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
for i, pl := range partLens {
|
||||
if i == d.nOP {
|
||||
break
|
||||
}
|
||||
d.op[i].init(buf[:pl])
|
||||
buf = buf[pl:]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseOtherHeaders parses header information other than the frame header.
|
||||
func (d *Decoder) parseOtherHeaders() error {
|
||||
// Initialize and parse the first partition.
|
||||
firstPartition := make([]byte, d.frameHeader.FirstPartitionLen)
|
||||
if err := d.r.ReadFull(firstPartition); err != nil {
|
||||
return err
|
||||
}
|
||||
d.fp.init(firstPartition)
|
||||
if d.frameHeader.KeyFrame {
|
||||
// Read and ignore the color space and pixel clamp values. They are
|
||||
// specified in section 9.2, but are unimplemented.
|
||||
d.fp.readBit(uniformProb)
|
||||
d.fp.readBit(uniformProb)
|
||||
}
|
||||
d.parseSegmentHeader()
|
||||
d.parseFilterHeader()
|
||||
if err := d.parseOtherPartitions(); err != nil {
|
||||
return err
|
||||
}
|
||||
d.parseQuant()
|
||||
if !d.frameHeader.KeyFrame {
|
||||
// Golden and AltRef frames are specified in section 9.7.
|
||||
// TODO(nigeltao): implement. Note that they are only used for video, not still images.
|
||||
return errors.New("vp8: Golden / AltRef frames are not implemented")
|
||||
}
|
||||
// Read and ignore the refreshLastFrameBuffer bit, specified in section 9.8.
|
||||
// It applies only to video, and not still images.
|
||||
d.fp.readBit(uniformProb)
|
||||
d.parseTokenProb()
|
||||
d.useSkipProb = d.fp.readBit(uniformProb)
|
||||
if d.useSkipProb {
|
||||
d.skipProb = uint8(d.fp.readUint(uniformProb, 8))
|
||||
}
|
||||
if d.fp.unexpectedEOF {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DecodeFrame decodes the frame and returns it as an YCbCr image.
|
||||
// The image's contents are valid up until the next call to Decoder.Init.
|
||||
func (d *Decoder) DecodeFrame() (*image.YCbCr, error) {
|
||||
d.ensureImg()
|
||||
if err := d.parseOtherHeaders(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Reconstruct the rows.
|
||||
for mbx := 0; mbx < d.mbw; mbx++ {
|
||||
d.upMB[mbx] = mb{}
|
||||
}
|
||||
for mby := 0; mby < d.mbh; mby++ {
|
||||
d.leftMB = mb{}
|
||||
for mbx := 0; mbx < d.mbw; mbx++ {
|
||||
skip := d.reconstruct(mbx, mby)
|
||||
fs := d.filterParams[d.segment][btou(!d.usePredY16)]
|
||||
fs.inner = fs.inner || !skip
|
||||
d.perMBFilterParams[d.mbw*mby+mbx] = fs
|
||||
}
|
||||
}
|
||||
if d.fp.unexpectedEOF {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
for i := 0; i < d.nOP; i++ {
|
||||
if d.op[i].unexpectedEOF {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
}
|
||||
// Apply the loop filter.
|
||||
//
|
||||
// Even if we are using per-segment levels, section 15 says that "loop
|
||||
// filtering must be skipped entirely if loop_filter_level at either the
|
||||
// frame header level or macroblock override level is 0".
|
||||
if d.filterHeader.level != 0 {
|
||||
if d.filterHeader.simple {
|
||||
d.simpleFilter()
|
||||
} else {
|
||||
d.normalFilter()
|
||||
}
|
||||
}
|
||||
return d.img, nil
|
||||
}
|
||||
273
vendor/golang.org/x/image/vp8/filter.go
generated
vendored
Normal file
273
vendor/golang.org/x/image/vp8/filter.go
generated
vendored
Normal file
@@ -0,0 +1,273 @@
|
||||
// Copyright 2014 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 vp8
|
||||
|
||||
// filter2 modifies a 2-pixel wide or 2-pixel high band along an edge.
|
||||
func filter2(pix []byte, level, index, iStep, jStep int) {
|
||||
for n := 16; n > 0; n, index = n-1, index+iStep {
|
||||
p1 := int(pix[index-2*jStep])
|
||||
p0 := int(pix[index-1*jStep])
|
||||
q0 := int(pix[index+0*jStep])
|
||||
q1 := int(pix[index+1*jStep])
|
||||
if abs(p0-q0)<<1+abs(p1-q1)>>1 > level {
|
||||
continue
|
||||
}
|
||||
a := 3*(q0-p0) + clamp127(p1-q1)
|
||||
a1 := clamp15((a + 4) >> 3)
|
||||
a2 := clamp15((a + 3) >> 3)
|
||||
pix[index-1*jStep] = clamp255(p0 + a2)
|
||||
pix[index+0*jStep] = clamp255(q0 - a1)
|
||||
}
|
||||
}
|
||||
|
||||
// filter246 modifies a 2-, 4- or 6-pixel wide or high band along an edge.
|
||||
func filter246(pix []byte, n, level, ilevel, hlevel, index, iStep, jStep int, fourNotSix bool) {
|
||||
for ; n > 0; n, index = n-1, index+iStep {
|
||||
p3 := int(pix[index-4*jStep])
|
||||
p2 := int(pix[index-3*jStep])
|
||||
p1 := int(pix[index-2*jStep])
|
||||
p0 := int(pix[index-1*jStep])
|
||||
q0 := int(pix[index+0*jStep])
|
||||
q1 := int(pix[index+1*jStep])
|
||||
q2 := int(pix[index+2*jStep])
|
||||
q3 := int(pix[index+3*jStep])
|
||||
if abs(p0-q0)<<1+abs(p1-q1)>>1 > level {
|
||||
continue
|
||||
}
|
||||
if abs(p3-p2) > ilevel ||
|
||||
abs(p2-p1) > ilevel ||
|
||||
abs(p1-p0) > ilevel ||
|
||||
abs(q1-q0) > ilevel ||
|
||||
abs(q2-q1) > ilevel ||
|
||||
abs(q3-q2) > ilevel {
|
||||
continue
|
||||
}
|
||||
if abs(p1-p0) > hlevel || abs(q1-q0) > hlevel {
|
||||
// Filter 2 pixels.
|
||||
a := 3*(q0-p0) + clamp127(p1-q1)
|
||||
a1 := clamp15((a + 4) >> 3)
|
||||
a2 := clamp15((a + 3) >> 3)
|
||||
pix[index-1*jStep] = clamp255(p0 + a2)
|
||||
pix[index+0*jStep] = clamp255(q0 - a1)
|
||||
} else if fourNotSix {
|
||||
// Filter 4 pixels.
|
||||
a := 3 * (q0 - p0)
|
||||
a1 := clamp15((a + 4) >> 3)
|
||||
a2 := clamp15((a + 3) >> 3)
|
||||
a3 := (a1 + 1) >> 1
|
||||
pix[index-2*jStep] = clamp255(p1 + a3)
|
||||
pix[index-1*jStep] = clamp255(p0 + a2)
|
||||
pix[index+0*jStep] = clamp255(q0 - a1)
|
||||
pix[index+1*jStep] = clamp255(q1 - a3)
|
||||
} else {
|
||||
// Filter 6 pixels.
|
||||
a := clamp127(3*(q0-p0) + clamp127(p1-q1))
|
||||
a1 := (27*a + 63) >> 7
|
||||
a2 := (18*a + 63) >> 7
|
||||
a3 := (9*a + 63) >> 7
|
||||
pix[index-3*jStep] = clamp255(p2 + a3)
|
||||
pix[index-2*jStep] = clamp255(p1 + a2)
|
||||
pix[index-1*jStep] = clamp255(p0 + a1)
|
||||
pix[index+0*jStep] = clamp255(q0 - a1)
|
||||
pix[index+1*jStep] = clamp255(q1 - a2)
|
||||
pix[index+2*jStep] = clamp255(q2 - a3)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// simpleFilter implements the simple filter, as specified in section 15.2.
|
||||
func (d *Decoder) simpleFilter() {
|
||||
for mby := 0; mby < d.mbh; mby++ {
|
||||
for mbx := 0; mbx < d.mbw; mbx++ {
|
||||
f := d.perMBFilterParams[d.mbw*mby+mbx]
|
||||
if f.level == 0 {
|
||||
continue
|
||||
}
|
||||
l := int(f.level)
|
||||
yIndex := (mby*d.img.YStride + mbx) * 16
|
||||
if mbx > 0 {
|
||||
filter2(d.img.Y, l+4, yIndex, d.img.YStride, 1)
|
||||
}
|
||||
if f.inner {
|
||||
filter2(d.img.Y, l, yIndex+0x4, d.img.YStride, 1)
|
||||
filter2(d.img.Y, l, yIndex+0x8, d.img.YStride, 1)
|
||||
filter2(d.img.Y, l, yIndex+0xc, d.img.YStride, 1)
|
||||
}
|
||||
if mby > 0 {
|
||||
filter2(d.img.Y, l+4, yIndex, 1, d.img.YStride)
|
||||
}
|
||||
if f.inner {
|
||||
filter2(d.img.Y, l, yIndex+d.img.YStride*0x4, 1, d.img.YStride)
|
||||
filter2(d.img.Y, l, yIndex+d.img.YStride*0x8, 1, d.img.YStride)
|
||||
filter2(d.img.Y, l, yIndex+d.img.YStride*0xc, 1, d.img.YStride)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// normalFilter implements the normal filter, as specified in section 15.3.
|
||||
func (d *Decoder) normalFilter() {
|
||||
for mby := 0; mby < d.mbh; mby++ {
|
||||
for mbx := 0; mbx < d.mbw; mbx++ {
|
||||
f := d.perMBFilterParams[d.mbw*mby+mbx]
|
||||
if f.level == 0 {
|
||||
continue
|
||||
}
|
||||
l, il, hl := int(f.level), int(f.ilevel), int(f.hlevel)
|
||||
yIndex := (mby*d.img.YStride + mbx) * 16
|
||||
cIndex := (mby*d.img.CStride + mbx) * 8
|
||||
if mbx > 0 {
|
||||
filter246(d.img.Y, 16, l+4, il, hl, yIndex, d.img.YStride, 1, false)
|
||||
filter246(d.img.Cb, 8, l+4, il, hl, cIndex, d.img.CStride, 1, false)
|
||||
filter246(d.img.Cr, 8, l+4, il, hl, cIndex, d.img.CStride, 1, false)
|
||||
}
|
||||
if f.inner {
|
||||
filter246(d.img.Y, 16, l, il, hl, yIndex+0x4, d.img.YStride, 1, true)
|
||||
filter246(d.img.Y, 16, l, il, hl, yIndex+0x8, d.img.YStride, 1, true)
|
||||
filter246(d.img.Y, 16, l, il, hl, yIndex+0xc, d.img.YStride, 1, true)
|
||||
filter246(d.img.Cb, 8, l, il, hl, cIndex+0x4, d.img.CStride, 1, true)
|
||||
filter246(d.img.Cr, 8, l, il, hl, cIndex+0x4, d.img.CStride, 1, true)
|
||||
}
|
||||
if mby > 0 {
|
||||
filter246(d.img.Y, 16, l+4, il, hl, yIndex, 1, d.img.YStride, false)
|
||||
filter246(d.img.Cb, 8, l+4, il, hl, cIndex, 1, d.img.CStride, false)
|
||||
filter246(d.img.Cr, 8, l+4, il, hl, cIndex, 1, d.img.CStride, false)
|
||||
}
|
||||
if f.inner {
|
||||
filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0x4, 1, d.img.YStride, true)
|
||||
filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0x8, 1, d.img.YStride, true)
|
||||
filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0xc, 1, d.img.YStride, true)
|
||||
filter246(d.img.Cb, 8, l, il, hl, cIndex+d.img.CStride*0x4, 1, d.img.CStride, true)
|
||||
filter246(d.img.Cr, 8, l, il, hl, cIndex+d.img.CStride*0x4, 1, d.img.CStride, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// filterParam holds the loop filter parameters for a macroblock.
|
||||
type filterParam struct {
|
||||
// The first three fields are thresholds used by the loop filter to smooth
|
||||
// over the edges and interior of a macroblock. level is used by both the
|
||||
// simple and normal filters. The inner level and high edge variance level
|
||||
// are only used by the normal filter.
|
||||
level, ilevel, hlevel uint8
|
||||
// inner is whether the inner loop filter cannot be optimized out as a
|
||||
// no-op for this particular macroblock.
|
||||
inner bool
|
||||
}
|
||||
|
||||
// computeFilterParams computes the loop filter parameters, as specified in
|
||||
// section 15.4.
|
||||
func (d *Decoder) computeFilterParams() {
|
||||
for i := range d.filterParams {
|
||||
baseLevel := d.filterHeader.level
|
||||
if d.segmentHeader.useSegment {
|
||||
baseLevel = d.segmentHeader.filterStrength[i]
|
||||
if d.segmentHeader.relativeDelta {
|
||||
baseLevel += d.filterHeader.level
|
||||
}
|
||||
}
|
||||
|
||||
for j := range d.filterParams[i] {
|
||||
p := &d.filterParams[i][j]
|
||||
p.inner = j != 0
|
||||
level := baseLevel
|
||||
if d.filterHeader.useLFDelta {
|
||||
// The libwebp C code has a "TODO: only CURRENT is handled for now."
|
||||
level += d.filterHeader.refLFDelta[0]
|
||||
if j != 0 {
|
||||
level += d.filterHeader.modeLFDelta[0]
|
||||
}
|
||||
}
|
||||
if level <= 0 {
|
||||
p.level = 0
|
||||
continue
|
||||
}
|
||||
if level > 63 {
|
||||
level = 63
|
||||
}
|
||||
ilevel := level
|
||||
if d.filterHeader.sharpness > 0 {
|
||||
if d.filterHeader.sharpness > 4 {
|
||||
ilevel >>= 2
|
||||
} else {
|
||||
ilevel >>= 1
|
||||
}
|
||||
if x := int8(9 - d.filterHeader.sharpness); ilevel > x {
|
||||
ilevel = x
|
||||
}
|
||||
}
|
||||
if ilevel < 1 {
|
||||
ilevel = 1
|
||||
}
|
||||
p.ilevel = uint8(ilevel)
|
||||
p.level = uint8(2*level + ilevel)
|
||||
if d.frameHeader.KeyFrame {
|
||||
if level < 15 {
|
||||
p.hlevel = 0
|
||||
} else if level < 40 {
|
||||
p.hlevel = 1
|
||||
} else {
|
||||
p.hlevel = 2
|
||||
}
|
||||
} else {
|
||||
if level < 15 {
|
||||
p.hlevel = 0
|
||||
} else if level < 20 {
|
||||
p.hlevel = 1
|
||||
} else if level < 40 {
|
||||
p.hlevel = 2
|
||||
} else {
|
||||
p.hlevel = 3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// intSize is either 32 or 64.
|
||||
const intSize = 32 << (^uint(0) >> 63)
|
||||
|
||||
func abs(x int) int {
|
||||
// m := -1 if x < 0. m := 0 otherwise.
|
||||
m := x >> (intSize - 1)
|
||||
|
||||
// In two's complement representation, the negative number
|
||||
// of any number (except the smallest one) can be computed
|
||||
// by flipping all the bits and add 1. This is faster than
|
||||
// code with a branch.
|
||||
// See Hacker's Delight, section 2-4.
|
||||
return (x ^ m) - m
|
||||
}
|
||||
|
||||
func clamp15(x int) int {
|
||||
if x < -16 {
|
||||
return -16
|
||||
}
|
||||
if x > 15 {
|
||||
return 15
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func clamp127(x int) int {
|
||||
if x < -128 {
|
||||
return -128
|
||||
}
|
||||
if x > 127 {
|
||||
return 127
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func clamp255(x int) uint8 {
|
||||
if x < 0 {
|
||||
return 0
|
||||
}
|
||||
if x > 255 {
|
||||
return 255
|
||||
}
|
||||
return uint8(x)
|
||||
}
|
||||
98
vendor/golang.org/x/image/vp8/idct.go
generated
vendored
Normal file
98
vendor/golang.org/x/image/vp8/idct.go
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright 2011 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 vp8
|
||||
|
||||
// This file implements the inverse Discrete Cosine Transform and the inverse
|
||||
// Walsh Hadamard Transform (WHT), as specified in sections 14.3 and 14.4.
|
||||
|
||||
func clip8(i int32) uint8 {
|
||||
if i < 0 {
|
||||
return 0
|
||||
}
|
||||
if i > 255 {
|
||||
return 255
|
||||
}
|
||||
return uint8(i)
|
||||
}
|
||||
|
||||
func (z *Decoder) inverseDCT4(y, x, coeffBase int) {
|
||||
const (
|
||||
c1 = 85627 // 65536 * cos(pi/8) * sqrt(2).
|
||||
c2 = 35468 // 65536 * sin(pi/8) * sqrt(2).
|
||||
)
|
||||
var m [4][4]int32
|
||||
for i := 0; i < 4; i++ {
|
||||
a := int32(z.coeff[coeffBase+0]) + int32(z.coeff[coeffBase+8])
|
||||
b := int32(z.coeff[coeffBase+0]) - int32(z.coeff[coeffBase+8])
|
||||
c := (int32(z.coeff[coeffBase+4])*c2)>>16 - (int32(z.coeff[coeffBase+12])*c1)>>16
|
||||
d := (int32(z.coeff[coeffBase+4])*c1)>>16 + (int32(z.coeff[coeffBase+12])*c2)>>16
|
||||
m[i][0] = a + d
|
||||
m[i][1] = b + c
|
||||
m[i][2] = b - c
|
||||
m[i][3] = a - d
|
||||
coeffBase++
|
||||
}
|
||||
for j := 0; j < 4; j++ {
|
||||
dc := m[0][j] + 4
|
||||
a := dc + m[2][j]
|
||||
b := dc - m[2][j]
|
||||
c := (m[1][j]*c2)>>16 - (m[3][j]*c1)>>16
|
||||
d := (m[1][j]*c1)>>16 + (m[3][j]*c2)>>16
|
||||
z.ybr[y+j][x+0] = clip8(int32(z.ybr[y+j][x+0]) + (a+d)>>3)
|
||||
z.ybr[y+j][x+1] = clip8(int32(z.ybr[y+j][x+1]) + (b+c)>>3)
|
||||
z.ybr[y+j][x+2] = clip8(int32(z.ybr[y+j][x+2]) + (b-c)>>3)
|
||||
z.ybr[y+j][x+3] = clip8(int32(z.ybr[y+j][x+3]) + (a-d)>>3)
|
||||
}
|
||||
}
|
||||
|
||||
func (z *Decoder) inverseDCT4DCOnly(y, x, coeffBase int) {
|
||||
dc := (int32(z.coeff[coeffBase+0]) + 4) >> 3
|
||||
for j := 0; j < 4; j++ {
|
||||
for i := 0; i < 4; i++ {
|
||||
z.ybr[y+j][x+i] = clip8(int32(z.ybr[y+j][x+i]) + dc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (z *Decoder) inverseDCT8(y, x, coeffBase int) {
|
||||
z.inverseDCT4(y+0, x+0, coeffBase+0*16)
|
||||
z.inverseDCT4(y+0, x+4, coeffBase+1*16)
|
||||
z.inverseDCT4(y+4, x+0, coeffBase+2*16)
|
||||
z.inverseDCT4(y+4, x+4, coeffBase+3*16)
|
||||
}
|
||||
|
||||
func (z *Decoder) inverseDCT8DCOnly(y, x, coeffBase int) {
|
||||
z.inverseDCT4DCOnly(y+0, x+0, coeffBase+0*16)
|
||||
z.inverseDCT4DCOnly(y+0, x+4, coeffBase+1*16)
|
||||
z.inverseDCT4DCOnly(y+4, x+0, coeffBase+2*16)
|
||||
z.inverseDCT4DCOnly(y+4, x+4, coeffBase+3*16)
|
||||
}
|
||||
|
||||
func (d *Decoder) inverseWHT16() {
|
||||
var m [16]int32
|
||||
for i := 0; i < 4; i++ {
|
||||
a0 := int32(d.coeff[384+0+i]) + int32(d.coeff[384+12+i])
|
||||
a1 := int32(d.coeff[384+4+i]) + int32(d.coeff[384+8+i])
|
||||
a2 := int32(d.coeff[384+4+i]) - int32(d.coeff[384+8+i])
|
||||
a3 := int32(d.coeff[384+0+i]) - int32(d.coeff[384+12+i])
|
||||
m[0+i] = a0 + a1
|
||||
m[8+i] = a0 - a1
|
||||
m[4+i] = a3 + a2
|
||||
m[12+i] = a3 - a2
|
||||
}
|
||||
out := 0
|
||||
for i := 0; i < 4; i++ {
|
||||
dc := m[0+i*4] + 3
|
||||
a0 := dc + m[3+i*4]
|
||||
a1 := m[1+i*4] + m[2+i*4]
|
||||
a2 := m[1+i*4] - m[2+i*4]
|
||||
a3 := dc - m[3+i*4]
|
||||
d.coeff[out+0] = int16((a0 + a1) >> 3)
|
||||
d.coeff[out+16] = int16((a3 + a2) >> 3)
|
||||
d.coeff[out+32] = int16((a0 - a1) >> 3)
|
||||
d.coeff[out+48] = int16((a3 - a2) >> 3)
|
||||
out += 64
|
||||
}
|
||||
}
|
||||
129
vendor/golang.org/x/image/vp8/partition.go
generated
vendored
Normal file
129
vendor/golang.org/x/image/vp8/partition.go
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
// Copyright 2011 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 vp8
|
||||
|
||||
// Each VP8 frame consists of between 2 and 9 bitstream partitions.
|
||||
// Each partition is byte-aligned and is independently arithmetic-encoded.
|
||||
//
|
||||
// This file implements decoding a partition's bitstream, as specified in
|
||||
// chapter 7. The implementation follows libwebp's approach instead of the
|
||||
// specification's reference C implementation. For example, we use a look-up
|
||||
// table instead of a for loop to recalibrate the encoded range.
|
||||
|
||||
var (
|
||||
lutShift = [127]uint8{
|
||||
7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
}
|
||||
lutRangeM1 = [127]uint8{
|
||||
127,
|
||||
127, 191,
|
||||
127, 159, 191, 223,
|
||||
127, 143, 159, 175, 191, 207, 223, 239,
|
||||
127, 135, 143, 151, 159, 167, 175, 183, 191, 199, 207, 215, 223, 231, 239, 247,
|
||||
127, 131, 135, 139, 143, 147, 151, 155, 159, 163, 167, 171, 175, 179, 183, 187,
|
||||
191, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251,
|
||||
127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157,
|
||||
159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189,
|
||||
191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221,
|
||||
223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253,
|
||||
}
|
||||
)
|
||||
|
||||
// uniformProb represents a 50% probability that the next bit is 0.
|
||||
const uniformProb = 128
|
||||
|
||||
// partition holds arithmetic-coded bits.
|
||||
type partition struct {
|
||||
// buf is the input bytes.
|
||||
buf []byte
|
||||
// r is how many of buf's bytes have been consumed.
|
||||
r int
|
||||
// rangeM1 is range minus 1, where range is in the arithmetic coding sense,
|
||||
// not the Go language sense.
|
||||
rangeM1 uint32
|
||||
// bits and nBits hold those bits shifted out of buf but not yet consumed.
|
||||
bits uint32
|
||||
nBits uint8
|
||||
// unexpectedEOF tells whether we tried to read past buf.
|
||||
unexpectedEOF bool
|
||||
}
|
||||
|
||||
// init initializes the partition.
|
||||
func (p *partition) init(buf []byte) {
|
||||
p.buf = buf
|
||||
p.r = 0
|
||||
p.rangeM1 = 254
|
||||
p.bits = 0
|
||||
p.nBits = 0
|
||||
p.unexpectedEOF = false
|
||||
}
|
||||
|
||||
// readBit returns the next bit.
|
||||
func (p *partition) readBit(prob uint8) bool {
|
||||
if p.nBits < 8 {
|
||||
if p.r >= len(p.buf) {
|
||||
p.unexpectedEOF = true
|
||||
return false
|
||||
}
|
||||
// Expression split for 386 compiler.
|
||||
x := uint32(p.buf[p.r])
|
||||
p.bits |= x << (8 - p.nBits)
|
||||
p.r++
|
||||
p.nBits += 8
|
||||
}
|
||||
split := (p.rangeM1*uint32(prob))>>8 + 1
|
||||
bit := p.bits >= split<<8
|
||||
if bit {
|
||||
p.rangeM1 -= split
|
||||
p.bits -= split << 8
|
||||
} else {
|
||||
p.rangeM1 = split - 1
|
||||
}
|
||||
if p.rangeM1 < 127 {
|
||||
shift := lutShift[p.rangeM1]
|
||||
p.rangeM1 = uint32(lutRangeM1[p.rangeM1])
|
||||
p.bits <<= shift
|
||||
p.nBits -= shift
|
||||
}
|
||||
return bit
|
||||
}
|
||||
|
||||
// readUint returns the next n-bit unsigned integer.
|
||||
func (p *partition) readUint(prob, n uint8) uint32 {
|
||||
var u uint32
|
||||
for n > 0 {
|
||||
n--
|
||||
if p.readBit(prob) {
|
||||
u |= 1 << n
|
||||
}
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
// readInt returns the next n-bit signed integer.
|
||||
func (p *partition) readInt(prob, n uint8) int32 {
|
||||
u := p.readUint(prob, n)
|
||||
b := p.readBit(prob)
|
||||
if b {
|
||||
return -int32(u)
|
||||
}
|
||||
return int32(u)
|
||||
}
|
||||
|
||||
// readOptionalInt returns the next n-bit signed integer in an encoding
|
||||
// where the likely result is zero.
|
||||
func (p *partition) readOptionalInt(prob, n uint8) int32 {
|
||||
if !p.readBit(prob) {
|
||||
return 0
|
||||
}
|
||||
return p.readInt(prob, n)
|
||||
}
|
||||
201
vendor/golang.org/x/image/vp8/pred.go
generated
vendored
Normal file
201
vendor/golang.org/x/image/vp8/pred.go
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
// Copyright 2011 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 vp8
|
||||
|
||||
// This file implements parsing the predictor modes, as specified in chapter
|
||||
// 11.
|
||||
|
||||
func (d *Decoder) parsePredModeY16(mbx int) {
|
||||
var p uint8
|
||||
if !d.fp.readBit(156) {
|
||||
if !d.fp.readBit(163) {
|
||||
p = predDC
|
||||
} else {
|
||||
p = predVE
|
||||
}
|
||||
} else if !d.fp.readBit(128) {
|
||||
p = predHE
|
||||
} else {
|
||||
p = predTM
|
||||
}
|
||||
for i := 0; i < 4; i++ {
|
||||
d.upMB[mbx].pred[i] = p
|
||||
d.leftMB.pred[i] = p
|
||||
}
|
||||
d.predY16 = p
|
||||
}
|
||||
|
||||
func (d *Decoder) parsePredModeC8() {
|
||||
if !d.fp.readBit(142) {
|
||||
d.predC8 = predDC
|
||||
} else if !d.fp.readBit(114) {
|
||||
d.predC8 = predVE
|
||||
} else if !d.fp.readBit(183) {
|
||||
d.predC8 = predHE
|
||||
} else {
|
||||
d.predC8 = predTM
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Decoder) parsePredModeY4(mbx int) {
|
||||
for j := 0; j < 4; j++ {
|
||||
p := d.leftMB.pred[j]
|
||||
for i := 0; i < 4; i++ {
|
||||
prob := &predProb[d.upMB[mbx].pred[i]][p]
|
||||
if !d.fp.readBit(prob[0]) {
|
||||
p = predDC
|
||||
} else if !d.fp.readBit(prob[1]) {
|
||||
p = predTM
|
||||
} else if !d.fp.readBit(prob[2]) {
|
||||
p = predVE
|
||||
} else if !d.fp.readBit(prob[3]) {
|
||||
if !d.fp.readBit(prob[4]) {
|
||||
p = predHE
|
||||
} else if !d.fp.readBit(prob[5]) {
|
||||
p = predRD
|
||||
} else {
|
||||
p = predVR
|
||||
}
|
||||
} else if !d.fp.readBit(prob[6]) {
|
||||
p = predLD
|
||||
} else if !d.fp.readBit(prob[7]) {
|
||||
p = predVL
|
||||
} else if !d.fp.readBit(prob[8]) {
|
||||
p = predHD
|
||||
} else {
|
||||
p = predHU
|
||||
}
|
||||
d.predY4[j][i] = p
|
||||
d.upMB[mbx].pred[i] = p
|
||||
}
|
||||
d.leftMB.pred[j] = p
|
||||
}
|
||||
}
|
||||
|
||||
// predProb are the probabilities to decode a 4x4 region's predictor mode given
|
||||
// the predictor modes of the regions above and left of it.
|
||||
// These values are specified in section 11.5.
|
||||
var predProb = [nPred][nPred][9]uint8{
|
||||
{
|
||||
{231, 120, 48, 89, 115, 113, 120, 152, 112},
|
||||
{152, 179, 64, 126, 170, 118, 46, 70, 95},
|
||||
{175, 69, 143, 80, 85, 82, 72, 155, 103},
|
||||
{56, 58, 10, 171, 218, 189, 17, 13, 152},
|
||||
{114, 26, 17, 163, 44, 195, 21, 10, 173},
|
||||
{121, 24, 80, 195, 26, 62, 44, 64, 85},
|
||||
{144, 71, 10, 38, 171, 213, 144, 34, 26},
|
||||
{170, 46, 55, 19, 136, 160, 33, 206, 71},
|
||||
{63, 20, 8, 114, 114, 208, 12, 9, 226},
|
||||
{81, 40, 11, 96, 182, 84, 29, 16, 36},
|
||||
},
|
||||
{
|
||||
{134, 183, 89, 137, 98, 101, 106, 165, 148},
|
||||
{72, 187, 100, 130, 157, 111, 32, 75, 80},
|
||||
{66, 102, 167, 99, 74, 62, 40, 234, 128},
|
||||
{41, 53, 9, 178, 241, 141, 26, 8, 107},
|
||||
{74, 43, 26, 146, 73, 166, 49, 23, 157},
|
||||
{65, 38, 105, 160, 51, 52, 31, 115, 128},
|
||||
{104, 79, 12, 27, 217, 255, 87, 17, 7},
|
||||
{87, 68, 71, 44, 114, 51, 15, 186, 23},
|
||||
{47, 41, 14, 110, 182, 183, 21, 17, 194},
|
||||
{66, 45, 25, 102, 197, 189, 23, 18, 22},
|
||||
},
|
||||
{
|
||||
{88, 88, 147, 150, 42, 46, 45, 196, 205},
|
||||
{43, 97, 183, 117, 85, 38, 35, 179, 61},
|
||||
{39, 53, 200, 87, 26, 21, 43, 232, 171},
|
||||
{56, 34, 51, 104, 114, 102, 29, 93, 77},
|
||||
{39, 28, 85, 171, 58, 165, 90, 98, 64},
|
||||
{34, 22, 116, 206, 23, 34, 43, 166, 73},
|
||||
{107, 54, 32, 26, 51, 1, 81, 43, 31},
|
||||
{68, 25, 106, 22, 64, 171, 36, 225, 114},
|
||||
{34, 19, 21, 102, 132, 188, 16, 76, 124},
|
||||
{62, 18, 78, 95, 85, 57, 50, 48, 51},
|
||||
},
|
||||
{
|
||||
{193, 101, 35, 159, 215, 111, 89, 46, 111},
|
||||
{60, 148, 31, 172, 219, 228, 21, 18, 111},
|
||||
{112, 113, 77, 85, 179, 255, 38, 120, 114},
|
||||
{40, 42, 1, 196, 245, 209, 10, 25, 109},
|
||||
{88, 43, 29, 140, 166, 213, 37, 43, 154},
|
||||
{61, 63, 30, 155, 67, 45, 68, 1, 209},
|
||||
{100, 80, 8, 43, 154, 1, 51, 26, 71},
|
||||
{142, 78, 78, 16, 255, 128, 34, 197, 171},
|
||||
{41, 40, 5, 102, 211, 183, 4, 1, 221},
|
||||
{51, 50, 17, 168, 209, 192, 23, 25, 82},
|
||||
},
|
||||
{
|
||||
{138, 31, 36, 171, 27, 166, 38, 44, 229},
|
||||
{67, 87, 58, 169, 82, 115, 26, 59, 179},
|
||||
{63, 59, 90, 180, 59, 166, 93, 73, 154},
|
||||
{40, 40, 21, 116, 143, 209, 34, 39, 175},
|
||||
{47, 15, 16, 183, 34, 223, 49, 45, 183},
|
||||
{46, 17, 33, 183, 6, 98, 15, 32, 183},
|
||||
{57, 46, 22, 24, 128, 1, 54, 17, 37},
|
||||
{65, 32, 73, 115, 28, 128, 23, 128, 205},
|
||||
{40, 3, 9, 115, 51, 192, 18, 6, 223},
|
||||
{87, 37, 9, 115, 59, 77, 64, 21, 47},
|
||||
},
|
||||
{
|
||||
{104, 55, 44, 218, 9, 54, 53, 130, 226},
|
||||
{64, 90, 70, 205, 40, 41, 23, 26, 57},
|
||||
{54, 57, 112, 184, 5, 41, 38, 166, 213},
|
||||
{30, 34, 26, 133, 152, 116, 10, 32, 134},
|
||||
{39, 19, 53, 221, 26, 114, 32, 73, 255},
|
||||
{31, 9, 65, 234, 2, 15, 1, 118, 73},
|
||||
{75, 32, 12, 51, 192, 255, 160, 43, 51},
|
||||
{88, 31, 35, 67, 102, 85, 55, 186, 85},
|
||||
{56, 21, 23, 111, 59, 205, 45, 37, 192},
|
||||
{55, 38, 70, 124, 73, 102, 1, 34, 98},
|
||||
},
|
||||
{
|
||||
{125, 98, 42, 88, 104, 85, 117, 175, 82},
|
||||
{95, 84, 53, 89, 128, 100, 113, 101, 45},
|
||||
{75, 79, 123, 47, 51, 128, 81, 171, 1},
|
||||
{57, 17, 5, 71, 102, 57, 53, 41, 49},
|
||||
{38, 33, 13, 121, 57, 73, 26, 1, 85},
|
||||
{41, 10, 67, 138, 77, 110, 90, 47, 114},
|
||||
{115, 21, 2, 10, 102, 255, 166, 23, 6},
|
||||
{101, 29, 16, 10, 85, 128, 101, 196, 26},
|
||||
{57, 18, 10, 102, 102, 213, 34, 20, 43},
|
||||
{117, 20, 15, 36, 163, 128, 68, 1, 26},
|
||||
},
|
||||
{
|
||||
{102, 61, 71, 37, 34, 53, 31, 243, 192},
|
||||
{69, 60, 71, 38, 73, 119, 28, 222, 37},
|
||||
{68, 45, 128, 34, 1, 47, 11, 245, 171},
|
||||
{62, 17, 19, 70, 146, 85, 55, 62, 70},
|
||||
{37, 43, 37, 154, 100, 163, 85, 160, 1},
|
||||
{63, 9, 92, 136, 28, 64, 32, 201, 85},
|
||||
{75, 15, 9, 9, 64, 255, 184, 119, 16},
|
||||
{86, 6, 28, 5, 64, 255, 25, 248, 1},
|
||||
{56, 8, 17, 132, 137, 255, 55, 116, 128},
|
||||
{58, 15, 20, 82, 135, 57, 26, 121, 40},
|
||||
},
|
||||
{
|
||||
{164, 50, 31, 137, 154, 133, 25, 35, 218},
|
||||
{51, 103, 44, 131, 131, 123, 31, 6, 158},
|
||||
{86, 40, 64, 135, 148, 224, 45, 183, 128},
|
||||
{22, 26, 17, 131, 240, 154, 14, 1, 209},
|
||||
{45, 16, 21, 91, 64, 222, 7, 1, 197},
|
||||
{56, 21, 39, 155, 60, 138, 23, 102, 213},
|
||||
{83, 12, 13, 54, 192, 255, 68, 47, 28},
|
||||
{85, 26, 85, 85, 128, 128, 32, 146, 171},
|
||||
{18, 11, 7, 63, 144, 171, 4, 4, 246},
|
||||
{35, 27, 10, 146, 174, 171, 12, 26, 128},
|
||||
},
|
||||
{
|
||||
{190, 80, 35, 99, 180, 80, 126, 54, 45},
|
||||
{85, 126, 47, 87, 176, 51, 41, 20, 32},
|
||||
{101, 75, 128, 139, 118, 146, 116, 128, 85},
|
||||
{56, 41, 15, 176, 236, 85, 37, 9, 62},
|
||||
{71, 30, 17, 119, 118, 255, 17, 18, 138},
|
||||
{101, 38, 60, 138, 55, 70, 43, 26, 142},
|
||||
{146, 36, 19, 30, 171, 255, 97, 27, 20},
|
||||
{138, 45, 61, 62, 219, 1, 81, 188, 64},
|
||||
{32, 41, 20, 117, 151, 142, 20, 21, 163},
|
||||
{112, 19, 12, 61, 195, 128, 48, 4, 24},
|
||||
},
|
||||
}
|
||||
553
vendor/golang.org/x/image/vp8/predfunc.go
generated
vendored
Normal file
553
vendor/golang.org/x/image/vp8/predfunc.go
generated
vendored
Normal file
@@ -0,0 +1,553 @@
|
||||
// Copyright 2011 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 vp8
|
||||
|
||||
// This file implements the predicition functions, as specified in chapter 12.
|
||||
//
|
||||
// For each macroblock (of 1x16x16 luma and 2x8x8 chroma coefficients), the
|
||||
// luma values are either predicted as one large 16x16 region or 16 separate
|
||||
// 4x4 regions. The chroma values are always predicted as one 8x8 region.
|
||||
//
|
||||
// For 4x4 regions, the target block's predicted values (Xs) are a function of
|
||||
// its previously-decoded top and left border values, as well as a number of
|
||||
// pixels from the top-right:
|
||||
//
|
||||
// a b c d e f g h
|
||||
// p X X X X
|
||||
// q X X X X
|
||||
// r X X X X
|
||||
// s X X X X
|
||||
//
|
||||
// The predictor modes are:
|
||||
// - DC: all Xs = (b + c + d + e + p + q + r + s + 4) / 8.
|
||||
// - TM: the first X = (b + p - a), the second X = (c + p - a), and so on.
|
||||
// - VE: each X = the weighted average of its column's top value and that
|
||||
// value's neighbors, i.e. averages of abc, bcd, cde or def.
|
||||
// - HE: similar to VE except rows instead of columns, and the final row is
|
||||
// an average of r, s and s.
|
||||
// - RD, VR, LD, VL, HD, HU: these diagonal modes ("Right Down", "Vertical
|
||||
// Right", etc) are more complicated and are described in section 12.3.
|
||||
// All Xs are clipped to the range [0, 255].
|
||||
//
|
||||
// For 8x8 and 16x16 regions, the target block's predicted values are a
|
||||
// function of the top and left border values without the top-right overhang,
|
||||
// i.e. without the 8x8 or 16x16 equivalent of f, g and h. Furthermore:
|
||||
// - There are no diagonal predictor modes, only DC, TM, VE and HE.
|
||||
// - The DC mode has variants for macroblocks in the top row and/or left
|
||||
// column, i.e. for macroblocks with mby == 0 || mbx == 0.
|
||||
// - The VE and HE modes take only the column top or row left values; they do
|
||||
// not smooth that top/left value with its neighbors.
|
||||
|
||||
// nPred is the number of predictor modes, not including the Top/Left versions
|
||||
// of the DC predictor mode.
|
||||
const nPred = 10
|
||||
|
||||
const (
|
||||
predDC = iota
|
||||
predTM
|
||||
predVE
|
||||
predHE
|
||||
predRD
|
||||
predVR
|
||||
predLD
|
||||
predVL
|
||||
predHD
|
||||
predHU
|
||||
predDCTop
|
||||
predDCLeft
|
||||
predDCTopLeft
|
||||
)
|
||||
|
||||
func checkTopLeftPred(mbx, mby int, p uint8) uint8 {
|
||||
if p != predDC {
|
||||
return p
|
||||
}
|
||||
if mbx == 0 {
|
||||
if mby == 0 {
|
||||
return predDCTopLeft
|
||||
}
|
||||
return predDCLeft
|
||||
}
|
||||
if mby == 0 {
|
||||
return predDCTop
|
||||
}
|
||||
return predDC
|
||||
}
|
||||
|
||||
var predFunc4 = [...]func(*Decoder, int, int){
|
||||
predFunc4DC,
|
||||
predFunc4TM,
|
||||
predFunc4VE,
|
||||
predFunc4HE,
|
||||
predFunc4RD,
|
||||
predFunc4VR,
|
||||
predFunc4LD,
|
||||
predFunc4VL,
|
||||
predFunc4HD,
|
||||
predFunc4HU,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
}
|
||||
|
||||
var predFunc8 = [...]func(*Decoder, int, int){
|
||||
predFunc8DC,
|
||||
predFunc8TM,
|
||||
predFunc8VE,
|
||||
predFunc8HE,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
predFunc8DCTop,
|
||||
predFunc8DCLeft,
|
||||
predFunc8DCTopLeft,
|
||||
}
|
||||
|
||||
var predFunc16 = [...]func(*Decoder, int, int){
|
||||
predFunc16DC,
|
||||
predFunc16TM,
|
||||
predFunc16VE,
|
||||
predFunc16HE,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
predFunc16DCTop,
|
||||
predFunc16DCLeft,
|
||||
predFunc16DCTopLeft,
|
||||
}
|
||||
|
||||
func predFunc4DC(z *Decoder, y, x int) {
|
||||
sum := uint32(4)
|
||||
for i := 0; i < 4; i++ {
|
||||
sum += uint32(z.ybr[y-1][x+i])
|
||||
}
|
||||
for j := 0; j < 4; j++ {
|
||||
sum += uint32(z.ybr[y+j][x-1])
|
||||
}
|
||||
avg := uint8(sum / 8)
|
||||
for j := 0; j < 4; j++ {
|
||||
for i := 0; i < 4; i++ {
|
||||
z.ybr[y+j][x+i] = avg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func predFunc4TM(z *Decoder, y, x int) {
|
||||
delta0 := -int32(z.ybr[y-1][x-1])
|
||||
for j := 0; j < 4; j++ {
|
||||
delta1 := delta0 + int32(z.ybr[y+j][x-1])
|
||||
for i := 0; i < 4; i++ {
|
||||
delta2 := delta1 + int32(z.ybr[y-1][x+i])
|
||||
z.ybr[y+j][x+i] = uint8(clip(delta2, 0, 255))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func predFunc4VE(z *Decoder, y, x int) {
|
||||
a := int32(z.ybr[y-1][x-1])
|
||||
b := int32(z.ybr[y-1][x+0])
|
||||
c := int32(z.ybr[y-1][x+1])
|
||||
d := int32(z.ybr[y-1][x+2])
|
||||
e := int32(z.ybr[y-1][x+3])
|
||||
f := int32(z.ybr[y-1][x+4])
|
||||
abc := uint8((a + 2*b + c + 2) / 4)
|
||||
bcd := uint8((b + 2*c + d + 2) / 4)
|
||||
cde := uint8((c + 2*d + e + 2) / 4)
|
||||
def := uint8((d + 2*e + f + 2) / 4)
|
||||
for j := 0; j < 4; j++ {
|
||||
z.ybr[y+j][x+0] = abc
|
||||
z.ybr[y+j][x+1] = bcd
|
||||
z.ybr[y+j][x+2] = cde
|
||||
z.ybr[y+j][x+3] = def
|
||||
}
|
||||
}
|
||||
|
||||
func predFunc4HE(z *Decoder, y, x int) {
|
||||
s := int32(z.ybr[y+3][x-1])
|
||||
r := int32(z.ybr[y+2][x-1])
|
||||
q := int32(z.ybr[y+1][x-1])
|
||||
p := int32(z.ybr[y+0][x-1])
|
||||
a := int32(z.ybr[y-1][x-1])
|
||||
ssr := uint8((s + 2*s + r + 2) / 4)
|
||||
srq := uint8((s + 2*r + q + 2) / 4)
|
||||
rqp := uint8((r + 2*q + p + 2) / 4)
|
||||
apq := uint8((a + 2*p + q + 2) / 4)
|
||||
for i := 0; i < 4; i++ {
|
||||
z.ybr[y+0][x+i] = apq
|
||||
z.ybr[y+1][x+i] = rqp
|
||||
z.ybr[y+2][x+i] = srq
|
||||
z.ybr[y+3][x+i] = ssr
|
||||
}
|
||||
}
|
||||
|
||||
func predFunc4RD(z *Decoder, y, x int) {
|
||||
s := int32(z.ybr[y+3][x-1])
|
||||
r := int32(z.ybr[y+2][x-1])
|
||||
q := int32(z.ybr[y+1][x-1])
|
||||
p := int32(z.ybr[y+0][x-1])
|
||||
a := int32(z.ybr[y-1][x-1])
|
||||
b := int32(z.ybr[y-1][x+0])
|
||||
c := int32(z.ybr[y-1][x+1])
|
||||
d := int32(z.ybr[y-1][x+2])
|
||||
e := int32(z.ybr[y-1][x+3])
|
||||
srq := uint8((s + 2*r + q + 2) / 4)
|
||||
rqp := uint8((r + 2*q + p + 2) / 4)
|
||||
qpa := uint8((q + 2*p + a + 2) / 4)
|
||||
pab := uint8((p + 2*a + b + 2) / 4)
|
||||
abc := uint8((a + 2*b + c + 2) / 4)
|
||||
bcd := uint8((b + 2*c + d + 2) / 4)
|
||||
cde := uint8((c + 2*d + e + 2) / 4)
|
||||
z.ybr[y+0][x+0] = pab
|
||||
z.ybr[y+0][x+1] = abc
|
||||
z.ybr[y+0][x+2] = bcd
|
||||
z.ybr[y+0][x+3] = cde
|
||||
z.ybr[y+1][x+0] = qpa
|
||||
z.ybr[y+1][x+1] = pab
|
||||
z.ybr[y+1][x+2] = abc
|
||||
z.ybr[y+1][x+3] = bcd
|
||||
z.ybr[y+2][x+0] = rqp
|
||||
z.ybr[y+2][x+1] = qpa
|
||||
z.ybr[y+2][x+2] = pab
|
||||
z.ybr[y+2][x+3] = abc
|
||||
z.ybr[y+3][x+0] = srq
|
||||
z.ybr[y+3][x+1] = rqp
|
||||
z.ybr[y+3][x+2] = qpa
|
||||
z.ybr[y+3][x+3] = pab
|
||||
}
|
||||
|
||||
func predFunc4VR(z *Decoder, y, x int) {
|
||||
r := int32(z.ybr[y+2][x-1])
|
||||
q := int32(z.ybr[y+1][x-1])
|
||||
p := int32(z.ybr[y+0][x-1])
|
||||
a := int32(z.ybr[y-1][x-1])
|
||||
b := int32(z.ybr[y-1][x+0])
|
||||
c := int32(z.ybr[y-1][x+1])
|
||||
d := int32(z.ybr[y-1][x+2])
|
||||
e := int32(z.ybr[y-1][x+3])
|
||||
ab := uint8((a + b + 1) / 2)
|
||||
bc := uint8((b + c + 1) / 2)
|
||||
cd := uint8((c + d + 1) / 2)
|
||||
de := uint8((d + e + 1) / 2)
|
||||
rqp := uint8((r + 2*q + p + 2) / 4)
|
||||
qpa := uint8((q + 2*p + a + 2) / 4)
|
||||
pab := uint8((p + 2*a + b + 2) / 4)
|
||||
abc := uint8((a + 2*b + c + 2) / 4)
|
||||
bcd := uint8((b + 2*c + d + 2) / 4)
|
||||
cde := uint8((c + 2*d + e + 2) / 4)
|
||||
z.ybr[y+0][x+0] = ab
|
||||
z.ybr[y+0][x+1] = bc
|
||||
z.ybr[y+0][x+2] = cd
|
||||
z.ybr[y+0][x+3] = de
|
||||
z.ybr[y+1][x+0] = pab
|
||||
z.ybr[y+1][x+1] = abc
|
||||
z.ybr[y+1][x+2] = bcd
|
||||
z.ybr[y+1][x+3] = cde
|
||||
z.ybr[y+2][x+0] = qpa
|
||||
z.ybr[y+2][x+1] = ab
|
||||
z.ybr[y+2][x+2] = bc
|
||||
z.ybr[y+2][x+3] = cd
|
||||
z.ybr[y+3][x+0] = rqp
|
||||
z.ybr[y+3][x+1] = pab
|
||||
z.ybr[y+3][x+2] = abc
|
||||
z.ybr[y+3][x+3] = bcd
|
||||
}
|
||||
|
||||
func predFunc4LD(z *Decoder, y, x int) {
|
||||
a := int32(z.ybr[y-1][x+0])
|
||||
b := int32(z.ybr[y-1][x+1])
|
||||
c := int32(z.ybr[y-1][x+2])
|
||||
d := int32(z.ybr[y-1][x+3])
|
||||
e := int32(z.ybr[y-1][x+4])
|
||||
f := int32(z.ybr[y-1][x+5])
|
||||
g := int32(z.ybr[y-1][x+6])
|
||||
h := int32(z.ybr[y-1][x+7])
|
||||
abc := uint8((a + 2*b + c + 2) / 4)
|
||||
bcd := uint8((b + 2*c + d + 2) / 4)
|
||||
cde := uint8((c + 2*d + e + 2) / 4)
|
||||
def := uint8((d + 2*e + f + 2) / 4)
|
||||
efg := uint8((e + 2*f + g + 2) / 4)
|
||||
fgh := uint8((f + 2*g + h + 2) / 4)
|
||||
ghh := uint8((g + 2*h + h + 2) / 4)
|
||||
z.ybr[y+0][x+0] = abc
|
||||
z.ybr[y+0][x+1] = bcd
|
||||
z.ybr[y+0][x+2] = cde
|
||||
z.ybr[y+0][x+3] = def
|
||||
z.ybr[y+1][x+0] = bcd
|
||||
z.ybr[y+1][x+1] = cde
|
||||
z.ybr[y+1][x+2] = def
|
||||
z.ybr[y+1][x+3] = efg
|
||||
z.ybr[y+2][x+0] = cde
|
||||
z.ybr[y+2][x+1] = def
|
||||
z.ybr[y+2][x+2] = efg
|
||||
z.ybr[y+2][x+3] = fgh
|
||||
z.ybr[y+3][x+0] = def
|
||||
z.ybr[y+3][x+1] = efg
|
||||
z.ybr[y+3][x+2] = fgh
|
||||
z.ybr[y+3][x+3] = ghh
|
||||
}
|
||||
|
||||
func predFunc4VL(z *Decoder, y, x int) {
|
||||
a := int32(z.ybr[y-1][x+0])
|
||||
b := int32(z.ybr[y-1][x+1])
|
||||
c := int32(z.ybr[y-1][x+2])
|
||||
d := int32(z.ybr[y-1][x+3])
|
||||
e := int32(z.ybr[y-1][x+4])
|
||||
f := int32(z.ybr[y-1][x+5])
|
||||
g := int32(z.ybr[y-1][x+6])
|
||||
h := int32(z.ybr[y-1][x+7])
|
||||
ab := uint8((a + b + 1) / 2)
|
||||
bc := uint8((b + c + 1) / 2)
|
||||
cd := uint8((c + d + 1) / 2)
|
||||
de := uint8((d + e + 1) / 2)
|
||||
abc := uint8((a + 2*b + c + 2) / 4)
|
||||
bcd := uint8((b + 2*c + d + 2) / 4)
|
||||
cde := uint8((c + 2*d + e + 2) / 4)
|
||||
def := uint8((d + 2*e + f + 2) / 4)
|
||||
efg := uint8((e + 2*f + g + 2) / 4)
|
||||
fgh := uint8((f + 2*g + h + 2) / 4)
|
||||
z.ybr[y+0][x+0] = ab
|
||||
z.ybr[y+0][x+1] = bc
|
||||
z.ybr[y+0][x+2] = cd
|
||||
z.ybr[y+0][x+3] = de
|
||||
z.ybr[y+1][x+0] = abc
|
||||
z.ybr[y+1][x+1] = bcd
|
||||
z.ybr[y+1][x+2] = cde
|
||||
z.ybr[y+1][x+3] = def
|
||||
z.ybr[y+2][x+0] = bc
|
||||
z.ybr[y+2][x+1] = cd
|
||||
z.ybr[y+2][x+2] = de
|
||||
z.ybr[y+2][x+3] = efg
|
||||
z.ybr[y+3][x+0] = bcd
|
||||
z.ybr[y+3][x+1] = cde
|
||||
z.ybr[y+3][x+2] = def
|
||||
z.ybr[y+3][x+3] = fgh
|
||||
}
|
||||
|
||||
func predFunc4HD(z *Decoder, y, x int) {
|
||||
s := int32(z.ybr[y+3][x-1])
|
||||
r := int32(z.ybr[y+2][x-1])
|
||||
q := int32(z.ybr[y+1][x-1])
|
||||
p := int32(z.ybr[y+0][x-1])
|
||||
a := int32(z.ybr[y-1][x-1])
|
||||
b := int32(z.ybr[y-1][x+0])
|
||||
c := int32(z.ybr[y-1][x+1])
|
||||
d := int32(z.ybr[y-1][x+2])
|
||||
sr := uint8((s + r + 1) / 2)
|
||||
rq := uint8((r + q + 1) / 2)
|
||||
qp := uint8((q + p + 1) / 2)
|
||||
pa := uint8((p + a + 1) / 2)
|
||||
srq := uint8((s + 2*r + q + 2) / 4)
|
||||
rqp := uint8((r + 2*q + p + 2) / 4)
|
||||
qpa := uint8((q + 2*p + a + 2) / 4)
|
||||
pab := uint8((p + 2*a + b + 2) / 4)
|
||||
abc := uint8((a + 2*b + c + 2) / 4)
|
||||
bcd := uint8((b + 2*c + d + 2) / 4)
|
||||
z.ybr[y+0][x+0] = pa
|
||||
z.ybr[y+0][x+1] = pab
|
||||
z.ybr[y+0][x+2] = abc
|
||||
z.ybr[y+0][x+3] = bcd
|
||||
z.ybr[y+1][x+0] = qp
|
||||
z.ybr[y+1][x+1] = qpa
|
||||
z.ybr[y+1][x+2] = pa
|
||||
z.ybr[y+1][x+3] = pab
|
||||
z.ybr[y+2][x+0] = rq
|
||||
z.ybr[y+2][x+1] = rqp
|
||||
z.ybr[y+2][x+2] = qp
|
||||
z.ybr[y+2][x+3] = qpa
|
||||
z.ybr[y+3][x+0] = sr
|
||||
z.ybr[y+3][x+1] = srq
|
||||
z.ybr[y+3][x+2] = rq
|
||||
z.ybr[y+3][x+3] = rqp
|
||||
}
|
||||
|
||||
func predFunc4HU(z *Decoder, y, x int) {
|
||||
s := int32(z.ybr[y+3][x-1])
|
||||
r := int32(z.ybr[y+2][x-1])
|
||||
q := int32(z.ybr[y+1][x-1])
|
||||
p := int32(z.ybr[y+0][x-1])
|
||||
pq := uint8((p + q + 1) / 2)
|
||||
qr := uint8((q + r + 1) / 2)
|
||||
rs := uint8((r + s + 1) / 2)
|
||||
pqr := uint8((p + 2*q + r + 2) / 4)
|
||||
qrs := uint8((q + 2*r + s + 2) / 4)
|
||||
rss := uint8((r + 2*s + s + 2) / 4)
|
||||
sss := uint8(s)
|
||||
z.ybr[y+0][x+0] = pq
|
||||
z.ybr[y+0][x+1] = pqr
|
||||
z.ybr[y+0][x+2] = qr
|
||||
z.ybr[y+0][x+3] = qrs
|
||||
z.ybr[y+1][x+0] = qr
|
||||
z.ybr[y+1][x+1] = qrs
|
||||
z.ybr[y+1][x+2] = rs
|
||||
z.ybr[y+1][x+3] = rss
|
||||
z.ybr[y+2][x+0] = rs
|
||||
z.ybr[y+2][x+1] = rss
|
||||
z.ybr[y+2][x+2] = sss
|
||||
z.ybr[y+2][x+3] = sss
|
||||
z.ybr[y+3][x+0] = sss
|
||||
z.ybr[y+3][x+1] = sss
|
||||
z.ybr[y+3][x+2] = sss
|
||||
z.ybr[y+3][x+3] = sss
|
||||
}
|
||||
|
||||
func predFunc8DC(z *Decoder, y, x int) {
|
||||
sum := uint32(8)
|
||||
for i := 0; i < 8; i++ {
|
||||
sum += uint32(z.ybr[y-1][x+i])
|
||||
}
|
||||
for j := 0; j < 8; j++ {
|
||||
sum += uint32(z.ybr[y+j][x-1])
|
||||
}
|
||||
avg := uint8(sum / 16)
|
||||
for j := 0; j < 8; j++ {
|
||||
for i := 0; i < 8; i++ {
|
||||
z.ybr[y+j][x+i] = avg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func predFunc8TM(z *Decoder, y, x int) {
|
||||
delta0 := -int32(z.ybr[y-1][x-1])
|
||||
for j := 0; j < 8; j++ {
|
||||
delta1 := delta0 + int32(z.ybr[y+j][x-1])
|
||||
for i := 0; i < 8; i++ {
|
||||
delta2 := delta1 + int32(z.ybr[y-1][x+i])
|
||||
z.ybr[y+j][x+i] = uint8(clip(delta2, 0, 255))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func predFunc8VE(z *Decoder, y, x int) {
|
||||
for j := 0; j < 8; j++ {
|
||||
for i := 0; i < 8; i++ {
|
||||
z.ybr[y+j][x+i] = z.ybr[y-1][x+i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func predFunc8HE(z *Decoder, y, x int) {
|
||||
for j := 0; j < 8; j++ {
|
||||
for i := 0; i < 8; i++ {
|
||||
z.ybr[y+j][x+i] = z.ybr[y+j][x-1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func predFunc8DCTop(z *Decoder, y, x int) {
|
||||
sum := uint32(4)
|
||||
for j := 0; j < 8; j++ {
|
||||
sum += uint32(z.ybr[y+j][x-1])
|
||||
}
|
||||
avg := uint8(sum / 8)
|
||||
for j := 0; j < 8; j++ {
|
||||
for i := 0; i < 8; i++ {
|
||||
z.ybr[y+j][x+i] = avg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func predFunc8DCLeft(z *Decoder, y, x int) {
|
||||
sum := uint32(4)
|
||||
for i := 0; i < 8; i++ {
|
||||
sum += uint32(z.ybr[y-1][x+i])
|
||||
}
|
||||
avg := uint8(sum / 8)
|
||||
for j := 0; j < 8; j++ {
|
||||
for i := 0; i < 8; i++ {
|
||||
z.ybr[y+j][x+i] = avg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func predFunc8DCTopLeft(z *Decoder, y, x int) {
|
||||
for j := 0; j < 8; j++ {
|
||||
for i := 0; i < 8; i++ {
|
||||
z.ybr[y+j][x+i] = 0x80
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func predFunc16DC(z *Decoder, y, x int) {
|
||||
sum := uint32(16)
|
||||
for i := 0; i < 16; i++ {
|
||||
sum += uint32(z.ybr[y-1][x+i])
|
||||
}
|
||||
for j := 0; j < 16; j++ {
|
||||
sum += uint32(z.ybr[y+j][x-1])
|
||||
}
|
||||
avg := uint8(sum / 32)
|
||||
for j := 0; j < 16; j++ {
|
||||
for i := 0; i < 16; i++ {
|
||||
z.ybr[y+j][x+i] = avg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func predFunc16TM(z *Decoder, y, x int) {
|
||||
delta0 := -int32(z.ybr[y-1][x-1])
|
||||
for j := 0; j < 16; j++ {
|
||||
delta1 := delta0 + int32(z.ybr[y+j][x-1])
|
||||
for i := 0; i < 16; i++ {
|
||||
delta2 := delta1 + int32(z.ybr[y-1][x+i])
|
||||
z.ybr[y+j][x+i] = uint8(clip(delta2, 0, 255))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func predFunc16VE(z *Decoder, y, x int) {
|
||||
for j := 0; j < 16; j++ {
|
||||
for i := 0; i < 16; i++ {
|
||||
z.ybr[y+j][x+i] = z.ybr[y-1][x+i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func predFunc16HE(z *Decoder, y, x int) {
|
||||
for j := 0; j < 16; j++ {
|
||||
for i := 0; i < 16; i++ {
|
||||
z.ybr[y+j][x+i] = z.ybr[y+j][x-1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func predFunc16DCTop(z *Decoder, y, x int) {
|
||||
sum := uint32(8)
|
||||
for j := 0; j < 16; j++ {
|
||||
sum += uint32(z.ybr[y+j][x-1])
|
||||
}
|
||||
avg := uint8(sum / 16)
|
||||
for j := 0; j < 16; j++ {
|
||||
for i := 0; i < 16; i++ {
|
||||
z.ybr[y+j][x+i] = avg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func predFunc16DCLeft(z *Decoder, y, x int) {
|
||||
sum := uint32(8)
|
||||
for i := 0; i < 16; i++ {
|
||||
sum += uint32(z.ybr[y-1][x+i])
|
||||
}
|
||||
avg := uint8(sum / 16)
|
||||
for j := 0; j < 16; j++ {
|
||||
for i := 0; i < 16; i++ {
|
||||
z.ybr[y+j][x+i] = avg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func predFunc16DCTopLeft(z *Decoder, y, x int) {
|
||||
for j := 0; j < 16; j++ {
|
||||
for i := 0; i < 16; i++ {
|
||||
z.ybr[y+j][x+i] = 0x80
|
||||
}
|
||||
}
|
||||
}
|
||||
98
vendor/golang.org/x/image/vp8/quant.go
generated
vendored
Normal file
98
vendor/golang.org/x/image/vp8/quant.go
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright 2011 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 vp8
|
||||
|
||||
// This file implements parsing the quantization factors.
|
||||
|
||||
// quant are DC/AC quantization factors.
|
||||
type quant struct {
|
||||
y1 [2]uint16
|
||||
y2 [2]uint16
|
||||
uv [2]uint16
|
||||
}
|
||||
|
||||
// clip clips x to the range [min, max] inclusive.
|
||||
func clip(x, min, max int32) int32 {
|
||||
if x < min {
|
||||
return min
|
||||
}
|
||||
if x > max {
|
||||
return max
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
// parseQuant parses the quantization factors, as specified in section 9.6.
|
||||
func (d *Decoder) parseQuant() {
|
||||
baseQ0 := d.fp.readUint(uniformProb, 7)
|
||||
dqy1DC := d.fp.readOptionalInt(uniformProb, 4)
|
||||
const dqy1AC = 0
|
||||
dqy2DC := d.fp.readOptionalInt(uniformProb, 4)
|
||||
dqy2AC := d.fp.readOptionalInt(uniformProb, 4)
|
||||
dquvDC := d.fp.readOptionalInt(uniformProb, 4)
|
||||
dquvAC := d.fp.readOptionalInt(uniformProb, 4)
|
||||
for i := 0; i < nSegment; i++ {
|
||||
q := int32(baseQ0)
|
||||
if d.segmentHeader.useSegment {
|
||||
if d.segmentHeader.relativeDelta {
|
||||
q += int32(d.segmentHeader.quantizer[i])
|
||||
} else {
|
||||
q = int32(d.segmentHeader.quantizer[i])
|
||||
}
|
||||
}
|
||||
d.quant[i].y1[0] = dequantTableDC[clip(q+dqy1DC, 0, 127)]
|
||||
d.quant[i].y1[1] = dequantTableAC[clip(q+dqy1AC, 0, 127)]
|
||||
d.quant[i].y2[0] = dequantTableDC[clip(q+dqy2DC, 0, 127)] * 2
|
||||
d.quant[i].y2[1] = dequantTableAC[clip(q+dqy2AC, 0, 127)] * 155 / 100
|
||||
if d.quant[i].y2[1] < 8 {
|
||||
d.quant[i].y2[1] = 8
|
||||
}
|
||||
// The 117 is not a typo. The dequant_init function in the spec's Reference
|
||||
// Decoder Source Code (http://tools.ietf.org/html/rfc6386#section-9.6 Page 145)
|
||||
// says to clamp the LHS value at 132, which is equal to dequantTableDC[117].
|
||||
d.quant[i].uv[0] = dequantTableDC[clip(q+dquvDC, 0, 117)]
|
||||
d.quant[i].uv[1] = dequantTableAC[clip(q+dquvAC, 0, 127)]
|
||||
}
|
||||
}
|
||||
|
||||
// The dequantization tables are specified in section 14.1.
|
||||
var (
|
||||
dequantTableDC = [128]uint16{
|
||||
4, 5, 6, 7, 8, 9, 10, 10,
|
||||
11, 12, 13, 14, 15, 16, 17, 17,
|
||||
18, 19, 20, 20, 21, 21, 22, 22,
|
||||
23, 23, 24, 25, 25, 26, 27, 28,
|
||||
29, 30, 31, 32, 33, 34, 35, 36,
|
||||
37, 37, 38, 39, 40, 41, 42, 43,
|
||||
44, 45, 46, 46, 47, 48, 49, 50,
|
||||
51, 52, 53, 54, 55, 56, 57, 58,
|
||||
59, 60, 61, 62, 63, 64, 65, 66,
|
||||
67, 68, 69, 70, 71, 72, 73, 74,
|
||||
75, 76, 76, 77, 78, 79, 80, 81,
|
||||
82, 83, 84, 85, 86, 87, 88, 89,
|
||||
91, 93, 95, 96, 98, 100, 101, 102,
|
||||
104, 106, 108, 110, 112, 114, 116, 118,
|
||||
122, 124, 126, 128, 130, 132, 134, 136,
|
||||
138, 140, 143, 145, 148, 151, 154, 157,
|
||||
}
|
||||
dequantTableAC = [128]uint16{
|
||||
4, 5, 6, 7, 8, 9, 10, 11,
|
||||
12, 13, 14, 15, 16, 17, 18, 19,
|
||||
20, 21, 22, 23, 24, 25, 26, 27,
|
||||
28, 29, 30, 31, 32, 33, 34, 35,
|
||||
36, 37, 38, 39, 40, 41, 42, 43,
|
||||
44, 45, 46, 47, 48, 49, 50, 51,
|
||||
52, 53, 54, 55, 56, 57, 58, 60,
|
||||
62, 64, 66, 68, 70, 72, 74, 76,
|
||||
78, 80, 82, 84, 86, 88, 90, 92,
|
||||
94, 96, 98, 100, 102, 104, 106, 108,
|
||||
110, 112, 114, 116, 119, 122, 125, 128,
|
||||
131, 134, 137, 140, 143, 146, 149, 152,
|
||||
155, 158, 161, 164, 167, 170, 173, 177,
|
||||
181, 185, 189, 193, 197, 201, 205, 209,
|
||||
213, 217, 221, 225, 229, 234, 239, 245,
|
||||
249, 254, 259, 264, 269, 274, 279, 284,
|
||||
}
|
||||
)
|
||||
442
vendor/golang.org/x/image/vp8/reconstruct.go
generated
vendored
Normal file
442
vendor/golang.org/x/image/vp8/reconstruct.go
generated
vendored
Normal file
@@ -0,0 +1,442 @@
|
||||
// Copyright 2011 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 vp8
|
||||
|
||||
// This file implements decoding DCT/WHT residual coefficients and
|
||||
// reconstructing YCbCr data equal to predicted values plus residuals.
|
||||
//
|
||||
// There are 1*16*16 + 2*8*8 + 1*4*4 coefficients per macroblock:
|
||||
// - 1*16*16 luma DCT coefficients,
|
||||
// - 2*8*8 chroma DCT coefficients, and
|
||||
// - 1*4*4 luma WHT coefficients.
|
||||
// Coefficients are read in lots of 16, and the later coefficients in each lot
|
||||
// are often zero.
|
||||
//
|
||||
// The YCbCr data consists of 1*16*16 luma values and 2*8*8 chroma values,
|
||||
// plus previously decoded values along the top and left borders. The combined
|
||||
// values are laid out as a [1+16+1+8][32]uint8 so that vertically adjacent
|
||||
// samples are 32 bytes apart. In detail, the layout is:
|
||||
//
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// . . . . . . . a b b b b b b b b b b b b b b b b c c c c . . . . 0
|
||||
// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 1
|
||||
// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 2
|
||||
// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 3
|
||||
// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y c c c c . . . . 4
|
||||
// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 5
|
||||
// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 6
|
||||
// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 7
|
||||
// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y c c c c . . . . 8
|
||||
// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 9
|
||||
// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 10
|
||||
// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 11
|
||||
// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y c c c c . . . . 12
|
||||
// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 13
|
||||
// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 14
|
||||
// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 15
|
||||
// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 16
|
||||
// . . . . . . . e f f f f f f f f . . . . . . . g h h h h h h h h 17
|
||||
// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 18
|
||||
// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 19
|
||||
// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 20
|
||||
// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 21
|
||||
// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 22
|
||||
// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 23
|
||||
// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 24
|
||||
// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 25
|
||||
//
|
||||
// Y, B and R are the reconstructed luma (Y) and chroma (B, R) values.
|
||||
// The Y values are predicted (either as one 16x16 region or 16 4x4 regions)
|
||||
// based on the row above's Y values (some combination of {abc} or {dYC}) and
|
||||
// the column left's Y values (either {ad} or {bY}). Similarly, B and R values
|
||||
// are predicted on the row above and column left of their respective 8x8
|
||||
// region: {efi} for B, {ghj} for R.
|
||||
//
|
||||
// For uppermost macroblocks (i.e. those with mby == 0), the {abcefgh} values
|
||||
// are initialized to 0x81. Otherwise, they are copied from the bottom row of
|
||||
// the macroblock above. The {c} values are then duplicated from row 0 to rows
|
||||
// 4, 8 and 12 of the ybr workspace.
|
||||
// Similarly, for leftmost macroblocks (i.e. those with mbx == 0), the {adeigj}
|
||||
// values are initialized to 0x7f. Otherwise, they are copied from the right
|
||||
// column of the macroblock to the left.
|
||||
// For the top-left macroblock (with mby == 0 && mbx == 0), {aeg} is 0x81.
|
||||
//
|
||||
// When moving from one macroblock to the next horizontally, the {adeigj}
|
||||
// values can simply be copied from the workspace to itself, shifted by 8 or
|
||||
// 16 columns. When moving from one macroblock to the next vertically,
|
||||
// filtering can occur and hence the row values have to be copied from the
|
||||
// post-filtered image instead of the pre-filtered workspace.
|
||||
|
||||
const (
|
||||
bCoeffBase = 1*16*16 + 0*8*8
|
||||
rCoeffBase = 1*16*16 + 1*8*8
|
||||
whtCoeffBase = 1*16*16 + 2*8*8
|
||||
)
|
||||
|
||||
const (
|
||||
ybrYX = 8
|
||||
ybrYY = 1
|
||||
ybrBX = 8
|
||||
ybrBY = 18
|
||||
ybrRX = 24
|
||||
ybrRY = 18
|
||||
)
|
||||
|
||||
// prepareYBR prepares the {abcdefghij} elements of ybr.
|
||||
func (d *Decoder) prepareYBR(mbx, mby int) {
|
||||
if mbx == 0 {
|
||||
for y := 0; y < 17; y++ {
|
||||
d.ybr[y][7] = 0x81
|
||||
}
|
||||
for y := 17; y < 26; y++ {
|
||||
d.ybr[y][7] = 0x81
|
||||
d.ybr[y][23] = 0x81
|
||||
}
|
||||
} else {
|
||||
for y := 0; y < 17; y++ {
|
||||
d.ybr[y][7] = d.ybr[y][7+16]
|
||||
}
|
||||
for y := 17; y < 26; y++ {
|
||||
d.ybr[y][7] = d.ybr[y][15]
|
||||
d.ybr[y][23] = d.ybr[y][31]
|
||||
}
|
||||
}
|
||||
if mby == 0 {
|
||||
for x := 7; x < 28; x++ {
|
||||
d.ybr[0][x] = 0x7f
|
||||
}
|
||||
for x := 7; x < 16; x++ {
|
||||
d.ybr[17][x] = 0x7f
|
||||
}
|
||||
for x := 23; x < 32; x++ {
|
||||
d.ybr[17][x] = 0x7f
|
||||
}
|
||||
} else {
|
||||
for i := 0; i < 16; i++ {
|
||||
d.ybr[0][8+i] = d.img.Y[(16*mby-1)*d.img.YStride+16*mbx+i]
|
||||
}
|
||||
for i := 0; i < 8; i++ {
|
||||
d.ybr[17][8+i] = d.img.Cb[(8*mby-1)*d.img.CStride+8*mbx+i]
|
||||
}
|
||||
for i := 0; i < 8; i++ {
|
||||
d.ybr[17][24+i] = d.img.Cr[(8*mby-1)*d.img.CStride+8*mbx+i]
|
||||
}
|
||||
if mbx == d.mbw-1 {
|
||||
for i := 16; i < 20; i++ {
|
||||
d.ybr[0][8+i] = d.img.Y[(16*mby-1)*d.img.YStride+16*mbx+15]
|
||||
}
|
||||
} else {
|
||||
for i := 16; i < 20; i++ {
|
||||
d.ybr[0][8+i] = d.img.Y[(16*mby-1)*d.img.YStride+16*mbx+i]
|
||||
}
|
||||
}
|
||||
}
|
||||
for y := 4; y < 16; y += 4 {
|
||||
d.ybr[y][24] = d.ybr[0][24]
|
||||
d.ybr[y][25] = d.ybr[0][25]
|
||||
d.ybr[y][26] = d.ybr[0][26]
|
||||
d.ybr[y][27] = d.ybr[0][27]
|
||||
}
|
||||
}
|
||||
|
||||
// btou converts a bool to a 0/1 value.
|
||||
func btou(b bool) uint8 {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// pack packs four 0/1 values into four bits of a uint32.
|
||||
func pack(x [4]uint8, shift int) uint32 {
|
||||
u := uint32(x[0])<<0 | uint32(x[1])<<1 | uint32(x[2])<<2 | uint32(x[3])<<3
|
||||
return u << uint(shift)
|
||||
}
|
||||
|
||||
// unpack unpacks four 0/1 values from a four-bit value.
|
||||
var unpack = [16][4]uint8{
|
||||
{0, 0, 0, 0},
|
||||
{1, 0, 0, 0},
|
||||
{0, 1, 0, 0},
|
||||
{1, 1, 0, 0},
|
||||
{0, 0, 1, 0},
|
||||
{1, 0, 1, 0},
|
||||
{0, 1, 1, 0},
|
||||
{1, 1, 1, 0},
|
||||
{0, 0, 0, 1},
|
||||
{1, 0, 0, 1},
|
||||
{0, 1, 0, 1},
|
||||
{1, 1, 0, 1},
|
||||
{0, 0, 1, 1},
|
||||
{1, 0, 1, 1},
|
||||
{0, 1, 1, 1},
|
||||
{1, 1, 1, 1},
|
||||
}
|
||||
|
||||
var (
|
||||
// The mapping from 4x4 region position to band is specified in section 13.3.
|
||||
bands = [17]uint8{0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 0}
|
||||
// Category probabilties are specified in section 13.2.
|
||||
// Decoding categories 1 and 2 are done inline.
|
||||
cat3456 = [4][12]uint8{
|
||||
{173, 148, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{176, 155, 140, 135, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{180, 157, 141, 134, 130, 0, 0, 0, 0, 0, 0, 0},
|
||||
{254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0},
|
||||
}
|
||||
// The zigzag order is:
|
||||
// 0 1 5 6
|
||||
// 2 4 7 12
|
||||
// 3 8 11 13
|
||||
// 9 10 14 15
|
||||
zigzag = [16]uint8{0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15}
|
||||
)
|
||||
|
||||
// parseResiduals4 parses a 4x4 region of residual coefficients, as specified
|
||||
// in section 13.3, and returns a 0/1 value indicating whether there was at
|
||||
// least one non-zero coefficient.
|
||||
// r is the partition to read bits from.
|
||||
// plane and context describe which token probability table to use. context is
|
||||
// either 0, 1 or 2, and equals how many of the macroblock left and macroblock
|
||||
// above have non-zero coefficients.
|
||||
// quant are the DC/AC quantization factors.
|
||||
// skipFirstCoeff is whether the DC coefficient has already been parsed.
|
||||
// coeffBase is the base index of d.coeff to write to.
|
||||
func (d *Decoder) parseResiduals4(r *partition, plane int, context uint8, quant [2]uint16, skipFirstCoeff bool, coeffBase int) uint8 {
|
||||
prob, n := &d.tokenProb[plane], 0
|
||||
if skipFirstCoeff {
|
||||
n = 1
|
||||
}
|
||||
p := prob[bands[n]][context]
|
||||
if !r.readBit(p[0]) {
|
||||
return 0
|
||||
}
|
||||
for n != 16 {
|
||||
n++
|
||||
if !r.readBit(p[1]) {
|
||||
p = prob[bands[n]][0]
|
||||
continue
|
||||
}
|
||||
var v uint32
|
||||
if !r.readBit(p[2]) {
|
||||
v = 1
|
||||
p = prob[bands[n]][1]
|
||||
} else {
|
||||
if !r.readBit(p[3]) {
|
||||
if !r.readBit(p[4]) {
|
||||
v = 2
|
||||
} else {
|
||||
v = 3 + r.readUint(p[5], 1)
|
||||
}
|
||||
} else if !r.readBit(p[6]) {
|
||||
if !r.readBit(p[7]) {
|
||||
// Category 1.
|
||||
v = 5 + r.readUint(159, 1)
|
||||
} else {
|
||||
// Category 2.
|
||||
v = 7 + 2*r.readUint(165, 1) + r.readUint(145, 1)
|
||||
}
|
||||
} else {
|
||||
// Categories 3, 4, 5 or 6.
|
||||
b1 := r.readUint(p[8], 1)
|
||||
b0 := r.readUint(p[9+b1], 1)
|
||||
cat := 2*b1 + b0
|
||||
tab := &cat3456[cat]
|
||||
v = 0
|
||||
for i := 0; tab[i] != 0; i++ {
|
||||
v *= 2
|
||||
v += r.readUint(tab[i], 1)
|
||||
}
|
||||
v += 3 + (8 << cat)
|
||||
}
|
||||
p = prob[bands[n]][2]
|
||||
}
|
||||
z := zigzag[n-1]
|
||||
c := int32(v) * int32(quant[btou(z > 0)])
|
||||
if r.readBit(uniformProb) {
|
||||
c = -c
|
||||
}
|
||||
d.coeff[coeffBase+int(z)] = int16(c)
|
||||
if n == 16 || !r.readBit(p[0]) {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// parseResiduals parses the residuals and returns whether inner loop filtering
|
||||
// should be skipped for this macroblock.
|
||||
func (d *Decoder) parseResiduals(mbx, mby int) (skip bool) {
|
||||
partition := &d.op[mby&(d.nOP-1)]
|
||||
plane := planeY1SansY2
|
||||
quant := &d.quant[d.segment]
|
||||
|
||||
// Parse the DC coefficient of each 4x4 luma region.
|
||||
if d.usePredY16 {
|
||||
nz := d.parseResiduals4(partition, planeY2, d.leftMB.nzY16+d.upMB[mbx].nzY16, quant.y2, false, whtCoeffBase)
|
||||
d.leftMB.nzY16 = nz
|
||||
d.upMB[mbx].nzY16 = nz
|
||||
d.inverseWHT16()
|
||||
plane = planeY1WithY2
|
||||
}
|
||||
|
||||
var (
|
||||
nzDC, nzAC [4]uint8
|
||||
nzDCMask, nzACMask uint32
|
||||
coeffBase int
|
||||
)
|
||||
|
||||
// Parse the luma coefficients.
|
||||
lnz := unpack[d.leftMB.nzMask&0x0f]
|
||||
unz := unpack[d.upMB[mbx].nzMask&0x0f]
|
||||
for y := 0; y < 4; y++ {
|
||||
nz := lnz[y]
|
||||
for x := 0; x < 4; x++ {
|
||||
nz = d.parseResiduals4(partition, plane, nz+unz[x], quant.y1, d.usePredY16, coeffBase)
|
||||
unz[x] = nz
|
||||
nzAC[x] = nz
|
||||
nzDC[x] = btou(d.coeff[coeffBase] != 0)
|
||||
coeffBase += 16
|
||||
}
|
||||
lnz[y] = nz
|
||||
nzDCMask |= pack(nzDC, y*4)
|
||||
nzACMask |= pack(nzAC, y*4)
|
||||
}
|
||||
lnzMask := pack(lnz, 0)
|
||||
unzMask := pack(unz, 0)
|
||||
|
||||
// Parse the chroma coefficients.
|
||||
lnz = unpack[d.leftMB.nzMask>>4]
|
||||
unz = unpack[d.upMB[mbx].nzMask>>4]
|
||||
for c := 0; c < 4; c += 2 {
|
||||
for y := 0; y < 2; y++ {
|
||||
nz := lnz[y+c]
|
||||
for x := 0; x < 2; x++ {
|
||||
nz = d.parseResiduals4(partition, planeUV, nz+unz[x+c], quant.uv, false, coeffBase)
|
||||
unz[x+c] = nz
|
||||
nzAC[y*2+x] = nz
|
||||
nzDC[y*2+x] = btou(d.coeff[coeffBase] != 0)
|
||||
coeffBase += 16
|
||||
}
|
||||
lnz[y+c] = nz
|
||||
}
|
||||
nzDCMask |= pack(nzDC, 16+c*2)
|
||||
nzACMask |= pack(nzAC, 16+c*2)
|
||||
}
|
||||
lnzMask |= pack(lnz, 4)
|
||||
unzMask |= pack(unz, 4)
|
||||
|
||||
// Save decoder state.
|
||||
d.leftMB.nzMask = uint8(lnzMask)
|
||||
d.upMB[mbx].nzMask = uint8(unzMask)
|
||||
d.nzDCMask = nzDCMask
|
||||
d.nzACMask = nzACMask
|
||||
|
||||
// Section 15.1 of the spec says that "Steps 2 and 4 [of the loop filter]
|
||||
// are skipped... [if] there is no DCT coefficient coded for the whole
|
||||
// macroblock."
|
||||
return nzDCMask == 0 && nzACMask == 0
|
||||
}
|
||||
|
||||
// reconstructMacroblock applies the predictor functions and adds the inverse-
|
||||
// DCT transformed residuals to recover the YCbCr data.
|
||||
func (d *Decoder) reconstructMacroblock(mbx, mby int) {
|
||||
if d.usePredY16 {
|
||||
p := checkTopLeftPred(mbx, mby, d.predY16)
|
||||
predFunc16[p](d, 1, 8)
|
||||
for j := 0; j < 4; j++ {
|
||||
for i := 0; i < 4; i++ {
|
||||
n := 4*j + i
|
||||
y := 4*j + 1
|
||||
x := 4*i + 8
|
||||
mask := uint32(1) << uint(n)
|
||||
if d.nzACMask&mask != 0 {
|
||||
d.inverseDCT4(y, x, 16*n)
|
||||
} else if d.nzDCMask&mask != 0 {
|
||||
d.inverseDCT4DCOnly(y, x, 16*n)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for j := 0; j < 4; j++ {
|
||||
for i := 0; i < 4; i++ {
|
||||
n := 4*j + i
|
||||
y := 4*j + 1
|
||||
x := 4*i + 8
|
||||
predFunc4[d.predY4[j][i]](d, y, x)
|
||||
mask := uint32(1) << uint(n)
|
||||
if d.nzACMask&mask != 0 {
|
||||
d.inverseDCT4(y, x, 16*n)
|
||||
} else if d.nzDCMask&mask != 0 {
|
||||
d.inverseDCT4DCOnly(y, x, 16*n)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
p := checkTopLeftPred(mbx, mby, d.predC8)
|
||||
predFunc8[p](d, ybrBY, ybrBX)
|
||||
if d.nzACMask&0x0f0000 != 0 {
|
||||
d.inverseDCT8(ybrBY, ybrBX, bCoeffBase)
|
||||
} else if d.nzDCMask&0x0f0000 != 0 {
|
||||
d.inverseDCT8DCOnly(ybrBY, ybrBX, bCoeffBase)
|
||||
}
|
||||
predFunc8[p](d, ybrRY, ybrRX)
|
||||
if d.nzACMask&0xf00000 != 0 {
|
||||
d.inverseDCT8(ybrRY, ybrRX, rCoeffBase)
|
||||
} else if d.nzDCMask&0xf00000 != 0 {
|
||||
d.inverseDCT8DCOnly(ybrRY, ybrRX, rCoeffBase)
|
||||
}
|
||||
}
|
||||
|
||||
// reconstruct reconstructs one macroblock and returns whether inner loop
|
||||
// filtering should be skipped for it.
|
||||
func (d *Decoder) reconstruct(mbx, mby int) (skip bool) {
|
||||
if d.segmentHeader.updateMap {
|
||||
if !d.fp.readBit(d.segmentHeader.prob[0]) {
|
||||
d.segment = int(d.fp.readUint(d.segmentHeader.prob[1], 1))
|
||||
} else {
|
||||
d.segment = int(d.fp.readUint(d.segmentHeader.prob[2], 1)) + 2
|
||||
}
|
||||
}
|
||||
if d.useSkipProb {
|
||||
skip = d.fp.readBit(d.skipProb)
|
||||
}
|
||||
// Prepare the workspace.
|
||||
for i := range d.coeff {
|
||||
d.coeff[i] = 0
|
||||
}
|
||||
d.prepareYBR(mbx, mby)
|
||||
// Parse the predictor modes.
|
||||
d.usePredY16 = d.fp.readBit(145)
|
||||
if d.usePredY16 {
|
||||
d.parsePredModeY16(mbx)
|
||||
} else {
|
||||
d.parsePredModeY4(mbx)
|
||||
}
|
||||
d.parsePredModeC8()
|
||||
// Parse the residuals.
|
||||
if !skip {
|
||||
skip = d.parseResiduals(mbx, mby)
|
||||
} else {
|
||||
if d.usePredY16 {
|
||||
d.leftMB.nzY16 = 0
|
||||
d.upMB[mbx].nzY16 = 0
|
||||
}
|
||||
d.leftMB.nzMask = 0
|
||||
d.upMB[mbx].nzMask = 0
|
||||
d.nzDCMask = 0
|
||||
d.nzACMask = 0
|
||||
}
|
||||
// Reconstruct the YCbCr data and copy it to the image.
|
||||
d.reconstructMacroblock(mbx, mby)
|
||||
for i, y := (mby*d.img.YStride+mbx)*16, 0; y < 16; i, y = i+d.img.YStride, y+1 {
|
||||
copy(d.img.Y[i:i+16], d.ybr[ybrYY+y][ybrYX:ybrYX+16])
|
||||
}
|
||||
for i, y := (mby*d.img.CStride+mbx)*8, 0; y < 8; i, y = i+d.img.CStride, y+1 {
|
||||
copy(d.img.Cb[i:i+8], d.ybr[ybrBY+y][ybrBX:ybrBX+8])
|
||||
copy(d.img.Cr[i:i+8], d.ybr[ybrRY+y][ybrRX:ybrRX+8])
|
||||
}
|
||||
return skip
|
||||
}
|
||||
381
vendor/golang.org/x/image/vp8/token.go
generated
vendored
Normal file
381
vendor/golang.org/x/image/vp8/token.go
generated
vendored
Normal file
@@ -0,0 +1,381 @@
|
||||
// Copyright 2011 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 vp8
|
||||
|
||||
// This file contains token probabilities for decoding DCT/WHT coefficients, as
|
||||
// specified in chapter 13.
|
||||
|
||||
func (d *Decoder) parseTokenProb() {
|
||||
for i := range d.tokenProb {
|
||||
for j := range d.tokenProb[i] {
|
||||
for k := range d.tokenProb[i][j] {
|
||||
for l := range d.tokenProb[i][j][k] {
|
||||
if d.fp.readBit(tokenProbUpdateProb[i][j][k][l]) {
|
||||
d.tokenProb[i][j][k][l] = uint8(d.fp.readUint(uniformProb, 8))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The plane enumeration is specified in section 13.3.
|
||||
const (
|
||||
planeY1WithY2 = iota
|
||||
planeY2
|
||||
planeUV
|
||||
planeY1SansY2
|
||||
nPlane
|
||||
)
|
||||
|
||||
const (
|
||||
nBand = 8
|
||||
nContext = 3
|
||||
nProb = 11
|
||||
)
|
||||
|
||||
// Token probability update probabilities are specified in section 13.4.
|
||||
var tokenProbUpdateProb = [nPlane][nBand][nContext][nProb]uint8{
|
||||
{
|
||||
{
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255},
|
||||
{250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255},
|
||||
{254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
{217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255},
|
||||
{234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
{186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255},
|
||||
{251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
{248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255},
|
||||
{248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
{
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Default token probabilities are specified in section 13.5.
|
||||
var defaultTokenProb = [nPlane][nBand][nContext][nProb]uint8{
|
||||
{
|
||||
{
|
||||
{128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||
{128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||
{128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128},
|
||||
{189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128},
|
||||
{106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128},
|
||||
{181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128},
|
||||
{78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128},
|
||||
{184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128},
|
||||
{77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128},
|
||||
{170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128},
|
||||
{37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128},
|
||||
{207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128},
|
||||
{102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128},
|
||||
{177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128},
|
||||
{80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||
{246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||
{255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
{198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62},
|
||||
{131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1},
|
||||
{68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128},
|
||||
},
|
||||
{
|
||||
{1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128},
|
||||
{184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128},
|
||||
{81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128},
|
||||
},
|
||||
{
|
||||
{1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128},
|
||||
{99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128},
|
||||
{23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128},
|
||||
},
|
||||
{
|
||||
{1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128},
|
||||
{109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128},
|
||||
{44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128},
|
||||
{94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128},
|
||||
{22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128},
|
||||
{124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128},
|
||||
{35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128},
|
||||
{121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128},
|
||||
{45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128},
|
||||
{203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128},
|
||||
{137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128},
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
{253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128},
|
||||
{175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128},
|
||||
{73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128},
|
||||
},
|
||||
{
|
||||
{1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128},
|
||||
{239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128},
|
||||
{155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128},
|
||||
{201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128},
|
||||
{69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128},
|
||||
{223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128},
|
||||
{141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128},
|
||||
{190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128},
|
||||
{149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||
{247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||
{240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128},
|
||||
{213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128},
|
||||
{55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||
{128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||
{128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
{202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255},
|
||||
{126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128},
|
||||
{61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128},
|
||||
},
|
||||
{
|
||||
{1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128},
|
||||
{166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128},
|
||||
{39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128},
|
||||
},
|
||||
{
|
||||
{1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128},
|
||||
{124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128},
|
||||
{24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128},
|
||||
},
|
||||
{
|
||||
{1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128},
|
||||
{149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128},
|
||||
{28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128},
|
||||
},
|
||||
{
|
||||
{1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128},
|
||||
{123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128},
|
||||
{20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128},
|
||||
{168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128},
|
||||
{47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128},
|
||||
{141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128},
|
||||
{42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128},
|
||||
},
|
||||
{
|
||||
{1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||
{244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||
{238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
|
||||
},
|
||||
},
|
||||
}
|
||||
603
vendor/golang.org/x/image/vp8l/decode.go
generated
vendored
Normal file
603
vendor/golang.org/x/image/vp8l/decode.go
generated
vendored
Normal file
@@ -0,0 +1,603 @@
|
||||
// Copyright 2014 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 vp8l implements a decoder for the VP8L lossless image format.
|
||||
//
|
||||
// The VP8L specification is at:
|
||||
// https://developers.google.com/speed/webp/docs/riff_container
|
||||
package vp8l // import "golang.org/x/image/vp8l"
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"image"
|
||||
"image/color"
|
||||
"io"
|
||||
)
|
||||
|
||||
var (
|
||||
errInvalidCodeLengths = errors.New("vp8l: invalid code lengths")
|
||||
errInvalidHuffmanTree = errors.New("vp8l: invalid Huffman tree")
|
||||
)
|
||||
|
||||
// colorCacheMultiplier is the multiplier used for the color cache hash
|
||||
// function, specified in section 4.2.3.
|
||||
const colorCacheMultiplier = 0x1e35a7bd
|
||||
|
||||
// distanceMapTable is the look-up table for distanceMap.
|
||||
var distanceMapTable = [120]uint8{
|
||||
0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
|
||||
0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
|
||||
0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
|
||||
0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
|
||||
0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
|
||||
0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
|
||||
0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
|
||||
0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
|
||||
0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
|
||||
0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
|
||||
0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,
|
||||
0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70,
|
||||
}
|
||||
|
||||
// distanceMap maps a LZ77 backwards reference distance to a two-dimensional
|
||||
// pixel offset, specified in section 4.2.2.
|
||||
func distanceMap(w int32, code uint32) int32 {
|
||||
if int32(code) > int32(len(distanceMapTable)) {
|
||||
return int32(code) - int32(len(distanceMapTable))
|
||||
}
|
||||
distCode := int32(distanceMapTable[code-1])
|
||||
yOffset := distCode >> 4
|
||||
xOffset := 8 - distCode&0xf
|
||||
if d := yOffset*w + xOffset; d >= 1 {
|
||||
return d
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// decoder holds the bit-stream for a VP8L image.
|
||||
type decoder struct {
|
||||
r io.ByteReader
|
||||
bits uint32
|
||||
nBits uint32
|
||||
}
|
||||
|
||||
// read reads the next n bits from the decoder's bit-stream.
|
||||
func (d *decoder) read(n uint32) (uint32, error) {
|
||||
for d.nBits < n {
|
||||
c, err := d.r.ReadByte()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
d.bits |= uint32(c) << d.nBits
|
||||
d.nBits += 8
|
||||
}
|
||||
u := d.bits & (1<<n - 1)
|
||||
d.bits >>= n
|
||||
d.nBits -= n
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// decodeTransform decodes the next transform and the width of the image after
|
||||
// transformation (or equivalently, before inverse transformation), specified
|
||||
// in section 3.
|
||||
func (d *decoder) decodeTransform(w int32, h int32) (t transform, newWidth int32, err error) {
|
||||
t.oldWidth = w
|
||||
t.transformType, err = d.read(2)
|
||||
if err != nil {
|
||||
return transform{}, 0, err
|
||||
}
|
||||
switch t.transformType {
|
||||
case transformTypePredictor, transformTypeCrossColor:
|
||||
t.bits, err = d.read(3)
|
||||
if err != nil {
|
||||
return transform{}, 0, err
|
||||
}
|
||||
t.bits += 2
|
||||
t.pix, err = d.decodePix(nTiles(w, t.bits), nTiles(h, t.bits), 0, false)
|
||||
if err != nil {
|
||||
return transform{}, 0, err
|
||||
}
|
||||
case transformTypeSubtractGreen:
|
||||
// No-op.
|
||||
case transformTypeColorIndexing:
|
||||
nColors, err := d.read(8)
|
||||
if err != nil {
|
||||
return transform{}, 0, err
|
||||
}
|
||||
nColors++
|
||||
t.bits = 0
|
||||
switch {
|
||||
case nColors <= 2:
|
||||
t.bits = 3
|
||||
case nColors <= 4:
|
||||
t.bits = 2
|
||||
case nColors <= 16:
|
||||
t.bits = 1
|
||||
}
|
||||
w = nTiles(w, t.bits)
|
||||
pix, err := d.decodePix(int32(nColors), 1, 4*256, false)
|
||||
if err != nil {
|
||||
return transform{}, 0, err
|
||||
}
|
||||
for p := 4; p < len(pix); p += 4 {
|
||||
pix[p+0] += pix[p-4]
|
||||
pix[p+1] += pix[p-3]
|
||||
pix[p+2] += pix[p-2]
|
||||
pix[p+3] += pix[p-1]
|
||||
}
|
||||
// The spec says that "if the index is equal or larger than color_table_size,
|
||||
// the argb color value should be set to 0x00000000 (transparent black)."
|
||||
// We re-slice up to 256 4-byte pixels.
|
||||
t.pix = pix[:4*256]
|
||||
}
|
||||
return t, w, nil
|
||||
}
|
||||
|
||||
// repeatsCodeLength is the minimum code length for repeated codes.
|
||||
const repeatsCodeLength = 16
|
||||
|
||||
// These magic numbers are specified at the end of section 5.2.2.
|
||||
// The 3-length arrays apply to code lengths >= repeatsCodeLength.
|
||||
var (
|
||||
codeLengthCodeOrder = [19]uint8{
|
||||
17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
}
|
||||
repeatBits = [3]uint8{2, 3, 7}
|
||||
repeatOffsets = [3]uint8{3, 3, 11}
|
||||
)
|
||||
|
||||
// decodeCodeLengths decodes a Huffman tree's code lengths which are themselves
|
||||
// encoded via a Huffman tree, specified in section 5.2.2.
|
||||
func (d *decoder) decodeCodeLengths(dst []uint32, codeLengthCodeLengths []uint32) error {
|
||||
h := hTree{}
|
||||
if err := h.build(codeLengthCodeLengths); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
maxSymbol := len(dst)
|
||||
useLength, err := d.read(1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if useLength != 0 {
|
||||
n, err := d.read(3)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n = 2 + 2*n
|
||||
ms, err := d.read(n)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
maxSymbol = int(ms) + 2
|
||||
if maxSymbol > len(dst) {
|
||||
return errInvalidCodeLengths
|
||||
}
|
||||
}
|
||||
|
||||
// The spec says that "if code 16 [meaning repeat] is used before
|
||||
// a non-zero value has been emitted, a value of 8 is repeated."
|
||||
prevCodeLength := uint32(8)
|
||||
|
||||
for symbol := 0; symbol < len(dst); {
|
||||
if maxSymbol == 0 {
|
||||
break
|
||||
}
|
||||
maxSymbol--
|
||||
codeLength, err := h.next(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if codeLength < repeatsCodeLength {
|
||||
dst[symbol] = codeLength
|
||||
symbol++
|
||||
if codeLength != 0 {
|
||||
prevCodeLength = codeLength
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
repeat, err := d.read(uint32(repeatBits[codeLength-repeatsCodeLength]))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repeat += uint32(repeatOffsets[codeLength-repeatsCodeLength])
|
||||
if symbol+int(repeat) > len(dst) {
|
||||
return errInvalidCodeLengths
|
||||
}
|
||||
// A code length of 16 repeats the previous non-zero code.
|
||||
// A code length of 17 or 18 repeats zeroes.
|
||||
cl := uint32(0)
|
||||
if codeLength == 16 {
|
||||
cl = prevCodeLength
|
||||
}
|
||||
for ; repeat > 0; repeat-- {
|
||||
dst[symbol] = cl
|
||||
symbol++
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// decodeHuffmanTree decodes a Huffman tree into h.
|
||||
func (d *decoder) decodeHuffmanTree(h *hTree, alphabetSize uint32) error {
|
||||
useSimple, err := d.read(1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if useSimple != 0 {
|
||||
nSymbols, err := d.read(1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nSymbols++
|
||||
firstSymbolLengthCode, err := d.read(1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
firstSymbolLengthCode = 7*firstSymbolLengthCode + 1
|
||||
var symbols [2]uint32
|
||||
symbols[0], err = d.read(firstSymbolLengthCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if nSymbols == 2 {
|
||||
symbols[1], err = d.read(8)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return h.buildSimple(nSymbols, symbols, alphabetSize)
|
||||
}
|
||||
|
||||
nCodes, err := d.read(4)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nCodes += 4
|
||||
if int(nCodes) > len(codeLengthCodeOrder) {
|
||||
return errInvalidHuffmanTree
|
||||
}
|
||||
codeLengthCodeLengths := [len(codeLengthCodeOrder)]uint32{}
|
||||
for i := uint32(0); i < nCodes; i++ {
|
||||
codeLengthCodeLengths[codeLengthCodeOrder[i]], err = d.read(3)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
codeLengths := make([]uint32, alphabetSize)
|
||||
if err = d.decodeCodeLengths(codeLengths, codeLengthCodeLengths[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
return h.build(codeLengths)
|
||||
}
|
||||
|
||||
const (
|
||||
huffGreen = 0
|
||||
huffRed = 1
|
||||
huffBlue = 2
|
||||
huffAlpha = 3
|
||||
huffDistance = 4
|
||||
nHuff = 5
|
||||
)
|
||||
|
||||
// hGroup is an array of 5 Huffman trees.
|
||||
type hGroup [nHuff]hTree
|
||||
|
||||
// decodeHuffmanGroups decodes the one or more hGroups used to decode the pixel
|
||||
// data. If one hGroup is used for the entire image, then hPix and hBits will
|
||||
// be zero. If more than one hGroup is used, then hPix contains the meta-image
|
||||
// that maps tiles to hGroup index, and hBits contains the log-2 tile size.
|
||||
func (d *decoder) decodeHuffmanGroups(w int32, h int32, topLevel bool, ccBits uint32) (
|
||||
hGroups []hGroup, hPix []byte, hBits uint32, err error) {
|
||||
|
||||
maxHGroupIndex := 0
|
||||
if topLevel {
|
||||
useMeta, err := d.read(1)
|
||||
if err != nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
if useMeta != 0 {
|
||||
hBits, err = d.read(3)
|
||||
if err != nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
hBits += 2
|
||||
hPix, err = d.decodePix(nTiles(w, hBits), nTiles(h, hBits), 0, false)
|
||||
if err != nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
for p := 0; p < len(hPix); p += 4 {
|
||||
i := int(hPix[p])<<8 | int(hPix[p+1])
|
||||
if maxHGroupIndex < i {
|
||||
maxHGroupIndex = i
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
hGroups = make([]hGroup, maxHGroupIndex+1)
|
||||
for i := range hGroups {
|
||||
for j, alphabetSize := range alphabetSizes {
|
||||
if j == 0 && ccBits > 0 {
|
||||
alphabetSize += 1 << ccBits
|
||||
}
|
||||
if err := d.decodeHuffmanTree(&hGroups[i][j], alphabetSize); err != nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return hGroups, hPix, hBits, nil
|
||||
}
|
||||
|
||||
const (
|
||||
nLiteralCodes = 256
|
||||
nLengthCodes = 24
|
||||
nDistanceCodes = 40
|
||||
)
|
||||
|
||||
var alphabetSizes = [nHuff]uint32{
|
||||
nLiteralCodes + nLengthCodes,
|
||||
nLiteralCodes,
|
||||
nLiteralCodes,
|
||||
nLiteralCodes,
|
||||
nDistanceCodes,
|
||||
}
|
||||
|
||||
// decodePix decodes pixel data, specified in section 5.2.2.
|
||||
func (d *decoder) decodePix(w int32, h int32, minCap int32, topLevel bool) ([]byte, error) {
|
||||
// Decode the color cache parameters.
|
||||
ccBits, ccShift, ccEntries := uint32(0), uint32(0), ([]uint32)(nil)
|
||||
useColorCache, err := d.read(1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if useColorCache != 0 {
|
||||
ccBits, err = d.read(4)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ccBits < 1 || 11 < ccBits {
|
||||
return nil, errors.New("vp8l: invalid color cache parameters")
|
||||
}
|
||||
ccShift = 32 - ccBits
|
||||
ccEntries = make([]uint32, 1<<ccBits)
|
||||
}
|
||||
|
||||
// Decode the Huffman groups.
|
||||
hGroups, hPix, hBits, err := d.decodeHuffmanGroups(w, h, topLevel, ccBits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hMask, tilesPerRow := int32(0), int32(0)
|
||||
if hBits != 0 {
|
||||
hMask, tilesPerRow = 1<<hBits-1, nTiles(w, hBits)
|
||||
}
|
||||
|
||||
// Decode the pixels.
|
||||
if minCap < 4*w*h {
|
||||
minCap = 4 * w * h
|
||||
}
|
||||
pix := make([]byte, 4*w*h, minCap)
|
||||
p, cachedP := 0, 0
|
||||
x, y := int32(0), int32(0)
|
||||
hg, lookupHG := &hGroups[0], hMask != 0
|
||||
for p < len(pix) {
|
||||
if lookupHG {
|
||||
i := 4 * (tilesPerRow*(y>>hBits) + (x >> hBits))
|
||||
hg = &hGroups[uint32(hPix[i])<<8|uint32(hPix[i+1])]
|
||||
}
|
||||
|
||||
green, err := hg[huffGreen].next(d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch {
|
||||
case green < nLiteralCodes:
|
||||
// We have a literal pixel.
|
||||
red, err := hg[huffRed].next(d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blue, err := hg[huffBlue].next(d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
alpha, err := hg[huffAlpha].next(d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pix[p+0] = uint8(red)
|
||||
pix[p+1] = uint8(green)
|
||||
pix[p+2] = uint8(blue)
|
||||
pix[p+3] = uint8(alpha)
|
||||
p += 4
|
||||
|
||||
x++
|
||||
if x == w {
|
||||
x, y = 0, y+1
|
||||
}
|
||||
lookupHG = hMask != 0 && x&hMask == 0
|
||||
|
||||
case green < nLiteralCodes+nLengthCodes:
|
||||
// We have a LZ77 backwards reference.
|
||||
length, err := d.lz77Param(green - nLiteralCodes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
distSym, err := hg[huffDistance].next(d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
distCode, err := d.lz77Param(distSym)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dist := distanceMap(w, distCode)
|
||||
pEnd := p + 4*int(length)
|
||||
q := p - 4*int(dist)
|
||||
qEnd := pEnd - 4*int(dist)
|
||||
if p < 0 || len(pix) < pEnd || q < 0 || len(pix) < qEnd {
|
||||
return nil, errors.New("vp8l: invalid LZ77 parameters")
|
||||
}
|
||||
for ; p < pEnd; p, q = p+1, q+1 {
|
||||
pix[p] = pix[q]
|
||||
}
|
||||
|
||||
x += int32(length)
|
||||
for x >= w {
|
||||
x, y = x-w, y+1
|
||||
}
|
||||
lookupHG = hMask != 0
|
||||
|
||||
default:
|
||||
// We have a color cache lookup. First, insert previous pixels
|
||||
// into the cache. Note that VP8L assumes ARGB order, but the
|
||||
// Go image.RGBA type is in RGBA order.
|
||||
for ; cachedP < p; cachedP += 4 {
|
||||
argb := uint32(pix[cachedP+0])<<16 |
|
||||
uint32(pix[cachedP+1])<<8 |
|
||||
uint32(pix[cachedP+2])<<0 |
|
||||
uint32(pix[cachedP+3])<<24
|
||||
ccEntries[(argb*colorCacheMultiplier)>>ccShift] = argb
|
||||
}
|
||||
green -= nLiteralCodes + nLengthCodes
|
||||
if int(green) >= len(ccEntries) {
|
||||
return nil, errors.New("vp8l: invalid color cache index")
|
||||
}
|
||||
argb := ccEntries[green]
|
||||
pix[p+0] = uint8(argb >> 16)
|
||||
pix[p+1] = uint8(argb >> 8)
|
||||
pix[p+2] = uint8(argb >> 0)
|
||||
pix[p+3] = uint8(argb >> 24)
|
||||
p += 4
|
||||
|
||||
x++
|
||||
if x == w {
|
||||
x, y = 0, y+1
|
||||
}
|
||||
lookupHG = hMask != 0 && x&hMask == 0
|
||||
}
|
||||
}
|
||||
return pix, nil
|
||||
}
|
||||
|
||||
// lz77Param returns the next LZ77 parameter: a length or a distance, specified
|
||||
// in section 4.2.2.
|
||||
func (d *decoder) lz77Param(symbol uint32) (uint32, error) {
|
||||
if symbol < 4 {
|
||||
return symbol + 1, nil
|
||||
}
|
||||
extraBits := (symbol - 2) >> 1
|
||||
offset := (2 + symbol&1) << extraBits
|
||||
n, err := d.read(extraBits)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return offset + n + 1, nil
|
||||
}
|
||||
|
||||
// decodeHeader decodes the VP8L header from r.
|
||||
func decodeHeader(r io.Reader) (d *decoder, w int32, h int32, err error) {
|
||||
rr, ok := r.(io.ByteReader)
|
||||
if !ok {
|
||||
rr = bufio.NewReader(r)
|
||||
}
|
||||
d = &decoder{r: rr}
|
||||
magic, err := d.read(8)
|
||||
if err != nil {
|
||||
return nil, 0, 0, err
|
||||
}
|
||||
if magic != 0x2f {
|
||||
return nil, 0, 0, errors.New("vp8l: invalid header")
|
||||
}
|
||||
width, err := d.read(14)
|
||||
if err != nil {
|
||||
return nil, 0, 0, err
|
||||
}
|
||||
width++
|
||||
height, err := d.read(14)
|
||||
if err != nil {
|
||||
return nil, 0, 0, err
|
||||
}
|
||||
height++
|
||||
_, err = d.read(1) // Read and ignore the hasAlpha hint.
|
||||
if err != nil {
|
||||
return nil, 0, 0, err
|
||||
}
|
||||
version, err := d.read(3)
|
||||
if err != nil {
|
||||
return nil, 0, 0, err
|
||||
}
|
||||
if version != 0 {
|
||||
return nil, 0, 0, errors.New("vp8l: invalid version")
|
||||
}
|
||||
return d, int32(width), int32(height), nil
|
||||
}
|
||||
|
||||
// DecodeConfig decodes the color model and dimensions of a VP8L image from r.
|
||||
func DecodeConfig(r io.Reader) (image.Config, error) {
|
||||
_, w, h, err := decodeHeader(r)
|
||||
if err != nil {
|
||||
return image.Config{}, err
|
||||
}
|
||||
return image.Config{
|
||||
ColorModel: color.NRGBAModel,
|
||||
Width: int(w),
|
||||
Height: int(h),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Decode decodes a VP8L image from r.
|
||||
func Decode(r io.Reader) (image.Image, error) {
|
||||
d, w, h, err := decodeHeader(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Decode the transforms.
|
||||
var (
|
||||
nTransforms int
|
||||
transforms [nTransformTypes]transform
|
||||
transformsSeen [nTransformTypes]bool
|
||||
originalW = w
|
||||
)
|
||||
for {
|
||||
more, err := d.read(1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if more == 0 {
|
||||
break
|
||||
}
|
||||
var t transform
|
||||
t, w, err = d.decodeTransform(w, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if transformsSeen[t.transformType] {
|
||||
return nil, errors.New("vp8l: repeated transform")
|
||||
}
|
||||
transformsSeen[t.transformType] = true
|
||||
transforms[nTransforms] = t
|
||||
nTransforms++
|
||||
}
|
||||
// Decode the transformed pixels.
|
||||
pix, err := d.decodePix(w, h, 0, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Apply the inverse transformations.
|
||||
for i := nTransforms - 1; i >= 0; i-- {
|
||||
t := &transforms[i]
|
||||
pix = inverseTransforms[t.transformType](t, pix, h)
|
||||
}
|
||||
return &image.NRGBA{
|
||||
Pix: pix,
|
||||
Stride: 4 * int(originalW),
|
||||
Rect: image.Rect(0, 0, int(originalW), int(h)),
|
||||
}, nil
|
||||
}
|
||||
245
vendor/golang.org/x/image/vp8l/huffman.go
generated
vendored
Normal file
245
vendor/golang.org/x/image/vp8l/huffman.go
generated
vendored
Normal file
@@ -0,0 +1,245 @@
|
||||
// Copyright 2014 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 vp8l
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// reverseBits reverses the bits in a byte.
|
||||
var reverseBits = [256]uint8{
|
||||
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
|
||||
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
|
||||
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
|
||||
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
|
||||
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
|
||||
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
|
||||
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
|
||||
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
|
||||
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
|
||||
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
|
||||
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
|
||||
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
|
||||
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
|
||||
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
|
||||
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
|
||||
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
|
||||
}
|
||||
|
||||
// hNode is a node in a Huffman tree.
|
||||
type hNode struct {
|
||||
// symbol is the symbol held by this node.
|
||||
symbol uint32
|
||||
// children, if positive, is the hTree.nodes index of the first of
|
||||
// this node's two children. Zero means an uninitialized node,
|
||||
// and -1 means a leaf node.
|
||||
children int32
|
||||
}
|
||||
|
||||
const leafNode = -1
|
||||
|
||||
// lutSize is the log-2 size of an hTree's look-up table.
|
||||
const lutSize, lutMask = 7, 1<<7 - 1
|
||||
|
||||
// hTree is a Huffman tree.
|
||||
type hTree struct {
|
||||
// nodes are the nodes of the Huffman tree. During construction,
|
||||
// len(nodes) grows from 1 up to cap(nodes) by steps of two.
|
||||
// After construction, len(nodes) == cap(nodes), and both equal
|
||||
// 2*theNumberOfSymbols - 1.
|
||||
nodes []hNode
|
||||
// lut is a look-up table for walking the nodes. The x in lut[x] is
|
||||
// the next lutSize bits in the bit-stream. The low 8 bits of lut[x]
|
||||
// equals 1 plus the number of bits in the next code, or 0 if the
|
||||
// next code requires more than lutSize bits. The high 24 bits are:
|
||||
// - the symbol, if the code requires lutSize or fewer bits, or
|
||||
// - the hTree.nodes index to start the tree traversal from, if
|
||||
// the next code requires more than lutSize bits.
|
||||
lut [1 << lutSize]uint32
|
||||
}
|
||||
|
||||
// insert inserts into the hTree a symbol whose encoding is the least
|
||||
// significant codeLength bits of code.
|
||||
func (h *hTree) insert(symbol uint32, code uint32, codeLength uint32) error {
|
||||
if symbol > 0xffff || codeLength > 0xfe {
|
||||
return errInvalidHuffmanTree
|
||||
}
|
||||
baseCode := uint32(0)
|
||||
if codeLength > lutSize {
|
||||
baseCode = uint32(reverseBits[(code>>(codeLength-lutSize))&0xff]) >> (8 - lutSize)
|
||||
} else {
|
||||
baseCode = uint32(reverseBits[code&0xff]) >> (8 - codeLength)
|
||||
for i := 0; i < 1<<(lutSize-codeLength); i++ {
|
||||
h.lut[baseCode|uint32(i)<<codeLength] = symbol<<8 | (codeLength + 1)
|
||||
}
|
||||
}
|
||||
|
||||
n := uint32(0)
|
||||
for jump := lutSize; codeLength > 0; {
|
||||
codeLength--
|
||||
if int(n) > len(h.nodes) {
|
||||
return errInvalidHuffmanTree
|
||||
}
|
||||
switch h.nodes[n].children {
|
||||
case leafNode:
|
||||
return errInvalidHuffmanTree
|
||||
case 0:
|
||||
if len(h.nodes) == cap(h.nodes) {
|
||||
return errInvalidHuffmanTree
|
||||
}
|
||||
// Create two empty child nodes.
|
||||
h.nodes[n].children = int32(len(h.nodes))
|
||||
h.nodes = h.nodes[:len(h.nodes)+2]
|
||||
}
|
||||
n = uint32(h.nodes[n].children) + 1&(code>>codeLength)
|
||||
jump--
|
||||
if jump == 0 && h.lut[baseCode] == 0 {
|
||||
h.lut[baseCode] = n << 8
|
||||
}
|
||||
}
|
||||
|
||||
switch h.nodes[n].children {
|
||||
case leafNode:
|
||||
// No-op.
|
||||
case 0:
|
||||
// Turn the uninitialized node into a leaf.
|
||||
h.nodes[n].children = leafNode
|
||||
default:
|
||||
return errInvalidHuffmanTree
|
||||
}
|
||||
h.nodes[n].symbol = symbol
|
||||
return nil
|
||||
}
|
||||
|
||||
// codeLengthsToCodes returns the canonical Huffman codes implied by the
|
||||
// sequence of code lengths.
|
||||
func codeLengthsToCodes(codeLengths []uint32) ([]uint32, error) {
|
||||
maxCodeLength := uint32(0)
|
||||
for _, cl := range codeLengths {
|
||||
if maxCodeLength < cl {
|
||||
maxCodeLength = cl
|
||||
}
|
||||
}
|
||||
const maxAllowedCodeLength = 15
|
||||
if len(codeLengths) == 0 || maxCodeLength > maxAllowedCodeLength {
|
||||
return nil, errInvalidHuffmanTree
|
||||
}
|
||||
histogram := [maxAllowedCodeLength + 1]uint32{}
|
||||
for _, cl := range codeLengths {
|
||||
histogram[cl]++
|
||||
}
|
||||
currCode, nextCodes := uint32(0), [maxAllowedCodeLength + 1]uint32{}
|
||||
for cl := 1; cl < len(nextCodes); cl++ {
|
||||
currCode = (currCode + histogram[cl-1]) << 1
|
||||
nextCodes[cl] = currCode
|
||||
}
|
||||
codes := make([]uint32, len(codeLengths))
|
||||
for symbol, cl := range codeLengths {
|
||||
if cl > 0 {
|
||||
codes[symbol] = nextCodes[cl]
|
||||
nextCodes[cl]++
|
||||
}
|
||||
}
|
||||
return codes, nil
|
||||
}
|
||||
|
||||
// build builds a canonical Huffman tree from the given code lengths.
|
||||
func (h *hTree) build(codeLengths []uint32) error {
|
||||
// Calculate the number of symbols.
|
||||
var nSymbols, lastSymbol uint32
|
||||
for symbol, cl := range codeLengths {
|
||||
if cl != 0 {
|
||||
nSymbols++
|
||||
lastSymbol = uint32(symbol)
|
||||
}
|
||||
}
|
||||
if nSymbols == 0 {
|
||||
return errInvalidHuffmanTree
|
||||
}
|
||||
h.nodes = make([]hNode, 1, 2*nSymbols-1)
|
||||
// Handle the trivial case.
|
||||
if nSymbols == 1 {
|
||||
if len(codeLengths) <= int(lastSymbol) {
|
||||
return errInvalidHuffmanTree
|
||||
}
|
||||
return h.insert(lastSymbol, 0, 0)
|
||||
}
|
||||
// Handle the non-trivial case.
|
||||
codes, err := codeLengthsToCodes(codeLengths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for symbol, cl := range codeLengths {
|
||||
if cl > 0 {
|
||||
if err := h.insert(uint32(symbol), codes[symbol], cl); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// buildSimple builds a Huffman tree with 1 or 2 symbols.
|
||||
func (h *hTree) buildSimple(nSymbols uint32, symbols [2]uint32, alphabetSize uint32) error {
|
||||
h.nodes = make([]hNode, 1, 2*nSymbols-1)
|
||||
for i := uint32(0); i < nSymbols; i++ {
|
||||
if symbols[i] >= alphabetSize {
|
||||
return errInvalidHuffmanTree
|
||||
}
|
||||
if err := h.insert(symbols[i], i, nSymbols-1); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// next returns the next Huffman-encoded symbol from the bit-stream d.
|
||||
func (h *hTree) next(d *decoder) (uint32, error) {
|
||||
var n uint32
|
||||
// Read enough bits so that we can use the look-up table.
|
||||
if d.nBits < lutSize {
|
||||
c, err := d.r.ReadByte()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
// There are no more bytes of data, but we may still be able
|
||||
// to read the next symbol out of the previously read bits.
|
||||
goto slowPath
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
d.bits |= uint32(c) << d.nBits
|
||||
d.nBits += 8
|
||||
}
|
||||
// Use the look-up table.
|
||||
n = h.lut[d.bits&lutMask]
|
||||
if b := n & 0xff; b != 0 {
|
||||
b--
|
||||
d.bits >>= b
|
||||
d.nBits -= b
|
||||
return n >> 8, nil
|
||||
}
|
||||
n >>= 8
|
||||
d.bits >>= lutSize
|
||||
d.nBits -= lutSize
|
||||
|
||||
slowPath:
|
||||
for h.nodes[n].children != leafNode {
|
||||
if d.nBits == 0 {
|
||||
c, err := d.r.ReadByte()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
d.bits = uint32(c)
|
||||
d.nBits = 8
|
||||
}
|
||||
n = uint32(h.nodes[n].children) + 1&d.bits
|
||||
d.bits >>= 1
|
||||
d.nBits--
|
||||
}
|
||||
return h.nodes[n].symbol, nil
|
||||
}
|
||||
299
vendor/golang.org/x/image/vp8l/transform.go
generated
vendored
Normal file
299
vendor/golang.org/x/image/vp8l/transform.go
generated
vendored
Normal file
@@ -0,0 +1,299 @@
|
||||
// Copyright 2014 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 vp8l
|
||||
|
||||
// This file deals with image transforms, specified in section 3.
|
||||
|
||||
// nTiles returns the number of tiles needed to cover size pixels, where each
|
||||
// tile's side is 1<<bits pixels long.
|
||||
func nTiles(size int32, bits uint32) int32 {
|
||||
return (size + 1<<bits - 1) >> bits
|
||||
}
|
||||
|
||||
const (
|
||||
transformTypePredictor = 0
|
||||
transformTypeCrossColor = 1
|
||||
transformTypeSubtractGreen = 2
|
||||
transformTypeColorIndexing = 3
|
||||
nTransformTypes = 4
|
||||
)
|
||||
|
||||
// transform holds the parameters for an invertible transform.
|
||||
type transform struct {
|
||||
// transformType is the type of the transform.
|
||||
transformType uint32
|
||||
// oldWidth is the width of the image before transformation (or
|
||||
// equivalently, after inverse transformation). The color-indexing
|
||||
// transform can reduce the width. For example, a 50-pixel-wide
|
||||
// image that only needs 4 bits (half a byte) per color index can
|
||||
// be transformed into a 25-pixel-wide image.
|
||||
oldWidth int32
|
||||
// bits is the log-2 size of the transform's tiles, for the predictor
|
||||
// and cross-color transforms. 8>>bits is the number of bits per
|
||||
// color index, for the color-index transform.
|
||||
bits uint32
|
||||
// pix is the tile values, for the predictor and cross-color
|
||||
// transforms, and the color palette, for the color-index transform.
|
||||
pix []byte
|
||||
}
|
||||
|
||||
var inverseTransforms = [nTransformTypes]func(*transform, []byte, int32) []byte{
|
||||
transformTypePredictor: inversePredictor,
|
||||
transformTypeCrossColor: inverseCrossColor,
|
||||
transformTypeSubtractGreen: inverseSubtractGreen,
|
||||
transformTypeColorIndexing: inverseColorIndexing,
|
||||
}
|
||||
|
||||
func inversePredictor(t *transform, pix []byte, h int32) []byte {
|
||||
if t.oldWidth == 0 || h == 0 {
|
||||
return pix
|
||||
}
|
||||
// The first pixel's predictor is mode 0 (opaque black).
|
||||
pix[3] += 0xff
|
||||
p, mask := int32(4), int32(1)<<t.bits-1
|
||||
for x := int32(1); x < t.oldWidth; x++ {
|
||||
// The rest of the first row's predictor is mode 1 (L).
|
||||
pix[p+0] += pix[p-4]
|
||||
pix[p+1] += pix[p-3]
|
||||
pix[p+2] += pix[p-2]
|
||||
pix[p+3] += pix[p-1]
|
||||
p += 4
|
||||
}
|
||||
top, tilesPerRow := 0, nTiles(t.oldWidth, t.bits)
|
||||
for y := int32(1); y < h; y++ {
|
||||
// The first column's predictor is mode 2 (T).
|
||||
pix[p+0] += pix[top+0]
|
||||
pix[p+1] += pix[top+1]
|
||||
pix[p+2] += pix[top+2]
|
||||
pix[p+3] += pix[top+3]
|
||||
p, top = p+4, top+4
|
||||
|
||||
q := 4 * (y >> t.bits) * tilesPerRow
|
||||
predictorMode := t.pix[q+1] & 0x0f
|
||||
q += 4
|
||||
for x := int32(1); x < t.oldWidth; x++ {
|
||||
if x&mask == 0 {
|
||||
predictorMode = t.pix[q+1] & 0x0f
|
||||
q += 4
|
||||
}
|
||||
switch predictorMode {
|
||||
case 0: // Opaque black.
|
||||
pix[p+3] += 0xff
|
||||
|
||||
case 1: // L.
|
||||
pix[p+0] += pix[p-4]
|
||||
pix[p+1] += pix[p-3]
|
||||
pix[p+2] += pix[p-2]
|
||||
pix[p+3] += pix[p-1]
|
||||
|
||||
case 2: // T.
|
||||
pix[p+0] += pix[top+0]
|
||||
pix[p+1] += pix[top+1]
|
||||
pix[p+2] += pix[top+2]
|
||||
pix[p+3] += pix[top+3]
|
||||
|
||||
case 3: // TR.
|
||||
pix[p+0] += pix[top+4]
|
||||
pix[p+1] += pix[top+5]
|
||||
pix[p+2] += pix[top+6]
|
||||
pix[p+3] += pix[top+7]
|
||||
|
||||
case 4: // TL.
|
||||
pix[p+0] += pix[top-4]
|
||||
pix[p+1] += pix[top-3]
|
||||
pix[p+2] += pix[top-2]
|
||||
pix[p+3] += pix[top-1]
|
||||
|
||||
case 5: // Average2(Average2(L, TR), T).
|
||||
pix[p+0] += avg2(avg2(pix[p-4], pix[top+4]), pix[top+0])
|
||||
pix[p+1] += avg2(avg2(pix[p-3], pix[top+5]), pix[top+1])
|
||||
pix[p+2] += avg2(avg2(pix[p-2], pix[top+6]), pix[top+2])
|
||||
pix[p+3] += avg2(avg2(pix[p-1], pix[top+7]), pix[top+3])
|
||||
|
||||
case 6: // Average2(L, TL).
|
||||
pix[p+0] += avg2(pix[p-4], pix[top-4])
|
||||
pix[p+1] += avg2(pix[p-3], pix[top-3])
|
||||
pix[p+2] += avg2(pix[p-2], pix[top-2])
|
||||
pix[p+3] += avg2(pix[p-1], pix[top-1])
|
||||
|
||||
case 7: // Average2(L, T).
|
||||
pix[p+0] += avg2(pix[p-4], pix[top+0])
|
||||
pix[p+1] += avg2(pix[p-3], pix[top+1])
|
||||
pix[p+2] += avg2(pix[p-2], pix[top+2])
|
||||
pix[p+3] += avg2(pix[p-1], pix[top+3])
|
||||
|
||||
case 8: // Average2(TL, T).
|
||||
pix[p+0] += avg2(pix[top-4], pix[top+0])
|
||||
pix[p+1] += avg2(pix[top-3], pix[top+1])
|
||||
pix[p+2] += avg2(pix[top-2], pix[top+2])
|
||||
pix[p+3] += avg2(pix[top-1], pix[top+3])
|
||||
|
||||
case 9: // Average2(T, TR).
|
||||
pix[p+0] += avg2(pix[top+0], pix[top+4])
|
||||
pix[p+1] += avg2(pix[top+1], pix[top+5])
|
||||
pix[p+2] += avg2(pix[top+2], pix[top+6])
|
||||
pix[p+3] += avg2(pix[top+3], pix[top+7])
|
||||
|
||||
case 10: // Average2(Average2(L, TL), Average2(T, TR)).
|
||||
pix[p+0] += avg2(avg2(pix[p-4], pix[top-4]), avg2(pix[top+0], pix[top+4]))
|
||||
pix[p+1] += avg2(avg2(pix[p-3], pix[top-3]), avg2(pix[top+1], pix[top+5]))
|
||||
pix[p+2] += avg2(avg2(pix[p-2], pix[top-2]), avg2(pix[top+2], pix[top+6]))
|
||||
pix[p+3] += avg2(avg2(pix[p-1], pix[top-1]), avg2(pix[top+3], pix[top+7]))
|
||||
|
||||
case 11: // Select(L, T, TL).
|
||||
l0 := int32(pix[p-4])
|
||||
l1 := int32(pix[p-3])
|
||||
l2 := int32(pix[p-2])
|
||||
l3 := int32(pix[p-1])
|
||||
c0 := int32(pix[top-4])
|
||||
c1 := int32(pix[top-3])
|
||||
c2 := int32(pix[top-2])
|
||||
c3 := int32(pix[top-1])
|
||||
t0 := int32(pix[top+0])
|
||||
t1 := int32(pix[top+1])
|
||||
t2 := int32(pix[top+2])
|
||||
t3 := int32(pix[top+3])
|
||||
l := abs(c0-t0) + abs(c1-t1) + abs(c2-t2) + abs(c3-t3)
|
||||
t := abs(c0-l0) + abs(c1-l1) + abs(c2-l2) + abs(c3-l3)
|
||||
if l < t {
|
||||
pix[p+0] += uint8(l0)
|
||||
pix[p+1] += uint8(l1)
|
||||
pix[p+2] += uint8(l2)
|
||||
pix[p+3] += uint8(l3)
|
||||
} else {
|
||||
pix[p+0] += uint8(t0)
|
||||
pix[p+1] += uint8(t1)
|
||||
pix[p+2] += uint8(t2)
|
||||
pix[p+3] += uint8(t3)
|
||||
}
|
||||
|
||||
case 12: // ClampAddSubtractFull(L, T, TL).
|
||||
pix[p+0] += clampAddSubtractFull(pix[p-4], pix[top+0], pix[top-4])
|
||||
pix[p+1] += clampAddSubtractFull(pix[p-3], pix[top+1], pix[top-3])
|
||||
pix[p+2] += clampAddSubtractFull(pix[p-2], pix[top+2], pix[top-2])
|
||||
pix[p+3] += clampAddSubtractFull(pix[p-1], pix[top+3], pix[top-1])
|
||||
|
||||
case 13: // ClampAddSubtractHalf(Average2(L, T), TL).
|
||||
pix[p+0] += clampAddSubtractHalf(avg2(pix[p-4], pix[top+0]), pix[top-4])
|
||||
pix[p+1] += clampAddSubtractHalf(avg2(pix[p-3], pix[top+1]), pix[top-3])
|
||||
pix[p+2] += clampAddSubtractHalf(avg2(pix[p-2], pix[top+2]), pix[top-2])
|
||||
pix[p+3] += clampAddSubtractHalf(avg2(pix[p-1], pix[top+3]), pix[top-1])
|
||||
}
|
||||
p, top = p+4, top+4
|
||||
}
|
||||
}
|
||||
return pix
|
||||
}
|
||||
|
||||
func inverseCrossColor(t *transform, pix []byte, h int32) []byte {
|
||||
var greenToRed, greenToBlue, redToBlue int32
|
||||
p, mask, tilesPerRow := int32(0), int32(1)<<t.bits-1, nTiles(t.oldWidth, t.bits)
|
||||
for y := int32(0); y < h; y++ {
|
||||
q := 4 * (y >> t.bits) * tilesPerRow
|
||||
for x := int32(0); x < t.oldWidth; x++ {
|
||||
if x&mask == 0 {
|
||||
redToBlue = int32(int8(t.pix[q+0]))
|
||||
greenToBlue = int32(int8(t.pix[q+1]))
|
||||
greenToRed = int32(int8(t.pix[q+2]))
|
||||
q += 4
|
||||
}
|
||||
red := pix[p+0]
|
||||
green := pix[p+1]
|
||||
blue := pix[p+2]
|
||||
red += uint8(uint32(greenToRed*int32(int8(green))) >> 5)
|
||||
blue += uint8(uint32(greenToBlue*int32(int8(green))) >> 5)
|
||||
blue += uint8(uint32(redToBlue*int32(int8(red))) >> 5)
|
||||
pix[p+0] = red
|
||||
pix[p+2] = blue
|
||||
p += 4
|
||||
}
|
||||
}
|
||||
return pix
|
||||
}
|
||||
|
||||
func inverseSubtractGreen(t *transform, pix []byte, h int32) []byte {
|
||||
for p := 0; p < len(pix); p += 4 {
|
||||
green := pix[p+1]
|
||||
pix[p+0] += green
|
||||
pix[p+2] += green
|
||||
}
|
||||
return pix
|
||||
}
|
||||
|
||||
func inverseColorIndexing(t *transform, pix []byte, h int32) []byte {
|
||||
if t.bits == 0 {
|
||||
for p := 0; p < len(pix); p += 4 {
|
||||
i := 4 * uint32(pix[p+1])
|
||||
pix[p+0] = t.pix[i+0]
|
||||
pix[p+1] = t.pix[i+1]
|
||||
pix[p+2] = t.pix[i+2]
|
||||
pix[p+3] = t.pix[i+3]
|
||||
}
|
||||
return pix
|
||||
}
|
||||
|
||||
vMask, xMask, bitsPerPixel := uint32(0), int32(0), uint32(8>>t.bits)
|
||||
switch t.bits {
|
||||
case 1:
|
||||
vMask, xMask = 0x0f, 0x01
|
||||
case 2:
|
||||
vMask, xMask = 0x03, 0x03
|
||||
case 3:
|
||||
vMask, xMask = 0x01, 0x07
|
||||
}
|
||||
|
||||
d, p, v, dst := 0, 0, uint32(0), make([]byte, 4*t.oldWidth*h)
|
||||
for y := int32(0); y < h; y++ {
|
||||
for x := int32(0); x < t.oldWidth; x++ {
|
||||
if x&xMask == 0 {
|
||||
v = uint32(pix[p+1])
|
||||
p += 4
|
||||
}
|
||||
|
||||
i := 4 * (v & vMask)
|
||||
dst[d+0] = t.pix[i+0]
|
||||
dst[d+1] = t.pix[i+1]
|
||||
dst[d+2] = t.pix[i+2]
|
||||
dst[d+3] = t.pix[i+3]
|
||||
d += 4
|
||||
|
||||
v >>= bitsPerPixel
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func abs(x int32) int32 {
|
||||
if x < 0 {
|
||||
return -x
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func avg2(a, b uint8) uint8 {
|
||||
return uint8((int32(a) + int32(b)) / 2)
|
||||
}
|
||||
|
||||
func clampAddSubtractFull(a, b, c uint8) uint8 {
|
||||
x := int32(a) + int32(b) - int32(c)
|
||||
if x < 0 {
|
||||
return 0
|
||||
}
|
||||
if x > 255 {
|
||||
return 255
|
||||
}
|
||||
return uint8(x)
|
||||
}
|
||||
|
||||
func clampAddSubtractHalf(a, b uint8) uint8 {
|
||||
x := int32(a) + (int32(a)-int32(b))/2
|
||||
if x < 0 {
|
||||
return 0
|
||||
}
|
||||
if x > 255 {
|
||||
return 255
|
||||
}
|
||||
return uint8(x)
|
||||
}
|
||||
271
vendor/golang.org/x/image/webp/decode.go
generated
vendored
Normal file
271
vendor/golang.org/x/image/webp/decode.go
generated
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
// Copyright 2011 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 webp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"image"
|
||||
"image/color"
|
||||
"io"
|
||||
|
||||
"golang.org/x/image/riff"
|
||||
"golang.org/x/image/vp8"
|
||||
"golang.org/x/image/vp8l"
|
||||
)
|
||||
|
||||
var errInvalidFormat = errors.New("webp: invalid format")
|
||||
|
||||
var (
|
||||
fccALPH = riff.FourCC{'A', 'L', 'P', 'H'}
|
||||
fccVP8 = riff.FourCC{'V', 'P', '8', ' '}
|
||||
fccVP8L = riff.FourCC{'V', 'P', '8', 'L'}
|
||||
fccVP8X = riff.FourCC{'V', 'P', '8', 'X'}
|
||||
fccWEBP = riff.FourCC{'W', 'E', 'B', 'P'}
|
||||
)
|
||||
|
||||
func decode(r io.Reader, configOnly bool) (image.Image, image.Config, error) {
|
||||
formType, riffReader, err := riff.NewReader(r)
|
||||
if err != nil {
|
||||
return nil, image.Config{}, err
|
||||
}
|
||||
if formType != fccWEBP {
|
||||
return nil, image.Config{}, errInvalidFormat
|
||||
}
|
||||
|
||||
var (
|
||||
alpha []byte
|
||||
alphaStride int
|
||||
wantAlpha bool
|
||||
widthMinusOne uint32
|
||||
heightMinusOne uint32
|
||||
buf [10]byte
|
||||
)
|
||||
for {
|
||||
chunkID, chunkLen, chunkData, err := riffReader.Next()
|
||||
if err == io.EOF {
|
||||
err = errInvalidFormat
|
||||
}
|
||||
if err != nil {
|
||||
return nil, image.Config{}, err
|
||||
}
|
||||
|
||||
switch chunkID {
|
||||
case fccALPH:
|
||||
if !wantAlpha {
|
||||
return nil, image.Config{}, errInvalidFormat
|
||||
}
|
||||
wantAlpha = false
|
||||
// Read the Pre-processing | Filter | Compression byte.
|
||||
if _, err := io.ReadFull(chunkData, buf[:1]); err != nil {
|
||||
if err == io.EOF {
|
||||
err = errInvalidFormat
|
||||
}
|
||||
return nil, image.Config{}, err
|
||||
}
|
||||
alpha, alphaStride, err = readAlpha(chunkData, widthMinusOne, heightMinusOne, buf[0]&0x03)
|
||||
if err != nil {
|
||||
return nil, image.Config{}, err
|
||||
}
|
||||
unfilterAlpha(alpha, alphaStride, (buf[0]>>2)&0x03)
|
||||
|
||||
case fccVP8:
|
||||
if wantAlpha || int32(chunkLen) < 0 {
|
||||
return nil, image.Config{}, errInvalidFormat
|
||||
}
|
||||
d := vp8.NewDecoder()
|
||||
d.Init(chunkData, int(chunkLen))
|
||||
fh, err := d.DecodeFrameHeader()
|
||||
if err != nil {
|
||||
return nil, image.Config{}, err
|
||||
}
|
||||
if configOnly {
|
||||
return nil, image.Config{
|
||||
ColorModel: color.YCbCrModel,
|
||||
Width: fh.Width,
|
||||
Height: fh.Height,
|
||||
}, nil
|
||||
}
|
||||
m, err := d.DecodeFrame()
|
||||
if err != nil {
|
||||
return nil, image.Config{}, err
|
||||
}
|
||||
if alpha != nil {
|
||||
return &image.NYCbCrA{
|
||||
YCbCr: *m,
|
||||
A: alpha,
|
||||
AStride: alphaStride,
|
||||
}, image.Config{}, nil
|
||||
}
|
||||
return m, image.Config{}, nil
|
||||
|
||||
case fccVP8L:
|
||||
if wantAlpha || alpha != nil {
|
||||
return nil, image.Config{}, errInvalidFormat
|
||||
}
|
||||
if configOnly {
|
||||
c, err := vp8l.DecodeConfig(chunkData)
|
||||
return nil, c, err
|
||||
}
|
||||
m, err := vp8l.Decode(chunkData)
|
||||
return m, image.Config{}, err
|
||||
|
||||
case fccVP8X:
|
||||
if chunkLen != 10 {
|
||||
return nil, image.Config{}, errInvalidFormat
|
||||
}
|
||||
if _, err := io.ReadFull(chunkData, buf[:10]); err != nil {
|
||||
return nil, image.Config{}, err
|
||||
}
|
||||
const (
|
||||
animationBit = 1 << 1
|
||||
xmpMetadataBit = 1 << 2
|
||||
exifMetadataBit = 1 << 3
|
||||
alphaBit = 1 << 4
|
||||
iccProfileBit = 1 << 5
|
||||
)
|
||||
wantAlpha = (buf[0] & alphaBit) != 0
|
||||
widthMinusOne = uint32(buf[4]) | uint32(buf[5])<<8 | uint32(buf[6])<<16
|
||||
heightMinusOne = uint32(buf[7]) | uint32(buf[8])<<8 | uint32(buf[9])<<16
|
||||
if configOnly {
|
||||
if wantAlpha {
|
||||
return nil, image.Config{
|
||||
ColorModel: color.NYCbCrAModel,
|
||||
Width: int(widthMinusOne) + 1,
|
||||
Height: int(heightMinusOne) + 1,
|
||||
}, nil
|
||||
}
|
||||
return nil, image.Config{
|
||||
ColorModel: color.YCbCrModel,
|
||||
Width: int(widthMinusOne) + 1,
|
||||
Height: int(heightMinusOne) + 1,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func readAlpha(chunkData io.Reader, widthMinusOne, heightMinusOne uint32, compression byte) (
|
||||
alpha []byte, alphaStride int, err error) {
|
||||
|
||||
switch compression {
|
||||
case 0:
|
||||
w := int(widthMinusOne) + 1
|
||||
h := int(heightMinusOne) + 1
|
||||
alpha = make([]byte, w*h)
|
||||
if _, err := io.ReadFull(chunkData, alpha); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return alpha, w, nil
|
||||
|
||||
case 1:
|
||||
// Read the VP8L-compressed alpha values. First, synthesize a 5-byte VP8L header:
|
||||
// a 1-byte magic number, a 14-bit widthMinusOne, a 14-bit heightMinusOne,
|
||||
// a 1-bit (ignored, zero) alphaIsUsed and a 3-bit (zero) version.
|
||||
// TODO(nigeltao): be more efficient than decoding an *image.NRGBA just to
|
||||
// extract the green values to a separately allocated []byte. Fixing this
|
||||
// will require changes to the vp8l package's API.
|
||||
if widthMinusOne > 0x3fff || heightMinusOne > 0x3fff {
|
||||
return nil, 0, errors.New("webp: invalid format")
|
||||
}
|
||||
alphaImage, err := vp8l.Decode(io.MultiReader(
|
||||
bytes.NewReader([]byte{
|
||||
0x2f, // VP8L magic number.
|
||||
uint8(widthMinusOne),
|
||||
uint8(widthMinusOne>>8) | uint8(heightMinusOne<<6),
|
||||
uint8(heightMinusOne >> 2),
|
||||
uint8(heightMinusOne >> 10),
|
||||
}),
|
||||
chunkData,
|
||||
))
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
// The green values of the inner NRGBA image are the alpha values of the
|
||||
// outer NYCbCrA image.
|
||||
pix := alphaImage.(*image.NRGBA).Pix
|
||||
alpha = make([]byte, len(pix)/4)
|
||||
for i := range alpha {
|
||||
alpha[i] = pix[4*i+1]
|
||||
}
|
||||
return alpha, int(widthMinusOne) + 1, nil
|
||||
}
|
||||
return nil, 0, errInvalidFormat
|
||||
}
|
||||
|
||||
func unfilterAlpha(alpha []byte, alphaStride int, filter byte) {
|
||||
if len(alpha) == 0 || alphaStride == 0 {
|
||||
return
|
||||
}
|
||||
switch filter {
|
||||
case 1: // Horizontal filter.
|
||||
for i := 1; i < alphaStride; i++ {
|
||||
alpha[i] += alpha[i-1]
|
||||
}
|
||||
for i := alphaStride; i < len(alpha); i += alphaStride {
|
||||
// The first column is equivalent to the vertical filter.
|
||||
alpha[i] += alpha[i-alphaStride]
|
||||
|
||||
for j := 1; j < alphaStride; j++ {
|
||||
alpha[i+j] += alpha[i+j-1]
|
||||
}
|
||||
}
|
||||
|
||||
case 2: // Vertical filter.
|
||||
// The first row is equivalent to the horizontal filter.
|
||||
for i := 1; i < alphaStride; i++ {
|
||||
alpha[i] += alpha[i-1]
|
||||
}
|
||||
|
||||
for i := alphaStride; i < len(alpha); i++ {
|
||||
alpha[i] += alpha[i-alphaStride]
|
||||
}
|
||||
|
||||
case 3: // Gradient filter.
|
||||
// The first row is equivalent to the horizontal filter.
|
||||
for i := 1; i < alphaStride; i++ {
|
||||
alpha[i] += alpha[i-1]
|
||||
}
|
||||
|
||||
for i := alphaStride; i < len(alpha); i += alphaStride {
|
||||
// The first column is equivalent to the vertical filter.
|
||||
alpha[i] += alpha[i-alphaStride]
|
||||
|
||||
// The interior is predicted on the three top/left pixels.
|
||||
for j := 1; j < alphaStride; j++ {
|
||||
c := int(alpha[i+j-alphaStride-1])
|
||||
b := int(alpha[i+j-alphaStride])
|
||||
a := int(alpha[i+j-1])
|
||||
x := a + b - c
|
||||
if x < 0 {
|
||||
x = 0
|
||||
} else if x > 255 {
|
||||
x = 255
|
||||
}
|
||||
alpha[i+j] += uint8(x)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decode reads a WEBP image from r and returns it as an image.Image.
|
||||
func Decode(r io.Reader) (image.Image, error) {
|
||||
m, _, err := decode(r, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, err
|
||||
}
|
||||
|
||||
// DecodeConfig returns the color model and dimensions of a WEBP image without
|
||||
// decoding the entire image.
|
||||
func DecodeConfig(r io.Reader) (image.Config, error) {
|
||||
_, c, err := decode(r, true)
|
||||
return c, err
|
||||
}
|
||||
|
||||
func init() {
|
||||
image.RegisterFormat("webp", "RIFF????WEBPVP8", Decode, DecodeConfig)
|
||||
}
|
||||
9
vendor/golang.org/x/image/webp/doc.go
generated
vendored
Normal file
9
vendor/golang.org/x/image/webp/doc.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// 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 webp implements a decoder for WEBP images.
|
||||
//
|
||||
// WEBP is defined at:
|
||||
// https://developers.google.com/speed/webp/docs/riff_container
|
||||
package webp // import "golang.org/x/image/webp"
|
||||
3
vendor/golang.org/x/text/AUTHORS
generated
vendored
Normal file
3
vendor/golang.org/x/text/AUTHORS
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# This source code refers to The Go Authors for copyright purposes.
|
||||
# The master list of authors is in the main Go distribution,
|
||||
# visible at http://tip.golang.org/AUTHORS.
|
||||
3
vendor/golang.org/x/text/CONTRIBUTORS
generated
vendored
Normal file
3
vendor/golang.org/x/text/CONTRIBUTORS
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# This source code was written by the Go contributors.
|
||||
# The master list of contributors is in the main Go distribution,
|
||||
# visible at http://tip.golang.org/CONTRIBUTORS.
|
||||
27
vendor/golang.org/x/text/LICENSE
generated
vendored
Normal file
27
vendor/golang.org/x/text/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
22
vendor/golang.org/x/text/PATENTS
generated
vendored
Normal file
22
vendor/golang.org/x/text/PATENTS
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
Additional IP Rights Grant (Patents)
|
||||
|
||||
"This implementation" means the copyrightable works distributed by
|
||||
Google as part of the Go project.
|
||||
|
||||
Google hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||
patent license to make, have made, use, offer to sell, sell, import,
|
||||
transfer and otherwise run, modify and propagate the contents of this
|
||||
implementation of Go, where such license applies only to those patent
|
||||
claims, both currently owned or controlled by Google and acquired in
|
||||
the future, licensable by Google that are necessarily infringed by this
|
||||
implementation of Go. This grant does not include claims that would be
|
||||
infringed only as a consequence of further modification of this
|
||||
implementation. If you or your agent or exclusive licensee institute or
|
||||
order or agree to the institution of patent litigation against any
|
||||
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||
that this implementation of Go or any code incorporated within this
|
||||
implementation of Go constitutes direct or contributory patent
|
||||
infringement, or inducement of patent infringement, then any patent
|
||||
rights granted to you under this License for this implementation of Go
|
||||
shall terminate as of the date such litigation is filed.
|
||||
709
vendor/golang.org/x/text/transform/transform.go
generated
vendored
Normal file
709
vendor/golang.org/x/text/transform/transform.go
generated
vendored
Normal file
@@ -0,0 +1,709 @@
|
||||
// Copyright 2013 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 transform provides reader and writer wrappers that transform the
|
||||
// bytes passing through as well as various transformations. Example
|
||||
// transformations provided by other packages include normalization and
|
||||
// conversion between character sets.
|
||||
package transform // import "golang.org/x/text/transform"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrShortDst means that the destination buffer was too short to
|
||||
// receive all of the transformed bytes.
|
||||
ErrShortDst = errors.New("transform: short destination buffer")
|
||||
|
||||
// ErrShortSrc means that the source buffer has insufficient data to
|
||||
// complete the transformation.
|
||||
ErrShortSrc = errors.New("transform: short source buffer")
|
||||
|
||||
// ErrEndOfSpan means that the input and output (the transformed input)
|
||||
// are not identical.
|
||||
ErrEndOfSpan = errors.New("transform: input and output are not identical")
|
||||
|
||||
// errInconsistentByteCount means that Transform returned success (nil
|
||||
// error) but also returned nSrc inconsistent with the src argument.
|
||||
errInconsistentByteCount = errors.New("transform: inconsistent byte count returned")
|
||||
|
||||
// errShortInternal means that an internal buffer is not large enough
|
||||
// to make progress and the Transform operation must be aborted.
|
||||
errShortInternal = errors.New("transform: short internal buffer")
|
||||
)
|
||||
|
||||
// Transformer transforms bytes.
|
||||
type Transformer interface {
|
||||
// Transform writes to dst the transformed bytes read from src, and
|
||||
// returns the number of dst bytes written and src bytes read. The
|
||||
// atEOF argument tells whether src represents the last bytes of the
|
||||
// input.
|
||||
//
|
||||
// Callers should always process the nDst bytes produced and account
|
||||
// for the nSrc bytes consumed before considering the error err.
|
||||
//
|
||||
// A nil error means that all of the transformed bytes (whether freshly
|
||||
// transformed from src or left over from previous Transform calls)
|
||||
// were written to dst. A nil error can be returned regardless of
|
||||
// whether atEOF is true. If err is nil then nSrc must equal len(src);
|
||||
// the converse is not necessarily true.
|
||||
//
|
||||
// ErrShortDst means that dst was too short to receive all of the
|
||||
// transformed bytes. ErrShortSrc means that src had insufficient data
|
||||
// to complete the transformation. If both conditions apply, then
|
||||
// either error may be returned. Other than the error conditions listed
|
||||
// here, implementations are free to report other errors that arise.
|
||||
Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error)
|
||||
|
||||
// Reset resets the state and allows a Transformer to be reused.
|
||||
Reset()
|
||||
}
|
||||
|
||||
// SpanningTransformer extends the Transformer interface with a Span method
|
||||
// that determines how much of the input already conforms to the Transformer.
|
||||
type SpanningTransformer interface {
|
||||
Transformer
|
||||
|
||||
// Span returns a position in src such that transforming src[:n] results in
|
||||
// identical output src[:n] for these bytes. It does not necessarily return
|
||||
// the largest such n. The atEOF argument tells whether src represents the
|
||||
// last bytes of the input.
|
||||
//
|
||||
// Callers should always account for the n bytes consumed before
|
||||
// considering the error err.
|
||||
//
|
||||
// A nil error means that all input bytes are known to be identical to the
|
||||
// output produced by the Transformer. A nil error can be returned
|
||||
// regardless of whether atEOF is true. If err is nil, then n must
|
||||
// equal len(src); the converse is not necessarily true.
|
||||
//
|
||||
// ErrEndOfSpan means that the Transformer output may differ from the
|
||||
// input after n bytes. Note that n may be len(src), meaning that the output
|
||||
// would contain additional bytes after otherwise identical output.
|
||||
// ErrShortSrc means that src had insufficient data to determine whether the
|
||||
// remaining bytes would change. Other than the error conditions listed
|
||||
// here, implementations are free to report other errors that arise.
|
||||
//
|
||||
// Calling Span can modify the Transformer state as a side effect. In
|
||||
// effect, it does the transformation just as calling Transform would, only
|
||||
// without copying to a destination buffer and only up to a point it can
|
||||
// determine the input and output bytes are the same. This is obviously more
|
||||
// limited than calling Transform, but can be more efficient in terms of
|
||||
// copying and allocating buffers. Calls to Span and Transform may be
|
||||
// interleaved.
|
||||
Span(src []byte, atEOF bool) (n int, err error)
|
||||
}
|
||||
|
||||
// NopResetter can be embedded by implementations of Transformer to add a nop
|
||||
// Reset method.
|
||||
type NopResetter struct{}
|
||||
|
||||
// Reset implements the Reset method of the Transformer interface.
|
||||
func (NopResetter) Reset() {}
|
||||
|
||||
// Reader wraps another io.Reader by transforming the bytes read.
|
||||
type Reader struct {
|
||||
r io.Reader
|
||||
t Transformer
|
||||
err error
|
||||
|
||||
// dst[dst0:dst1] contains bytes that have been transformed by t but
|
||||
// not yet copied out via Read.
|
||||
dst []byte
|
||||
dst0, dst1 int
|
||||
|
||||
// src[src0:src1] contains bytes that have been read from r but not
|
||||
// yet transformed through t.
|
||||
src []byte
|
||||
src0, src1 int
|
||||
|
||||
// transformComplete is whether the transformation is complete,
|
||||
// regardless of whether or not it was successful.
|
||||
transformComplete bool
|
||||
}
|
||||
|
||||
const defaultBufSize = 4096
|
||||
|
||||
// NewReader returns a new Reader that wraps r by transforming the bytes read
|
||||
// via t. It calls Reset on t.
|
||||
func NewReader(r io.Reader, t Transformer) *Reader {
|
||||
t.Reset()
|
||||
return &Reader{
|
||||
r: r,
|
||||
t: t,
|
||||
dst: make([]byte, defaultBufSize),
|
||||
src: make([]byte, defaultBufSize),
|
||||
}
|
||||
}
|
||||
|
||||
// Read implements the io.Reader interface.
|
||||
func (r *Reader) Read(p []byte) (int, error) {
|
||||
n, err := 0, error(nil)
|
||||
for {
|
||||
// Copy out any transformed bytes and return the final error if we are done.
|
||||
if r.dst0 != r.dst1 {
|
||||
n = copy(p, r.dst[r.dst0:r.dst1])
|
||||
r.dst0 += n
|
||||
if r.dst0 == r.dst1 && r.transformComplete {
|
||||
return n, r.err
|
||||
}
|
||||
return n, nil
|
||||
} else if r.transformComplete {
|
||||
return 0, r.err
|
||||
}
|
||||
|
||||
// Try to transform some source bytes, or to flush the transformer if we
|
||||
// are out of source bytes. We do this even if r.r.Read returned an error.
|
||||
// As the io.Reader documentation says, "process the n > 0 bytes returned
|
||||
// before considering the error".
|
||||
if r.src0 != r.src1 || r.err != nil {
|
||||
r.dst0 = 0
|
||||
r.dst1, n, err = r.t.Transform(r.dst, r.src[r.src0:r.src1], r.err == io.EOF)
|
||||
r.src0 += n
|
||||
|
||||
switch {
|
||||
case err == nil:
|
||||
if r.src0 != r.src1 {
|
||||
r.err = errInconsistentByteCount
|
||||
}
|
||||
// The Transform call was successful; we are complete if we
|
||||
// cannot read more bytes into src.
|
||||
r.transformComplete = r.err != nil
|
||||
continue
|
||||
case err == ErrShortDst && (r.dst1 != 0 || n != 0):
|
||||
// Make room in dst by copying out, and try again.
|
||||
continue
|
||||
case err == ErrShortSrc && r.src1-r.src0 != len(r.src) && r.err == nil:
|
||||
// Read more bytes into src via the code below, and try again.
|
||||
default:
|
||||
r.transformComplete = true
|
||||
// The reader error (r.err) takes precedence over the
|
||||
// transformer error (err) unless r.err is nil or io.EOF.
|
||||
if r.err == nil || r.err == io.EOF {
|
||||
r.err = err
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Move any untransformed source bytes to the start of the buffer
|
||||
// and read more bytes.
|
||||
if r.src0 != 0 {
|
||||
r.src0, r.src1 = 0, copy(r.src, r.src[r.src0:r.src1])
|
||||
}
|
||||
n, r.err = r.r.Read(r.src[r.src1:])
|
||||
r.src1 += n
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: implement ReadByte (and ReadRune??).
|
||||
|
||||
// Writer wraps another io.Writer by transforming the bytes read.
|
||||
// The user needs to call Close to flush unwritten bytes that may
|
||||
// be buffered.
|
||||
type Writer struct {
|
||||
w io.Writer
|
||||
t Transformer
|
||||
dst []byte
|
||||
|
||||
// src[:n] contains bytes that have not yet passed through t.
|
||||
src []byte
|
||||
n int
|
||||
}
|
||||
|
||||
// NewWriter returns a new Writer that wraps w by transforming the bytes written
|
||||
// via t. It calls Reset on t.
|
||||
func NewWriter(w io.Writer, t Transformer) *Writer {
|
||||
t.Reset()
|
||||
return &Writer{
|
||||
w: w,
|
||||
t: t,
|
||||
dst: make([]byte, defaultBufSize),
|
||||
src: make([]byte, defaultBufSize),
|
||||
}
|
||||
}
|
||||
|
||||
// Write implements the io.Writer interface. If there are not enough
|
||||
// bytes available to complete a Transform, the bytes will be buffered
|
||||
// for the next write. Call Close to convert the remaining bytes.
|
||||
func (w *Writer) Write(data []byte) (n int, err error) {
|
||||
src := data
|
||||
if w.n > 0 {
|
||||
// Append bytes from data to the last remainder.
|
||||
// TODO: limit the amount copied on first try.
|
||||
n = copy(w.src[w.n:], data)
|
||||
w.n += n
|
||||
src = w.src[:w.n]
|
||||
}
|
||||
for {
|
||||
nDst, nSrc, err := w.t.Transform(w.dst, src, false)
|
||||
if _, werr := w.w.Write(w.dst[:nDst]); werr != nil {
|
||||
return n, werr
|
||||
}
|
||||
src = src[nSrc:]
|
||||
if w.n == 0 {
|
||||
n += nSrc
|
||||
} else if len(src) <= n {
|
||||
// Enough bytes from w.src have been consumed. We make src point
|
||||
// to data instead to reduce the copying.
|
||||
w.n = 0
|
||||
n -= len(src)
|
||||
src = data[n:]
|
||||
if n < len(data) && (err == nil || err == ErrShortSrc) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
switch err {
|
||||
case ErrShortDst:
|
||||
// This error is okay as long as we are making progress.
|
||||
if nDst > 0 || nSrc > 0 {
|
||||
continue
|
||||
}
|
||||
case ErrShortSrc:
|
||||
if len(src) < len(w.src) {
|
||||
m := copy(w.src, src)
|
||||
// If w.n > 0, bytes from data were already copied to w.src and n
|
||||
// was already set to the number of bytes consumed.
|
||||
if w.n == 0 {
|
||||
n += m
|
||||
}
|
||||
w.n = m
|
||||
err = nil
|
||||
} else if nDst > 0 || nSrc > 0 {
|
||||
// Not enough buffer to store the remainder. Keep processing as
|
||||
// long as there is progress. Without this case, transforms that
|
||||
// require a lookahead larger than the buffer may result in an
|
||||
// error. This is not something one may expect to be common in
|
||||
// practice, but it may occur when buffers are set to small
|
||||
// sizes during testing.
|
||||
continue
|
||||
}
|
||||
case nil:
|
||||
if w.n > 0 {
|
||||
err = errInconsistentByteCount
|
||||
}
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
|
||||
// Close implements the io.Closer interface.
|
||||
func (w *Writer) Close() error {
|
||||
src := w.src[:w.n]
|
||||
for {
|
||||
nDst, nSrc, err := w.t.Transform(w.dst, src, true)
|
||||
if _, werr := w.w.Write(w.dst[:nDst]); werr != nil {
|
||||
return werr
|
||||
}
|
||||
if err != ErrShortDst {
|
||||
return err
|
||||
}
|
||||
src = src[nSrc:]
|
||||
}
|
||||
}
|
||||
|
||||
type nop struct{ NopResetter }
|
||||
|
||||
func (nop) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
n := copy(dst, src)
|
||||
if n < len(src) {
|
||||
err = ErrShortDst
|
||||
}
|
||||
return n, n, err
|
||||
}
|
||||
|
||||
func (nop) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
return len(src), nil
|
||||
}
|
||||
|
||||
type discard struct{ NopResetter }
|
||||
|
||||
func (discard) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
return 0, len(src), nil
|
||||
}
|
||||
|
||||
var (
|
||||
// Discard is a Transformer for which all Transform calls succeed
|
||||
// by consuming all bytes and writing nothing.
|
||||
Discard Transformer = discard{}
|
||||
|
||||
// Nop is a SpanningTransformer that copies src to dst.
|
||||
Nop SpanningTransformer = nop{}
|
||||
)
|
||||
|
||||
// chain is a sequence of links. A chain with N Transformers has N+1 links and
|
||||
// N+1 buffers. Of those N+1 buffers, the first and last are the src and dst
|
||||
// buffers given to chain.Transform and the middle N-1 buffers are intermediate
|
||||
// buffers owned by the chain. The i'th link transforms bytes from the i'th
|
||||
// buffer chain.link[i].b at read offset chain.link[i].p to the i+1'th buffer
|
||||
// chain.link[i+1].b at write offset chain.link[i+1].n, for i in [0, N).
|
||||
type chain struct {
|
||||
link []link
|
||||
err error
|
||||
// errStart is the index at which the error occurred plus 1. Processing
|
||||
// errStart at this level at the next call to Transform. As long as
|
||||
// errStart > 0, chain will not consume any more source bytes.
|
||||
errStart int
|
||||
}
|
||||
|
||||
func (c *chain) fatalError(errIndex int, err error) {
|
||||
if i := errIndex + 1; i > c.errStart {
|
||||
c.errStart = i
|
||||
c.err = err
|
||||
}
|
||||
}
|
||||
|
||||
type link struct {
|
||||
t Transformer
|
||||
// b[p:n] holds the bytes to be transformed by t.
|
||||
b []byte
|
||||
p int
|
||||
n int
|
||||
}
|
||||
|
||||
func (l *link) src() []byte {
|
||||
return l.b[l.p:l.n]
|
||||
}
|
||||
|
||||
func (l *link) dst() []byte {
|
||||
return l.b[l.n:]
|
||||
}
|
||||
|
||||
// Chain returns a Transformer that applies t in sequence.
|
||||
func Chain(t ...Transformer) Transformer {
|
||||
if len(t) == 0 {
|
||||
return nop{}
|
||||
}
|
||||
c := &chain{link: make([]link, len(t)+1)}
|
||||
for i, tt := range t {
|
||||
c.link[i].t = tt
|
||||
}
|
||||
// Allocate intermediate buffers.
|
||||
b := make([][defaultBufSize]byte, len(t)-1)
|
||||
for i := range b {
|
||||
c.link[i+1].b = b[i][:]
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// Reset resets the state of Chain. It calls Reset on all the Transformers.
|
||||
func (c *chain) Reset() {
|
||||
for i, l := range c.link {
|
||||
if l.t != nil {
|
||||
l.t.Reset()
|
||||
}
|
||||
c.link[i].p, c.link[i].n = 0, 0
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: make chain use Span (is going to be fun to implement!)
|
||||
|
||||
// Transform applies the transformers of c in sequence.
|
||||
func (c *chain) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
// Set up src and dst in the chain.
|
||||
srcL := &c.link[0]
|
||||
dstL := &c.link[len(c.link)-1]
|
||||
srcL.b, srcL.p, srcL.n = src, 0, len(src)
|
||||
dstL.b, dstL.n = dst, 0
|
||||
var lastFull, needProgress bool // for detecting progress
|
||||
|
||||
// i is the index of the next Transformer to apply, for i in [low, high].
|
||||
// low is the lowest index for which c.link[low] may still produce bytes.
|
||||
// high is the highest index for which c.link[high] has a Transformer.
|
||||
// The error returned by Transform determines whether to increase or
|
||||
// decrease i. We try to completely fill a buffer before converting it.
|
||||
for low, i, high := c.errStart, c.errStart, len(c.link)-2; low <= i && i <= high; {
|
||||
in, out := &c.link[i], &c.link[i+1]
|
||||
nDst, nSrc, err0 := in.t.Transform(out.dst(), in.src(), atEOF && low == i)
|
||||
out.n += nDst
|
||||
in.p += nSrc
|
||||
if i > 0 && in.p == in.n {
|
||||
in.p, in.n = 0, 0
|
||||
}
|
||||
needProgress, lastFull = lastFull, false
|
||||
switch err0 {
|
||||
case ErrShortDst:
|
||||
// Process the destination buffer next. Return if we are already
|
||||
// at the high index.
|
||||
if i == high {
|
||||
return dstL.n, srcL.p, ErrShortDst
|
||||
}
|
||||
if out.n != 0 {
|
||||
i++
|
||||
// If the Transformer at the next index is not able to process any
|
||||
// source bytes there is nothing that can be done to make progress
|
||||
// and the bytes will remain unprocessed. lastFull is used to
|
||||
// detect this and break out of the loop with a fatal error.
|
||||
lastFull = true
|
||||
continue
|
||||
}
|
||||
// The destination buffer was too small, but is completely empty.
|
||||
// Return a fatal error as this transformation can never complete.
|
||||
c.fatalError(i, errShortInternal)
|
||||
case ErrShortSrc:
|
||||
if i == 0 {
|
||||
// Save ErrShortSrc in err. All other errors take precedence.
|
||||
err = ErrShortSrc
|
||||
break
|
||||
}
|
||||
// Source bytes were depleted before filling up the destination buffer.
|
||||
// Verify we made some progress, move the remaining bytes to the errStart
|
||||
// and try to get more source bytes.
|
||||
if needProgress && nSrc == 0 || in.n-in.p == len(in.b) {
|
||||
// There were not enough source bytes to proceed while the source
|
||||
// buffer cannot hold any more bytes. Return a fatal error as this
|
||||
// transformation can never complete.
|
||||
c.fatalError(i, errShortInternal)
|
||||
break
|
||||
}
|
||||
// in.b is an internal buffer and we can make progress.
|
||||
in.p, in.n = 0, copy(in.b, in.src())
|
||||
fallthrough
|
||||
case nil:
|
||||
// if i == low, we have depleted the bytes at index i or any lower levels.
|
||||
// In that case we increase low and i. In all other cases we decrease i to
|
||||
// fetch more bytes before proceeding to the next index.
|
||||
if i > low {
|
||||
i--
|
||||
continue
|
||||
}
|
||||
default:
|
||||
c.fatalError(i, err0)
|
||||
}
|
||||
// Exhausted level low or fatal error: increase low and continue
|
||||
// to process the bytes accepted so far.
|
||||
i++
|
||||
low = i
|
||||
}
|
||||
|
||||
// If c.errStart > 0, this means we found a fatal error. We will clear
|
||||
// all upstream buffers. At this point, no more progress can be made
|
||||
// downstream, as Transform would have bailed while handling ErrShortDst.
|
||||
if c.errStart > 0 {
|
||||
for i := 1; i < c.errStart; i++ {
|
||||
c.link[i].p, c.link[i].n = 0, 0
|
||||
}
|
||||
err, c.errStart, c.err = c.err, 0, nil
|
||||
}
|
||||
return dstL.n, srcL.p, err
|
||||
}
|
||||
|
||||
// Deprecated: Use runes.Remove instead.
|
||||
func RemoveFunc(f func(r rune) bool) Transformer {
|
||||
return removeF(f)
|
||||
}
|
||||
|
||||
type removeF func(r rune) bool
|
||||
|
||||
func (removeF) Reset() {}
|
||||
|
||||
// Transform implements the Transformer interface.
|
||||
func (t removeF) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
for r, sz := rune(0), 0; len(src) > 0; src = src[sz:] {
|
||||
|
||||
if r = rune(src[0]); r < utf8.RuneSelf {
|
||||
sz = 1
|
||||
} else {
|
||||
r, sz = utf8.DecodeRune(src)
|
||||
|
||||
if sz == 1 {
|
||||
// Invalid rune.
|
||||
if !atEOF && !utf8.FullRune(src) {
|
||||
err = ErrShortSrc
|
||||
break
|
||||
}
|
||||
// We replace illegal bytes with RuneError. Not doing so might
|
||||
// otherwise turn a sequence of invalid UTF-8 into valid UTF-8.
|
||||
// The resulting byte sequence may subsequently contain runes
|
||||
// for which t(r) is true that were passed unnoticed.
|
||||
if !t(r) {
|
||||
if nDst+3 > len(dst) {
|
||||
err = ErrShortDst
|
||||
break
|
||||
}
|
||||
nDst += copy(dst[nDst:], "\uFFFD")
|
||||
}
|
||||
nSrc++
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if !t(r) {
|
||||
if nDst+sz > len(dst) {
|
||||
err = ErrShortDst
|
||||
break
|
||||
}
|
||||
nDst += copy(dst[nDst:], src[:sz])
|
||||
}
|
||||
nSrc += sz
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// grow returns a new []byte that is longer than b, and copies the first n bytes
|
||||
// of b to the start of the new slice.
|
||||
func grow(b []byte, n int) []byte {
|
||||
m := len(b)
|
||||
if m <= 32 {
|
||||
m = 64
|
||||
} else if m <= 256 {
|
||||
m *= 2
|
||||
} else {
|
||||
m += m >> 1
|
||||
}
|
||||
buf := make([]byte, m)
|
||||
copy(buf, b[:n])
|
||||
return buf
|
||||
}
|
||||
|
||||
const initialBufSize = 128
|
||||
|
||||
// String returns a string with the result of converting s[:n] using t, where
|
||||
// n <= len(s). If err == nil, n will be len(s). It calls Reset on t.
|
||||
func String(t Transformer, s string) (result string, n int, err error) {
|
||||
t.Reset()
|
||||
if s == "" {
|
||||
// Fast path for the common case for empty input. Results in about a
|
||||
// 86% reduction of running time for BenchmarkStringLowerEmpty.
|
||||
if _, _, err := t.Transform(nil, nil, true); err == nil {
|
||||
return "", 0, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate only once. Note that both dst and src escape when passed to
|
||||
// Transform.
|
||||
buf := [2 * initialBufSize]byte{}
|
||||
dst := buf[:initialBufSize:initialBufSize]
|
||||
src := buf[initialBufSize : 2*initialBufSize]
|
||||
|
||||
// The input string s is transformed in multiple chunks (starting with a
|
||||
// chunk size of initialBufSize). nDst and nSrc are per-chunk (or
|
||||
// per-Transform-call) indexes, pDst and pSrc are overall indexes.
|
||||
nDst, nSrc := 0, 0
|
||||
pDst, pSrc := 0, 0
|
||||
|
||||
// pPrefix is the length of a common prefix: the first pPrefix bytes of the
|
||||
// result will equal the first pPrefix bytes of s. It is not guaranteed to
|
||||
// be the largest such value, but if pPrefix, len(result) and len(s) are
|
||||
// all equal after the final transform (i.e. calling Transform with atEOF
|
||||
// being true returned nil error) then we don't need to allocate a new
|
||||
// result string.
|
||||
pPrefix := 0
|
||||
for {
|
||||
// Invariant: pDst == pPrefix && pSrc == pPrefix.
|
||||
|
||||
n := copy(src, s[pSrc:])
|
||||
nDst, nSrc, err = t.Transform(dst, src[:n], pSrc+n == len(s))
|
||||
pDst += nDst
|
||||
pSrc += nSrc
|
||||
|
||||
// TODO: let transformers implement an optional Spanner interface, akin
|
||||
// to norm's QuickSpan. This would even allow us to avoid any allocation.
|
||||
if !bytes.Equal(dst[:nDst], src[:nSrc]) {
|
||||
break
|
||||
}
|
||||
pPrefix = pSrc
|
||||
if err == ErrShortDst {
|
||||
// A buffer can only be short if a transformer modifies its input.
|
||||
break
|
||||
} else if err == ErrShortSrc {
|
||||
if nSrc == 0 {
|
||||
// No progress was made.
|
||||
break
|
||||
}
|
||||
// Equal so far and !atEOF, so continue checking.
|
||||
} else if err != nil || pPrefix == len(s) {
|
||||
return string(s[:pPrefix]), pPrefix, err
|
||||
}
|
||||
}
|
||||
// Post-condition: pDst == pPrefix + nDst && pSrc == pPrefix + nSrc.
|
||||
|
||||
// We have transformed the first pSrc bytes of the input s to become pDst
|
||||
// transformed bytes. Those transformed bytes are discontiguous: the first
|
||||
// pPrefix of them equal s[:pPrefix] and the last nDst of them equal
|
||||
// dst[:nDst]. We copy them around, into a new dst buffer if necessary, so
|
||||
// that they become one contiguous slice: dst[:pDst].
|
||||
if pPrefix != 0 {
|
||||
newDst := dst
|
||||
if pDst > len(newDst) {
|
||||
newDst = make([]byte, len(s)+nDst-nSrc)
|
||||
}
|
||||
copy(newDst[pPrefix:pDst], dst[:nDst])
|
||||
copy(newDst[:pPrefix], s[:pPrefix])
|
||||
dst = newDst
|
||||
}
|
||||
|
||||
// Prevent duplicate Transform calls with atEOF being true at the end of
|
||||
// the input. Also return if we have an unrecoverable error.
|
||||
if (err == nil && pSrc == len(s)) ||
|
||||
(err != nil && err != ErrShortDst && err != ErrShortSrc) {
|
||||
return string(dst[:pDst]), pSrc, err
|
||||
}
|
||||
|
||||
// Transform the remaining input, growing dst and src buffers as necessary.
|
||||
for {
|
||||
n := copy(src, s[pSrc:])
|
||||
atEOF := pSrc+n == len(s)
|
||||
nDst, nSrc, err := t.Transform(dst[pDst:], src[:n], atEOF)
|
||||
pDst += nDst
|
||||
pSrc += nSrc
|
||||
|
||||
// If we got ErrShortDst or ErrShortSrc, do not grow as long as we can
|
||||
// make progress. This may avoid excessive allocations.
|
||||
if err == ErrShortDst {
|
||||
if nDst == 0 {
|
||||
dst = grow(dst, pDst)
|
||||
}
|
||||
} else if err == ErrShortSrc {
|
||||
if atEOF {
|
||||
return string(dst[:pDst]), pSrc, err
|
||||
}
|
||||
if nSrc == 0 {
|
||||
src = grow(src, 0)
|
||||
}
|
||||
} else if err != nil || pSrc == len(s) {
|
||||
return string(dst[:pDst]), pSrc, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bytes returns a new byte slice with the result of converting b[:n] using t,
|
||||
// where n <= len(b). If err == nil, n will be len(b). It calls Reset on t.
|
||||
func Bytes(t Transformer, b []byte) (result []byte, n int, err error) {
|
||||
return doAppend(t, 0, make([]byte, len(b)), b)
|
||||
}
|
||||
|
||||
// Append appends the result of converting src[:n] using t to dst, where
|
||||
// n <= len(src), If err == nil, n will be len(src). It calls Reset on t.
|
||||
func Append(t Transformer, dst, src []byte) (result []byte, n int, err error) {
|
||||
if len(dst) == cap(dst) {
|
||||
n := len(src) + len(dst) // It is okay for this to be 0.
|
||||
b := make([]byte, n)
|
||||
dst = b[:copy(b, dst)]
|
||||
}
|
||||
return doAppend(t, len(dst), dst[:cap(dst)], src)
|
||||
}
|
||||
|
||||
func doAppend(t Transformer, pDst int, dst, src []byte) (result []byte, n int, err error) {
|
||||
t.Reset()
|
||||
pSrc := 0
|
||||
for {
|
||||
nDst, nSrc, err := t.Transform(dst[pDst:], src[pSrc:], true)
|
||||
pDst += nDst
|
||||
pSrc += nSrc
|
||||
if err != ErrShortDst {
|
||||
return dst[:pDst], pSrc, err
|
||||
}
|
||||
|
||||
// Grow the destination buffer, but do not grow as long as we can make
|
||||
// progress. This may avoid excessive allocations.
|
||||
if nDst == 0 {
|
||||
dst = grow(dst, pDst)
|
||||
}
|
||||
}
|
||||
}
|
||||
512
vendor/golang.org/x/text/unicode/norm/composition.go
generated
vendored
Normal file
512
vendor/golang.org/x/text/unicode/norm/composition.go
generated
vendored
Normal file
@@ -0,0 +1,512 @@
|
||||
// Copyright 2011 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 norm
|
||||
|
||||
import "unicode/utf8"
|
||||
|
||||
const (
|
||||
maxNonStarters = 30
|
||||
// The maximum number of characters needed for a buffer is
|
||||
// maxNonStarters + 1 for the starter + 1 for the GCJ
|
||||
maxBufferSize = maxNonStarters + 2
|
||||
maxNFCExpansion = 3 // NFC(0x1D160)
|
||||
maxNFKCExpansion = 18 // NFKC(0xFDFA)
|
||||
|
||||
maxByteBufferSize = utf8.UTFMax * maxBufferSize // 128
|
||||
)
|
||||
|
||||
// ssState is used for reporting the segment state after inserting a rune.
|
||||
// It is returned by streamSafe.next.
|
||||
type ssState int
|
||||
|
||||
const (
|
||||
// Indicates a rune was successfully added to the segment.
|
||||
ssSuccess ssState = iota
|
||||
// Indicates a rune starts a new segment and should not be added.
|
||||
ssStarter
|
||||
// Indicates a rune caused a segment overflow and a CGJ should be inserted.
|
||||
ssOverflow
|
||||
)
|
||||
|
||||
// streamSafe implements the policy of when a CGJ should be inserted.
|
||||
type streamSafe uint8
|
||||
|
||||
// first inserts the first rune of a segment. It is a faster version of next if
|
||||
// it is known p represents the first rune in a segment.
|
||||
func (ss *streamSafe) first(p Properties) {
|
||||
*ss = streamSafe(p.nTrailingNonStarters())
|
||||
}
|
||||
|
||||
// insert returns a ssState value to indicate whether a rune represented by p
|
||||
// can be inserted.
|
||||
func (ss *streamSafe) next(p Properties) ssState {
|
||||
if *ss > maxNonStarters {
|
||||
panic("streamSafe was not reset")
|
||||
}
|
||||
n := p.nLeadingNonStarters()
|
||||
if *ss += streamSafe(n); *ss > maxNonStarters {
|
||||
*ss = 0
|
||||
return ssOverflow
|
||||
}
|
||||
// The Stream-Safe Text Processing prescribes that the counting can stop
|
||||
// as soon as a starter is encountered. However, there are some starters,
|
||||
// like Jamo V and T, that can combine with other runes, leaving their
|
||||
// successive non-starters appended to the previous, possibly causing an
|
||||
// overflow. We will therefore consider any rune with a non-zero nLead to
|
||||
// be a non-starter. Note that it always hold that if nLead > 0 then
|
||||
// nLead == nTrail.
|
||||
if n == 0 {
|
||||
*ss = streamSafe(p.nTrailingNonStarters())
|
||||
return ssStarter
|
||||
}
|
||||
return ssSuccess
|
||||
}
|
||||
|
||||
// backwards is used for checking for overflow and segment starts
|
||||
// when traversing a string backwards. Users do not need to call first
|
||||
// for the first rune. The state of the streamSafe retains the count of
|
||||
// the non-starters loaded.
|
||||
func (ss *streamSafe) backwards(p Properties) ssState {
|
||||
if *ss > maxNonStarters {
|
||||
panic("streamSafe was not reset")
|
||||
}
|
||||
c := *ss + streamSafe(p.nTrailingNonStarters())
|
||||
if c > maxNonStarters {
|
||||
return ssOverflow
|
||||
}
|
||||
*ss = c
|
||||
if p.nLeadingNonStarters() == 0 {
|
||||
return ssStarter
|
||||
}
|
||||
return ssSuccess
|
||||
}
|
||||
|
||||
func (ss streamSafe) isMax() bool {
|
||||
return ss == maxNonStarters
|
||||
}
|
||||
|
||||
// GraphemeJoiner is inserted after maxNonStarters non-starter runes.
|
||||
const GraphemeJoiner = "\u034F"
|
||||
|
||||
// reorderBuffer is used to normalize a single segment. Characters inserted with
|
||||
// insert are decomposed and reordered based on CCC. The compose method can
|
||||
// be used to recombine characters. Note that the byte buffer does not hold
|
||||
// the UTF-8 characters in order. Only the rune array is maintained in sorted
|
||||
// order. flush writes the resulting segment to a byte array.
|
||||
type reorderBuffer struct {
|
||||
rune [maxBufferSize]Properties // Per character info.
|
||||
byte [maxByteBufferSize]byte // UTF-8 buffer. Referenced by runeInfo.pos.
|
||||
nbyte uint8 // Number or bytes.
|
||||
ss streamSafe // For limiting length of non-starter sequence.
|
||||
nrune int // Number of runeInfos.
|
||||
f formInfo
|
||||
|
||||
src input
|
||||
nsrc int
|
||||
tmpBytes input
|
||||
|
||||
out []byte
|
||||
flushF func(*reorderBuffer) bool
|
||||
}
|
||||
|
||||
func (rb *reorderBuffer) init(f Form, src []byte) {
|
||||
rb.f = *formTable[f]
|
||||
rb.src.setBytes(src)
|
||||
rb.nsrc = len(src)
|
||||
rb.ss = 0
|
||||
}
|
||||
|
||||
func (rb *reorderBuffer) initString(f Form, src string) {
|
||||
rb.f = *formTable[f]
|
||||
rb.src.setString(src)
|
||||
rb.nsrc = len(src)
|
||||
rb.ss = 0
|
||||
}
|
||||
|
||||
func (rb *reorderBuffer) setFlusher(out []byte, f func(*reorderBuffer) bool) {
|
||||
rb.out = out
|
||||
rb.flushF = f
|
||||
}
|
||||
|
||||
// reset discards all characters from the buffer.
|
||||
func (rb *reorderBuffer) reset() {
|
||||
rb.nrune = 0
|
||||
rb.nbyte = 0
|
||||
}
|
||||
|
||||
func (rb *reorderBuffer) doFlush() bool {
|
||||
if rb.f.composing {
|
||||
rb.compose()
|
||||
}
|
||||
res := rb.flushF(rb)
|
||||
rb.reset()
|
||||
return res
|
||||
}
|
||||
|
||||
// appendFlush appends the normalized segment to rb.out.
|
||||
func appendFlush(rb *reorderBuffer) bool {
|
||||
for i := 0; i < rb.nrune; i++ {
|
||||
start := rb.rune[i].pos
|
||||
end := start + rb.rune[i].size
|
||||
rb.out = append(rb.out, rb.byte[start:end]...)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// flush appends the normalized segment to out and resets rb.
|
||||
func (rb *reorderBuffer) flush(out []byte) []byte {
|
||||
for i := 0; i < rb.nrune; i++ {
|
||||
start := rb.rune[i].pos
|
||||
end := start + rb.rune[i].size
|
||||
out = append(out, rb.byte[start:end]...)
|
||||
}
|
||||
rb.reset()
|
||||
return out
|
||||
}
|
||||
|
||||
// flushCopy copies the normalized segment to buf and resets rb.
|
||||
// It returns the number of bytes written to buf.
|
||||
func (rb *reorderBuffer) flushCopy(buf []byte) int {
|
||||
p := 0
|
||||
for i := 0; i < rb.nrune; i++ {
|
||||
runep := rb.rune[i]
|
||||
p += copy(buf[p:], rb.byte[runep.pos:runep.pos+runep.size])
|
||||
}
|
||||
rb.reset()
|
||||
return p
|
||||
}
|
||||
|
||||
// insertOrdered inserts a rune in the buffer, ordered by Canonical Combining Class.
|
||||
// It returns false if the buffer is not large enough to hold the rune.
|
||||
// It is used internally by insert and insertString only.
|
||||
func (rb *reorderBuffer) insertOrdered(info Properties) {
|
||||
n := rb.nrune
|
||||
b := rb.rune[:]
|
||||
cc := info.ccc
|
||||
if cc > 0 {
|
||||
// Find insertion position + move elements to make room.
|
||||
for ; n > 0; n-- {
|
||||
if b[n-1].ccc <= cc {
|
||||
break
|
||||
}
|
||||
b[n] = b[n-1]
|
||||
}
|
||||
}
|
||||
rb.nrune += 1
|
||||
pos := uint8(rb.nbyte)
|
||||
rb.nbyte += utf8.UTFMax
|
||||
info.pos = pos
|
||||
b[n] = info
|
||||
}
|
||||
|
||||
// insertErr is an error code returned by insert. Using this type instead
|
||||
// of error improves performance up to 20% for many of the benchmarks.
|
||||
type insertErr int
|
||||
|
||||
const (
|
||||
iSuccess insertErr = -iota
|
||||
iShortDst
|
||||
iShortSrc
|
||||
)
|
||||
|
||||
// insertFlush inserts the given rune in the buffer ordered by CCC.
|
||||
// If a decomposition with multiple segments are encountered, they leading
|
||||
// ones are flushed.
|
||||
// It returns a non-zero error code if the rune was not inserted.
|
||||
func (rb *reorderBuffer) insertFlush(src input, i int, info Properties) insertErr {
|
||||
if rune := src.hangul(i); rune != 0 {
|
||||
rb.decomposeHangul(rune)
|
||||
return iSuccess
|
||||
}
|
||||
if info.hasDecomposition() {
|
||||
return rb.insertDecomposed(info.Decomposition())
|
||||
}
|
||||
rb.insertSingle(src, i, info)
|
||||
return iSuccess
|
||||
}
|
||||
|
||||
// insertUnsafe inserts the given rune in the buffer ordered by CCC.
|
||||
// It is assumed there is sufficient space to hold the runes. It is the
|
||||
// responsibility of the caller to ensure this. This can be done by checking
|
||||
// the state returned by the streamSafe type.
|
||||
func (rb *reorderBuffer) insertUnsafe(src input, i int, info Properties) {
|
||||
if rune := src.hangul(i); rune != 0 {
|
||||
rb.decomposeHangul(rune)
|
||||
}
|
||||
if info.hasDecomposition() {
|
||||
// TODO: inline.
|
||||
rb.insertDecomposed(info.Decomposition())
|
||||
} else {
|
||||
rb.insertSingle(src, i, info)
|
||||
}
|
||||
}
|
||||
|
||||
// insertDecomposed inserts an entry in to the reorderBuffer for each rune
|
||||
// in dcomp. dcomp must be a sequence of decomposed UTF-8-encoded runes.
|
||||
// It flushes the buffer on each new segment start.
|
||||
func (rb *reorderBuffer) insertDecomposed(dcomp []byte) insertErr {
|
||||
rb.tmpBytes.setBytes(dcomp)
|
||||
// As the streamSafe accounting already handles the counting for modifiers,
|
||||
// we don't have to call next. However, we do need to keep the accounting
|
||||
// intact when flushing the buffer.
|
||||
for i := 0; i < len(dcomp); {
|
||||
info := rb.f.info(rb.tmpBytes, i)
|
||||
if info.BoundaryBefore() && rb.nrune > 0 && !rb.doFlush() {
|
||||
return iShortDst
|
||||
}
|
||||
i += copy(rb.byte[rb.nbyte:], dcomp[i:i+int(info.size)])
|
||||
rb.insertOrdered(info)
|
||||
}
|
||||
return iSuccess
|
||||
}
|
||||
|
||||
// insertSingle inserts an entry in the reorderBuffer for the rune at
|
||||
// position i. info is the runeInfo for the rune at position i.
|
||||
func (rb *reorderBuffer) insertSingle(src input, i int, info Properties) {
|
||||
src.copySlice(rb.byte[rb.nbyte:], i, i+int(info.size))
|
||||
rb.insertOrdered(info)
|
||||
}
|
||||
|
||||
// insertCGJ inserts a Combining Grapheme Joiner (0x034f) into rb.
|
||||
func (rb *reorderBuffer) insertCGJ() {
|
||||
rb.insertSingle(input{str: GraphemeJoiner}, 0, Properties{size: uint8(len(GraphemeJoiner))})
|
||||
}
|
||||
|
||||
// appendRune inserts a rune at the end of the buffer. It is used for Hangul.
|
||||
func (rb *reorderBuffer) appendRune(r rune) {
|
||||
bn := rb.nbyte
|
||||
sz := utf8.EncodeRune(rb.byte[bn:], rune(r))
|
||||
rb.nbyte += utf8.UTFMax
|
||||
rb.rune[rb.nrune] = Properties{pos: bn, size: uint8(sz)}
|
||||
rb.nrune++
|
||||
}
|
||||
|
||||
// assignRune sets a rune at position pos. It is used for Hangul and recomposition.
|
||||
func (rb *reorderBuffer) assignRune(pos int, r rune) {
|
||||
bn := rb.rune[pos].pos
|
||||
sz := utf8.EncodeRune(rb.byte[bn:], rune(r))
|
||||
rb.rune[pos] = Properties{pos: bn, size: uint8(sz)}
|
||||
}
|
||||
|
||||
// runeAt returns the rune at position n. It is used for Hangul and recomposition.
|
||||
func (rb *reorderBuffer) runeAt(n int) rune {
|
||||
inf := rb.rune[n]
|
||||
r, _ := utf8.DecodeRune(rb.byte[inf.pos : inf.pos+inf.size])
|
||||
return r
|
||||
}
|
||||
|
||||
// bytesAt returns the UTF-8 encoding of the rune at position n.
|
||||
// It is used for Hangul and recomposition.
|
||||
func (rb *reorderBuffer) bytesAt(n int) []byte {
|
||||
inf := rb.rune[n]
|
||||
return rb.byte[inf.pos : int(inf.pos)+int(inf.size)]
|
||||
}
|
||||
|
||||
// For Hangul we combine algorithmically, instead of using tables.
|
||||
const (
|
||||
hangulBase = 0xAC00 // UTF-8(hangulBase) -> EA B0 80
|
||||
hangulBase0 = 0xEA
|
||||
hangulBase1 = 0xB0
|
||||
hangulBase2 = 0x80
|
||||
|
||||
hangulEnd = hangulBase + jamoLVTCount // UTF-8(0xD7A4) -> ED 9E A4
|
||||
hangulEnd0 = 0xED
|
||||
hangulEnd1 = 0x9E
|
||||
hangulEnd2 = 0xA4
|
||||
|
||||
jamoLBase = 0x1100 // UTF-8(jamoLBase) -> E1 84 00
|
||||
jamoLBase0 = 0xE1
|
||||
jamoLBase1 = 0x84
|
||||
jamoLEnd = 0x1113
|
||||
jamoVBase = 0x1161
|
||||
jamoVEnd = 0x1176
|
||||
jamoTBase = 0x11A7
|
||||
jamoTEnd = 0x11C3
|
||||
|
||||
jamoTCount = 28
|
||||
jamoVCount = 21
|
||||
jamoVTCount = 21 * 28
|
||||
jamoLVTCount = 19 * 21 * 28
|
||||
)
|
||||
|
||||
const hangulUTF8Size = 3
|
||||
|
||||
func isHangul(b []byte) bool {
|
||||
if len(b) < hangulUTF8Size {
|
||||
return false
|
||||
}
|
||||
b0 := b[0]
|
||||
if b0 < hangulBase0 {
|
||||
return false
|
||||
}
|
||||
b1 := b[1]
|
||||
switch {
|
||||
case b0 == hangulBase0:
|
||||
return b1 >= hangulBase1
|
||||
case b0 < hangulEnd0:
|
||||
return true
|
||||
case b0 > hangulEnd0:
|
||||
return false
|
||||
case b1 < hangulEnd1:
|
||||
return true
|
||||
}
|
||||
return b1 == hangulEnd1 && b[2] < hangulEnd2
|
||||
}
|
||||
|
||||
func isHangulString(b string) bool {
|
||||
if len(b) < hangulUTF8Size {
|
||||
return false
|
||||
}
|
||||
b0 := b[0]
|
||||
if b0 < hangulBase0 {
|
||||
return false
|
||||
}
|
||||
b1 := b[1]
|
||||
switch {
|
||||
case b0 == hangulBase0:
|
||||
return b1 >= hangulBase1
|
||||
case b0 < hangulEnd0:
|
||||
return true
|
||||
case b0 > hangulEnd0:
|
||||
return false
|
||||
case b1 < hangulEnd1:
|
||||
return true
|
||||
}
|
||||
return b1 == hangulEnd1 && b[2] < hangulEnd2
|
||||
}
|
||||
|
||||
// Caller must ensure len(b) >= 2.
|
||||
func isJamoVT(b []byte) bool {
|
||||
// True if (rune & 0xff00) == jamoLBase
|
||||
return b[0] == jamoLBase0 && (b[1]&0xFC) == jamoLBase1
|
||||
}
|
||||
|
||||
func isHangulWithoutJamoT(b []byte) bool {
|
||||
c, _ := utf8.DecodeRune(b)
|
||||
c -= hangulBase
|
||||
return c < jamoLVTCount && c%jamoTCount == 0
|
||||
}
|
||||
|
||||
// decomposeHangul writes the decomposed Hangul to buf and returns the number
|
||||
// of bytes written. len(buf) should be at least 9.
|
||||
func decomposeHangul(buf []byte, r rune) int {
|
||||
const JamoUTF8Len = 3
|
||||
r -= hangulBase
|
||||
x := r % jamoTCount
|
||||
r /= jamoTCount
|
||||
utf8.EncodeRune(buf, jamoLBase+r/jamoVCount)
|
||||
utf8.EncodeRune(buf[JamoUTF8Len:], jamoVBase+r%jamoVCount)
|
||||
if x != 0 {
|
||||
utf8.EncodeRune(buf[2*JamoUTF8Len:], jamoTBase+x)
|
||||
return 3 * JamoUTF8Len
|
||||
}
|
||||
return 2 * JamoUTF8Len
|
||||
}
|
||||
|
||||
// decomposeHangul algorithmically decomposes a Hangul rune into
|
||||
// its Jamo components.
|
||||
// See https://unicode.org/reports/tr15/#Hangul for details on decomposing Hangul.
|
||||
func (rb *reorderBuffer) decomposeHangul(r rune) {
|
||||
r -= hangulBase
|
||||
x := r % jamoTCount
|
||||
r /= jamoTCount
|
||||
rb.appendRune(jamoLBase + r/jamoVCount)
|
||||
rb.appendRune(jamoVBase + r%jamoVCount)
|
||||
if x != 0 {
|
||||
rb.appendRune(jamoTBase + x)
|
||||
}
|
||||
}
|
||||
|
||||
// combineHangul algorithmically combines Jamo character components into Hangul.
|
||||
// See https://unicode.org/reports/tr15/#Hangul for details on combining Hangul.
|
||||
func (rb *reorderBuffer) combineHangul(s, i, k int) {
|
||||
b := rb.rune[:]
|
||||
bn := rb.nrune
|
||||
for ; i < bn; i++ {
|
||||
cccB := b[k-1].ccc
|
||||
cccC := b[i].ccc
|
||||
if cccB == 0 {
|
||||
s = k - 1
|
||||
}
|
||||
if s != k-1 && cccB >= cccC {
|
||||
// b[i] is blocked by greater-equal cccX below it
|
||||
b[k] = b[i]
|
||||
k++
|
||||
} else {
|
||||
l := rb.runeAt(s) // also used to compare to hangulBase
|
||||
v := rb.runeAt(i) // also used to compare to jamoT
|
||||
switch {
|
||||
case jamoLBase <= l && l < jamoLEnd &&
|
||||
jamoVBase <= v && v < jamoVEnd:
|
||||
// 11xx plus 116x to LV
|
||||
rb.assignRune(s, hangulBase+
|
||||
(l-jamoLBase)*jamoVTCount+(v-jamoVBase)*jamoTCount)
|
||||
case hangulBase <= l && l < hangulEnd &&
|
||||
jamoTBase < v && v < jamoTEnd &&
|
||||
((l-hangulBase)%jamoTCount) == 0:
|
||||
// ACxx plus 11Ax to LVT
|
||||
rb.assignRune(s, l+v-jamoTBase)
|
||||
default:
|
||||
b[k] = b[i]
|
||||
k++
|
||||
}
|
||||
}
|
||||
}
|
||||
rb.nrune = k
|
||||
}
|
||||
|
||||
// compose recombines the runes in the buffer.
|
||||
// It should only be used to recompose a single segment, as it will not
|
||||
// handle alternations between Hangul and non-Hangul characters correctly.
|
||||
func (rb *reorderBuffer) compose() {
|
||||
// Lazily load the map used by the combine func below, but do
|
||||
// it outside of the loop.
|
||||
recompMapOnce.Do(buildRecompMap)
|
||||
|
||||
// UAX #15, section X5 , including Corrigendum #5
|
||||
// "In any character sequence beginning with starter S, a character C is
|
||||
// blocked from S if and only if there is some character B between S
|
||||
// and C, and either B is a starter or it has the same or higher
|
||||
// combining class as C."
|
||||
bn := rb.nrune
|
||||
if bn == 0 {
|
||||
return
|
||||
}
|
||||
k := 1
|
||||
b := rb.rune[:]
|
||||
for s, i := 0, 1; i < bn; i++ {
|
||||
if isJamoVT(rb.bytesAt(i)) {
|
||||
// Redo from start in Hangul mode. Necessary to support
|
||||
// U+320E..U+321E in NFKC mode.
|
||||
rb.combineHangul(s, i, k)
|
||||
return
|
||||
}
|
||||
ii := b[i]
|
||||
// We can only use combineForward as a filter if we later
|
||||
// get the info for the combined character. This is more
|
||||
// expensive than using the filter. Using combinesBackward()
|
||||
// is safe.
|
||||
if ii.combinesBackward() {
|
||||
cccB := b[k-1].ccc
|
||||
cccC := ii.ccc
|
||||
blocked := false // b[i] blocked by starter or greater or equal CCC?
|
||||
if cccB == 0 {
|
||||
s = k - 1
|
||||
} else {
|
||||
blocked = s != k-1 && cccB >= cccC
|
||||
}
|
||||
if !blocked {
|
||||
combined := combine(rb.runeAt(s), rb.runeAt(i))
|
||||
if combined != 0 {
|
||||
rb.assignRune(s, combined)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
b[k] = b[i]
|
||||
k++
|
||||
}
|
||||
rb.nrune = k
|
||||
}
|
||||
278
vendor/golang.org/x/text/unicode/norm/forminfo.go
generated
vendored
Normal file
278
vendor/golang.org/x/text/unicode/norm/forminfo.go
generated
vendored
Normal file
@@ -0,0 +1,278 @@
|
||||
// Copyright 2011 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 norm
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
// This file contains Form-specific logic and wrappers for data in tables.go.
|
||||
|
||||
// Rune info is stored in a separate trie per composing form. A composing form
|
||||
// and its corresponding decomposing form share the same trie. Each trie maps
|
||||
// a rune to a uint16. The values take two forms. For v >= 0x8000:
|
||||
// bits
|
||||
// 15: 1 (inverse of NFD_QC bit of qcInfo)
|
||||
// 13..7: qcInfo (see below). isYesD is always true (no decompostion).
|
||||
// 6..0: ccc (compressed CCC value).
|
||||
// For v < 0x8000, the respective rune has a decomposition and v is an index
|
||||
// into a byte array of UTF-8 decomposition sequences and additional info and
|
||||
// has the form:
|
||||
// <header> <decomp_byte>* [<tccc> [<lccc>]]
|
||||
// The header contains the number of bytes in the decomposition (excluding this
|
||||
// length byte). The two most significant bits of this length byte correspond
|
||||
// to bit 5 and 4 of qcInfo (see below). The byte sequence itself starts at v+1.
|
||||
// The byte sequence is followed by a trailing and leading CCC if the values
|
||||
// for these are not zero. The value of v determines which ccc are appended
|
||||
// to the sequences. For v < firstCCC, there are none, for v >= firstCCC,
|
||||
// the sequence is followed by a trailing ccc, and for v >= firstLeadingCC
|
||||
// there is an additional leading ccc. The value of tccc itself is the
|
||||
// trailing CCC shifted left 2 bits. The two least-significant bits of tccc
|
||||
// are the number of trailing non-starters.
|
||||
|
||||
const (
|
||||
qcInfoMask = 0x3F // to clear all but the relevant bits in a qcInfo
|
||||
headerLenMask = 0x3F // extract the length value from the header byte
|
||||
headerFlagsMask = 0xC0 // extract the qcInfo bits from the header byte
|
||||
)
|
||||
|
||||
// Properties provides access to normalization properties of a rune.
|
||||
type Properties struct {
|
||||
pos uint8 // start position in reorderBuffer; used in composition.go
|
||||
size uint8 // length of UTF-8 encoding of this rune
|
||||
ccc uint8 // leading canonical combining class (ccc if not decomposition)
|
||||
tccc uint8 // trailing canonical combining class (ccc if not decomposition)
|
||||
nLead uint8 // number of leading non-starters.
|
||||
flags qcInfo // quick check flags
|
||||
index uint16
|
||||
}
|
||||
|
||||
// functions dispatchable per form
|
||||
type lookupFunc func(b input, i int) Properties
|
||||
|
||||
// formInfo holds Form-specific functions and tables.
|
||||
type formInfo struct {
|
||||
form Form
|
||||
composing, compatibility bool // form type
|
||||
info lookupFunc
|
||||
nextMain iterFunc
|
||||
}
|
||||
|
||||
var formTable = []*formInfo{{
|
||||
form: NFC,
|
||||
composing: true,
|
||||
compatibility: false,
|
||||
info: lookupInfoNFC,
|
||||
nextMain: nextComposed,
|
||||
}, {
|
||||
form: NFD,
|
||||
composing: false,
|
||||
compatibility: false,
|
||||
info: lookupInfoNFC,
|
||||
nextMain: nextDecomposed,
|
||||
}, {
|
||||
form: NFKC,
|
||||
composing: true,
|
||||
compatibility: true,
|
||||
info: lookupInfoNFKC,
|
||||
nextMain: nextComposed,
|
||||
}, {
|
||||
form: NFKD,
|
||||
composing: false,
|
||||
compatibility: true,
|
||||
info: lookupInfoNFKC,
|
||||
nextMain: nextDecomposed,
|
||||
}}
|
||||
|
||||
// We do not distinguish between boundaries for NFC, NFD, etc. to avoid
|
||||
// unexpected behavior for the user. For example, in NFD, there is a boundary
|
||||
// after 'a'. However, 'a' might combine with modifiers, so from the application's
|
||||
// perspective it is not a good boundary. We will therefore always use the
|
||||
// boundaries for the combining variants.
|
||||
|
||||
// BoundaryBefore returns true if this rune starts a new segment and
|
||||
// cannot combine with any rune on the left.
|
||||
func (p Properties) BoundaryBefore() bool {
|
||||
if p.ccc == 0 && !p.combinesBackward() {
|
||||
return true
|
||||
}
|
||||
// We assume that the CCC of the first character in a decomposition
|
||||
// is always non-zero if different from info.ccc and that we can return
|
||||
// false at this point. This is verified by maketables.
|
||||
return false
|
||||
}
|
||||
|
||||
// BoundaryAfter returns true if runes cannot combine with or otherwise
|
||||
// interact with this or previous runes.
|
||||
func (p Properties) BoundaryAfter() bool {
|
||||
// TODO: loosen these conditions.
|
||||
return p.isInert()
|
||||
}
|
||||
|
||||
// We pack quick check data in 4 bits:
|
||||
// 5: Combines forward (0 == false, 1 == true)
|
||||
// 4..3: NFC_QC Yes(00), No (10), or Maybe (11)
|
||||
// 2: NFD_QC Yes (0) or No (1). No also means there is a decomposition.
|
||||
// 1..0: Number of trailing non-starters.
|
||||
//
|
||||
// When all 4 bits are zero, the character is inert, meaning it is never
|
||||
// influenced by normalization.
|
||||
type qcInfo uint8
|
||||
|
||||
func (p Properties) isYesC() bool { return p.flags&0x10 == 0 }
|
||||
func (p Properties) isYesD() bool { return p.flags&0x4 == 0 }
|
||||
|
||||
func (p Properties) combinesForward() bool { return p.flags&0x20 != 0 }
|
||||
func (p Properties) combinesBackward() bool { return p.flags&0x8 != 0 } // == isMaybe
|
||||
func (p Properties) hasDecomposition() bool { return p.flags&0x4 != 0 } // == isNoD
|
||||
|
||||
func (p Properties) isInert() bool {
|
||||
return p.flags&qcInfoMask == 0 && p.ccc == 0
|
||||
}
|
||||
|
||||
func (p Properties) multiSegment() bool {
|
||||
return p.index >= firstMulti && p.index < endMulti
|
||||
}
|
||||
|
||||
func (p Properties) nLeadingNonStarters() uint8 {
|
||||
return p.nLead
|
||||
}
|
||||
|
||||
func (p Properties) nTrailingNonStarters() uint8 {
|
||||
return uint8(p.flags & 0x03)
|
||||
}
|
||||
|
||||
// Decomposition returns the decomposition for the underlying rune
|
||||
// or nil if there is none.
|
||||
func (p Properties) Decomposition() []byte {
|
||||
// TODO: create the decomposition for Hangul?
|
||||
if p.index == 0 {
|
||||
return nil
|
||||
}
|
||||
i := p.index
|
||||
n := decomps[i] & headerLenMask
|
||||
i++
|
||||
return decomps[i : i+uint16(n)]
|
||||
}
|
||||
|
||||
// Size returns the length of UTF-8 encoding of the rune.
|
||||
func (p Properties) Size() int {
|
||||
return int(p.size)
|
||||
}
|
||||
|
||||
// CCC returns the canonical combining class of the underlying rune.
|
||||
func (p Properties) CCC() uint8 {
|
||||
if p.index >= firstCCCZeroExcept {
|
||||
return 0
|
||||
}
|
||||
return ccc[p.ccc]
|
||||
}
|
||||
|
||||
// LeadCCC returns the CCC of the first rune in the decomposition.
|
||||
// If there is no decomposition, LeadCCC equals CCC.
|
||||
func (p Properties) LeadCCC() uint8 {
|
||||
return ccc[p.ccc]
|
||||
}
|
||||
|
||||
// TrailCCC returns the CCC of the last rune in the decomposition.
|
||||
// If there is no decomposition, TrailCCC equals CCC.
|
||||
func (p Properties) TrailCCC() uint8 {
|
||||
return ccc[p.tccc]
|
||||
}
|
||||
|
||||
func buildRecompMap() {
|
||||
recompMap = make(map[uint32]rune, len(recompMapPacked)/8)
|
||||
var buf [8]byte
|
||||
for i := 0; i < len(recompMapPacked); i += 8 {
|
||||
copy(buf[:], recompMapPacked[i:i+8])
|
||||
key := binary.BigEndian.Uint32(buf[:4])
|
||||
val := binary.BigEndian.Uint32(buf[4:])
|
||||
recompMap[key] = rune(val)
|
||||
}
|
||||
}
|
||||
|
||||
// Recomposition
|
||||
// We use 32-bit keys instead of 64-bit for the two codepoint keys.
|
||||
// This clips off the bits of three entries, but we know this will not
|
||||
// result in a collision. In the unlikely event that changes to
|
||||
// UnicodeData.txt introduce collisions, the compiler will catch it.
|
||||
// Note that the recomposition map for NFC and NFKC are identical.
|
||||
|
||||
// combine returns the combined rune or 0 if it doesn't exist.
|
||||
//
|
||||
// The caller is responsible for calling
|
||||
// recompMapOnce.Do(buildRecompMap) sometime before this is called.
|
||||
func combine(a, b rune) rune {
|
||||
key := uint32(uint16(a))<<16 + uint32(uint16(b))
|
||||
if recompMap == nil {
|
||||
panic("caller error") // see func comment
|
||||
}
|
||||
return recompMap[key]
|
||||
}
|
||||
|
||||
func lookupInfoNFC(b input, i int) Properties {
|
||||
v, sz := b.charinfoNFC(i)
|
||||
return compInfo(v, sz)
|
||||
}
|
||||
|
||||
func lookupInfoNFKC(b input, i int) Properties {
|
||||
v, sz := b.charinfoNFKC(i)
|
||||
return compInfo(v, sz)
|
||||
}
|
||||
|
||||
// Properties returns properties for the first rune in s.
|
||||
func (f Form) Properties(s []byte) Properties {
|
||||
if f == NFC || f == NFD {
|
||||
return compInfo(nfcData.lookup(s))
|
||||
}
|
||||
return compInfo(nfkcData.lookup(s))
|
||||
}
|
||||
|
||||
// PropertiesString returns properties for the first rune in s.
|
||||
func (f Form) PropertiesString(s string) Properties {
|
||||
if f == NFC || f == NFD {
|
||||
return compInfo(nfcData.lookupString(s))
|
||||
}
|
||||
return compInfo(nfkcData.lookupString(s))
|
||||
}
|
||||
|
||||
// compInfo converts the information contained in v and sz
|
||||
// to a Properties. See the comment at the top of the file
|
||||
// for more information on the format.
|
||||
func compInfo(v uint16, sz int) Properties {
|
||||
if v == 0 {
|
||||
return Properties{size: uint8(sz)}
|
||||
} else if v >= 0x8000 {
|
||||
p := Properties{
|
||||
size: uint8(sz),
|
||||
ccc: uint8(v),
|
||||
tccc: uint8(v),
|
||||
flags: qcInfo(v >> 8),
|
||||
}
|
||||
if p.ccc > 0 || p.combinesBackward() {
|
||||
p.nLead = uint8(p.flags & 0x3)
|
||||
}
|
||||
return p
|
||||
}
|
||||
// has decomposition
|
||||
h := decomps[v]
|
||||
f := (qcInfo(h&headerFlagsMask) >> 2) | 0x4
|
||||
p := Properties{size: uint8(sz), flags: f, index: v}
|
||||
if v >= firstCCC {
|
||||
v += uint16(h&headerLenMask) + 1
|
||||
c := decomps[v]
|
||||
p.tccc = c >> 2
|
||||
p.flags |= qcInfo(c & 0x3)
|
||||
if v >= firstLeadingCCC {
|
||||
p.nLead = c & 0x3
|
||||
if v >= firstStarterWithNLead {
|
||||
// We were tricked. Remove the decomposition.
|
||||
p.flags &= 0x03
|
||||
p.index = 0
|
||||
return p
|
||||
}
|
||||
p.ccc = decomps[v+1]
|
||||
}
|
||||
}
|
||||
return p
|
||||
}
|
||||
109
vendor/golang.org/x/text/unicode/norm/input.go
generated
vendored
Normal file
109
vendor/golang.org/x/text/unicode/norm/input.go
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
// Copyright 2011 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 norm
|
||||
|
||||
import "unicode/utf8"
|
||||
|
||||
type input struct {
|
||||
str string
|
||||
bytes []byte
|
||||
}
|
||||
|
||||
func inputBytes(str []byte) input {
|
||||
return input{bytes: str}
|
||||
}
|
||||
|
||||
func inputString(str string) input {
|
||||
return input{str: str}
|
||||
}
|
||||
|
||||
func (in *input) setBytes(str []byte) {
|
||||
in.str = ""
|
||||
in.bytes = str
|
||||
}
|
||||
|
||||
func (in *input) setString(str string) {
|
||||
in.str = str
|
||||
in.bytes = nil
|
||||
}
|
||||
|
||||
func (in *input) _byte(p int) byte {
|
||||
if in.bytes == nil {
|
||||
return in.str[p]
|
||||
}
|
||||
return in.bytes[p]
|
||||
}
|
||||
|
||||
func (in *input) skipASCII(p, max int) int {
|
||||
if in.bytes == nil {
|
||||
for ; p < max && in.str[p] < utf8.RuneSelf; p++ {
|
||||
}
|
||||
} else {
|
||||
for ; p < max && in.bytes[p] < utf8.RuneSelf; p++ {
|
||||
}
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func (in *input) skipContinuationBytes(p int) int {
|
||||
if in.bytes == nil {
|
||||
for ; p < len(in.str) && !utf8.RuneStart(in.str[p]); p++ {
|
||||
}
|
||||
} else {
|
||||
for ; p < len(in.bytes) && !utf8.RuneStart(in.bytes[p]); p++ {
|
||||
}
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func (in *input) appendSlice(buf []byte, b, e int) []byte {
|
||||
if in.bytes != nil {
|
||||
return append(buf, in.bytes[b:e]...)
|
||||
}
|
||||
for i := b; i < e; i++ {
|
||||
buf = append(buf, in.str[i])
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
||||
func (in *input) copySlice(buf []byte, b, e int) int {
|
||||
if in.bytes == nil {
|
||||
return copy(buf, in.str[b:e])
|
||||
}
|
||||
return copy(buf, in.bytes[b:e])
|
||||
}
|
||||
|
||||
func (in *input) charinfoNFC(p int) (uint16, int) {
|
||||
if in.bytes == nil {
|
||||
return nfcData.lookupString(in.str[p:])
|
||||
}
|
||||
return nfcData.lookup(in.bytes[p:])
|
||||
}
|
||||
|
||||
func (in *input) charinfoNFKC(p int) (uint16, int) {
|
||||
if in.bytes == nil {
|
||||
return nfkcData.lookupString(in.str[p:])
|
||||
}
|
||||
return nfkcData.lookup(in.bytes[p:])
|
||||
}
|
||||
|
||||
func (in *input) hangul(p int) (r rune) {
|
||||
var size int
|
||||
if in.bytes == nil {
|
||||
if !isHangulString(in.str[p:]) {
|
||||
return 0
|
||||
}
|
||||
r, size = utf8.DecodeRuneInString(in.str[p:])
|
||||
} else {
|
||||
if !isHangul(in.bytes[p:]) {
|
||||
return 0
|
||||
}
|
||||
r, size = utf8.DecodeRune(in.bytes[p:])
|
||||
}
|
||||
if size != hangulUTF8Size {
|
||||
return 0
|
||||
}
|
||||
return r
|
||||
}
|
||||
458
vendor/golang.org/x/text/unicode/norm/iter.go
generated
vendored
Normal file
458
vendor/golang.org/x/text/unicode/norm/iter.go
generated
vendored
Normal file
@@ -0,0 +1,458 @@
|
||||
// Copyright 2011 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 norm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// MaxSegmentSize is the maximum size of a byte buffer needed to consider any
|
||||
// sequence of starter and non-starter runes for the purpose of normalization.
|
||||
const MaxSegmentSize = maxByteBufferSize
|
||||
|
||||
// An Iter iterates over a string or byte slice, while normalizing it
|
||||
// to a given Form.
|
||||
type Iter struct {
|
||||
rb reorderBuffer
|
||||
buf [maxByteBufferSize]byte
|
||||
info Properties // first character saved from previous iteration
|
||||
next iterFunc // implementation of next depends on form
|
||||
asciiF iterFunc
|
||||
|
||||
p int // current position in input source
|
||||
multiSeg []byte // remainder of multi-segment decomposition
|
||||
}
|
||||
|
||||
type iterFunc func(*Iter) []byte
|
||||
|
||||
// Init initializes i to iterate over src after normalizing it to Form f.
|
||||
func (i *Iter) Init(f Form, src []byte) {
|
||||
i.p = 0
|
||||
if len(src) == 0 {
|
||||
i.setDone()
|
||||
i.rb.nsrc = 0
|
||||
return
|
||||
}
|
||||
i.multiSeg = nil
|
||||
i.rb.init(f, src)
|
||||
i.next = i.rb.f.nextMain
|
||||
i.asciiF = nextASCIIBytes
|
||||
i.info = i.rb.f.info(i.rb.src, i.p)
|
||||
i.rb.ss.first(i.info)
|
||||
}
|
||||
|
||||
// InitString initializes i to iterate over src after normalizing it to Form f.
|
||||
func (i *Iter) InitString(f Form, src string) {
|
||||
i.p = 0
|
||||
if len(src) == 0 {
|
||||
i.setDone()
|
||||
i.rb.nsrc = 0
|
||||
return
|
||||
}
|
||||
i.multiSeg = nil
|
||||
i.rb.initString(f, src)
|
||||
i.next = i.rb.f.nextMain
|
||||
i.asciiF = nextASCIIString
|
||||
i.info = i.rb.f.info(i.rb.src, i.p)
|
||||
i.rb.ss.first(i.info)
|
||||
}
|
||||
|
||||
// Seek sets the segment to be returned by the next call to Next to start
|
||||
// at position p. It is the responsibility of the caller to set p to the
|
||||
// start of a segment.
|
||||
func (i *Iter) Seek(offset int64, whence int) (int64, error) {
|
||||
var abs int64
|
||||
switch whence {
|
||||
case 0:
|
||||
abs = offset
|
||||
case 1:
|
||||
abs = int64(i.p) + offset
|
||||
case 2:
|
||||
abs = int64(i.rb.nsrc) + offset
|
||||
default:
|
||||
return 0, fmt.Errorf("norm: invalid whence")
|
||||
}
|
||||
if abs < 0 {
|
||||
return 0, fmt.Errorf("norm: negative position")
|
||||
}
|
||||
if int(abs) >= i.rb.nsrc {
|
||||
i.setDone()
|
||||
return int64(i.p), nil
|
||||
}
|
||||
i.p = int(abs)
|
||||
i.multiSeg = nil
|
||||
i.next = i.rb.f.nextMain
|
||||
i.info = i.rb.f.info(i.rb.src, i.p)
|
||||
i.rb.ss.first(i.info)
|
||||
return abs, nil
|
||||
}
|
||||
|
||||
// returnSlice returns a slice of the underlying input type as a byte slice.
|
||||
// If the underlying is of type []byte, it will simply return a slice.
|
||||
// If the underlying is of type string, it will copy the slice to the buffer
|
||||
// and return that.
|
||||
func (i *Iter) returnSlice(a, b int) []byte {
|
||||
if i.rb.src.bytes == nil {
|
||||
return i.buf[:copy(i.buf[:], i.rb.src.str[a:b])]
|
||||
}
|
||||
return i.rb.src.bytes[a:b]
|
||||
}
|
||||
|
||||
// Pos returns the byte position at which the next call to Next will commence processing.
|
||||
func (i *Iter) Pos() int {
|
||||
return i.p
|
||||
}
|
||||
|
||||
func (i *Iter) setDone() {
|
||||
i.next = nextDone
|
||||
i.p = i.rb.nsrc
|
||||
}
|
||||
|
||||
// Done returns true if there is no more input to process.
|
||||
func (i *Iter) Done() bool {
|
||||
return i.p >= i.rb.nsrc
|
||||
}
|
||||
|
||||
// Next returns f(i.input[i.Pos():n]), where n is a boundary of i.input.
|
||||
// For any input a and b for which f(a) == f(b), subsequent calls
|
||||
// to Next will return the same segments.
|
||||
// Modifying runes are grouped together with the preceding starter, if such a starter exists.
|
||||
// Although not guaranteed, n will typically be the smallest possible n.
|
||||
func (i *Iter) Next() []byte {
|
||||
return i.next(i)
|
||||
}
|
||||
|
||||
func nextASCIIBytes(i *Iter) []byte {
|
||||
p := i.p + 1
|
||||
if p >= i.rb.nsrc {
|
||||
p0 := i.p
|
||||
i.setDone()
|
||||
return i.rb.src.bytes[p0:p]
|
||||
}
|
||||
if i.rb.src.bytes[p] < utf8.RuneSelf {
|
||||
p0 := i.p
|
||||
i.p = p
|
||||
return i.rb.src.bytes[p0:p]
|
||||
}
|
||||
i.info = i.rb.f.info(i.rb.src, i.p)
|
||||
i.next = i.rb.f.nextMain
|
||||
return i.next(i)
|
||||
}
|
||||
|
||||
func nextASCIIString(i *Iter) []byte {
|
||||
p := i.p + 1
|
||||
if p >= i.rb.nsrc {
|
||||
i.buf[0] = i.rb.src.str[i.p]
|
||||
i.setDone()
|
||||
return i.buf[:1]
|
||||
}
|
||||
if i.rb.src.str[p] < utf8.RuneSelf {
|
||||
i.buf[0] = i.rb.src.str[i.p]
|
||||
i.p = p
|
||||
return i.buf[:1]
|
||||
}
|
||||
i.info = i.rb.f.info(i.rb.src, i.p)
|
||||
i.next = i.rb.f.nextMain
|
||||
return i.next(i)
|
||||
}
|
||||
|
||||
func nextHangul(i *Iter) []byte {
|
||||
p := i.p
|
||||
next := p + hangulUTF8Size
|
||||
if next >= i.rb.nsrc {
|
||||
i.setDone()
|
||||
} else if i.rb.src.hangul(next) == 0 {
|
||||
i.rb.ss.next(i.info)
|
||||
i.info = i.rb.f.info(i.rb.src, i.p)
|
||||
i.next = i.rb.f.nextMain
|
||||
return i.next(i)
|
||||
}
|
||||
i.p = next
|
||||
return i.buf[:decomposeHangul(i.buf[:], i.rb.src.hangul(p))]
|
||||
}
|
||||
|
||||
func nextDone(i *Iter) []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
// nextMulti is used for iterating over multi-segment decompositions
|
||||
// for decomposing normal forms.
|
||||
func nextMulti(i *Iter) []byte {
|
||||
j := 0
|
||||
d := i.multiSeg
|
||||
// skip first rune
|
||||
for j = 1; j < len(d) && !utf8.RuneStart(d[j]); j++ {
|
||||
}
|
||||
for j < len(d) {
|
||||
info := i.rb.f.info(input{bytes: d}, j)
|
||||
if info.BoundaryBefore() {
|
||||
i.multiSeg = d[j:]
|
||||
return d[:j]
|
||||
}
|
||||
j += int(info.size)
|
||||
}
|
||||
// treat last segment as normal decomposition
|
||||
i.next = i.rb.f.nextMain
|
||||
return i.next(i)
|
||||
}
|
||||
|
||||
// nextMultiNorm is used for iterating over multi-segment decompositions
|
||||
// for composing normal forms.
|
||||
func nextMultiNorm(i *Iter) []byte {
|
||||
j := 0
|
||||
d := i.multiSeg
|
||||
for j < len(d) {
|
||||
info := i.rb.f.info(input{bytes: d}, j)
|
||||
if info.BoundaryBefore() {
|
||||
i.rb.compose()
|
||||
seg := i.buf[:i.rb.flushCopy(i.buf[:])]
|
||||
i.rb.insertUnsafe(input{bytes: d}, j, info)
|
||||
i.multiSeg = d[j+int(info.size):]
|
||||
return seg
|
||||
}
|
||||
i.rb.insertUnsafe(input{bytes: d}, j, info)
|
||||
j += int(info.size)
|
||||
}
|
||||
i.multiSeg = nil
|
||||
i.next = nextComposed
|
||||
return doNormComposed(i)
|
||||
}
|
||||
|
||||
// nextDecomposed is the implementation of Next for forms NFD and NFKD.
|
||||
func nextDecomposed(i *Iter) (next []byte) {
|
||||
outp := 0
|
||||
inCopyStart, outCopyStart := i.p, 0
|
||||
for {
|
||||
if sz := int(i.info.size); sz <= 1 {
|
||||
i.rb.ss = 0
|
||||
p := i.p
|
||||
i.p++ // ASCII or illegal byte. Either way, advance by 1.
|
||||
if i.p >= i.rb.nsrc {
|
||||
i.setDone()
|
||||
return i.returnSlice(p, i.p)
|
||||
} else if i.rb.src._byte(i.p) < utf8.RuneSelf {
|
||||
i.next = i.asciiF
|
||||
return i.returnSlice(p, i.p)
|
||||
}
|
||||
outp++
|
||||
} else if d := i.info.Decomposition(); d != nil {
|
||||
// Note: If leading CCC != 0, then len(d) == 2 and last is also non-zero.
|
||||
// Case 1: there is a leftover to copy. In this case the decomposition
|
||||
// must begin with a modifier and should always be appended.
|
||||
// Case 2: no leftover. Simply return d if followed by a ccc == 0 value.
|
||||
p := outp + len(d)
|
||||
if outp > 0 {
|
||||
i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
|
||||
// TODO: this condition should not be possible, but we leave it
|
||||
// in for defensive purposes.
|
||||
if p > len(i.buf) {
|
||||
return i.buf[:outp]
|
||||
}
|
||||
} else if i.info.multiSegment() {
|
||||
// outp must be 0 as multi-segment decompositions always
|
||||
// start a new segment.
|
||||
if i.multiSeg == nil {
|
||||
i.multiSeg = d
|
||||
i.next = nextMulti
|
||||
return nextMulti(i)
|
||||
}
|
||||
// We are in the last segment. Treat as normal decomposition.
|
||||
d = i.multiSeg
|
||||
i.multiSeg = nil
|
||||
p = len(d)
|
||||
}
|
||||
prevCC := i.info.tccc
|
||||
if i.p += sz; i.p >= i.rb.nsrc {
|
||||
i.setDone()
|
||||
i.info = Properties{} // Force BoundaryBefore to succeed.
|
||||
} else {
|
||||
i.info = i.rb.f.info(i.rb.src, i.p)
|
||||
}
|
||||
switch i.rb.ss.next(i.info) {
|
||||
case ssOverflow:
|
||||
i.next = nextCGJDecompose
|
||||
fallthrough
|
||||
case ssStarter:
|
||||
if outp > 0 {
|
||||
copy(i.buf[outp:], d)
|
||||
return i.buf[:p]
|
||||
}
|
||||
return d
|
||||
}
|
||||
copy(i.buf[outp:], d)
|
||||
outp = p
|
||||
inCopyStart, outCopyStart = i.p, outp
|
||||
if i.info.ccc < prevCC {
|
||||
goto doNorm
|
||||
}
|
||||
continue
|
||||
} else if r := i.rb.src.hangul(i.p); r != 0 {
|
||||
outp = decomposeHangul(i.buf[:], r)
|
||||
i.p += hangulUTF8Size
|
||||
inCopyStart, outCopyStart = i.p, outp
|
||||
if i.p >= i.rb.nsrc {
|
||||
i.setDone()
|
||||
break
|
||||
} else if i.rb.src.hangul(i.p) != 0 {
|
||||
i.next = nextHangul
|
||||
return i.buf[:outp]
|
||||
}
|
||||
} else {
|
||||
p := outp + sz
|
||||
if p > len(i.buf) {
|
||||
break
|
||||
}
|
||||
outp = p
|
||||
i.p += sz
|
||||
}
|
||||
if i.p >= i.rb.nsrc {
|
||||
i.setDone()
|
||||
break
|
||||
}
|
||||
prevCC := i.info.tccc
|
||||
i.info = i.rb.f.info(i.rb.src, i.p)
|
||||
if v := i.rb.ss.next(i.info); v == ssStarter {
|
||||
break
|
||||
} else if v == ssOverflow {
|
||||
i.next = nextCGJDecompose
|
||||
break
|
||||
}
|
||||
if i.info.ccc < prevCC {
|
||||
goto doNorm
|
||||
}
|
||||
}
|
||||
if outCopyStart == 0 {
|
||||
return i.returnSlice(inCopyStart, i.p)
|
||||
} else if inCopyStart < i.p {
|
||||
i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
|
||||
}
|
||||
return i.buf[:outp]
|
||||
doNorm:
|
||||
// Insert what we have decomposed so far in the reorderBuffer.
|
||||
// As we will only reorder, there will always be enough room.
|
||||
i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
|
||||
i.rb.insertDecomposed(i.buf[0:outp])
|
||||
return doNormDecomposed(i)
|
||||
}
|
||||
|
||||
func doNormDecomposed(i *Iter) []byte {
|
||||
for {
|
||||
i.rb.insertUnsafe(i.rb.src, i.p, i.info)
|
||||
if i.p += int(i.info.size); i.p >= i.rb.nsrc {
|
||||
i.setDone()
|
||||
break
|
||||
}
|
||||
i.info = i.rb.f.info(i.rb.src, i.p)
|
||||
if i.info.ccc == 0 {
|
||||
break
|
||||
}
|
||||
if s := i.rb.ss.next(i.info); s == ssOverflow {
|
||||
i.next = nextCGJDecompose
|
||||
break
|
||||
}
|
||||
}
|
||||
// new segment or too many combining characters: exit normalization
|
||||
return i.buf[:i.rb.flushCopy(i.buf[:])]
|
||||
}
|
||||
|
||||
func nextCGJDecompose(i *Iter) []byte {
|
||||
i.rb.ss = 0
|
||||
i.rb.insertCGJ()
|
||||
i.next = nextDecomposed
|
||||
i.rb.ss.first(i.info)
|
||||
buf := doNormDecomposed(i)
|
||||
return buf
|
||||
}
|
||||
|
||||
// nextComposed is the implementation of Next for forms NFC and NFKC.
|
||||
func nextComposed(i *Iter) []byte {
|
||||
outp, startp := 0, i.p
|
||||
var prevCC uint8
|
||||
for {
|
||||
if !i.info.isYesC() {
|
||||
goto doNorm
|
||||
}
|
||||
prevCC = i.info.tccc
|
||||
sz := int(i.info.size)
|
||||
if sz == 0 {
|
||||
sz = 1 // illegal rune: copy byte-by-byte
|
||||
}
|
||||
p := outp + sz
|
||||
if p > len(i.buf) {
|
||||
break
|
||||
}
|
||||
outp = p
|
||||
i.p += sz
|
||||
if i.p >= i.rb.nsrc {
|
||||
i.setDone()
|
||||
break
|
||||
} else if i.rb.src._byte(i.p) < utf8.RuneSelf {
|
||||
i.rb.ss = 0
|
||||
i.next = i.asciiF
|
||||
break
|
||||
}
|
||||
i.info = i.rb.f.info(i.rb.src, i.p)
|
||||
if v := i.rb.ss.next(i.info); v == ssStarter {
|
||||
break
|
||||
} else if v == ssOverflow {
|
||||
i.next = nextCGJCompose
|
||||
break
|
||||
}
|
||||
if i.info.ccc < prevCC {
|
||||
goto doNorm
|
||||
}
|
||||
}
|
||||
return i.returnSlice(startp, i.p)
|
||||
doNorm:
|
||||
// reset to start position
|
||||
i.p = startp
|
||||
i.info = i.rb.f.info(i.rb.src, i.p)
|
||||
i.rb.ss.first(i.info)
|
||||
if i.info.multiSegment() {
|
||||
d := i.info.Decomposition()
|
||||
info := i.rb.f.info(input{bytes: d}, 0)
|
||||
i.rb.insertUnsafe(input{bytes: d}, 0, info)
|
||||
i.multiSeg = d[int(info.size):]
|
||||
i.next = nextMultiNorm
|
||||
return nextMultiNorm(i)
|
||||
}
|
||||
i.rb.ss.first(i.info)
|
||||
i.rb.insertUnsafe(i.rb.src, i.p, i.info)
|
||||
return doNormComposed(i)
|
||||
}
|
||||
|
||||
func doNormComposed(i *Iter) []byte {
|
||||
// First rune should already be inserted.
|
||||
for {
|
||||
if i.p += int(i.info.size); i.p >= i.rb.nsrc {
|
||||
i.setDone()
|
||||
break
|
||||
}
|
||||
i.info = i.rb.f.info(i.rb.src, i.p)
|
||||
if s := i.rb.ss.next(i.info); s == ssStarter {
|
||||
break
|
||||
} else if s == ssOverflow {
|
||||
i.next = nextCGJCompose
|
||||
break
|
||||
}
|
||||
i.rb.insertUnsafe(i.rb.src, i.p, i.info)
|
||||
}
|
||||
i.rb.compose()
|
||||
seg := i.buf[:i.rb.flushCopy(i.buf[:])]
|
||||
return seg
|
||||
}
|
||||
|
||||
func nextCGJCompose(i *Iter) []byte {
|
||||
i.rb.ss = 0 // instead of first
|
||||
i.rb.insertCGJ()
|
||||
i.next = nextComposed
|
||||
// Note that we treat any rune with nLeadingNonStarters > 0 as a non-starter,
|
||||
// even if they are not. This is particularly dubious for U+FF9E and UFF9A.
|
||||
// If we ever change that, insert a check here.
|
||||
i.rb.ss.first(i.info)
|
||||
i.rb.insertUnsafe(i.rb.src, i.p, i.info)
|
||||
return doNormComposed(i)
|
||||
}
|
||||
609
vendor/golang.org/x/text/unicode/norm/normalize.go
generated
vendored
Normal file
609
vendor/golang.org/x/text/unicode/norm/normalize.go
generated
vendored
Normal file
@@ -0,0 +1,609 @@
|
||||
// Copyright 2011 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.
|
||||
|
||||
// Note: the file data_test.go that is generated should not be checked in.
|
||||
//go:generate go run maketables.go triegen.go
|
||||
//go:generate go test -tags test
|
||||
|
||||
// Package norm contains types and functions for normalizing Unicode strings.
|
||||
package norm // import "golang.org/x/text/unicode/norm"
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// A Form denotes a canonical representation of Unicode code points.
|
||||
// The Unicode-defined normalization and equivalence forms are:
|
||||
//
|
||||
// NFC Unicode Normalization Form C
|
||||
// NFD Unicode Normalization Form D
|
||||
// NFKC Unicode Normalization Form KC
|
||||
// NFKD Unicode Normalization Form KD
|
||||
//
|
||||
// For a Form f, this documentation uses the notation f(x) to mean
|
||||
// the bytes or string x converted to the given form.
|
||||
// A position n in x is called a boundary if conversion to the form can
|
||||
// proceed independently on both sides:
|
||||
// f(x) == append(f(x[0:n]), f(x[n:])...)
|
||||
//
|
||||
// References: https://unicode.org/reports/tr15/ and
|
||||
// https://unicode.org/notes/tn5/.
|
||||
type Form int
|
||||
|
||||
const (
|
||||
NFC Form = iota
|
||||
NFD
|
||||
NFKC
|
||||
NFKD
|
||||
)
|
||||
|
||||
// Bytes returns f(b). May return b if f(b) = b.
|
||||
func (f Form) Bytes(b []byte) []byte {
|
||||
src := inputBytes(b)
|
||||
ft := formTable[f]
|
||||
n, ok := ft.quickSpan(src, 0, len(b), true)
|
||||
if ok {
|
||||
return b
|
||||
}
|
||||
out := make([]byte, n, len(b))
|
||||
copy(out, b[0:n])
|
||||
rb := reorderBuffer{f: *ft, src: src, nsrc: len(b), out: out, flushF: appendFlush}
|
||||
return doAppendInner(&rb, n)
|
||||
}
|
||||
|
||||
// String returns f(s).
|
||||
func (f Form) String(s string) string {
|
||||
src := inputString(s)
|
||||
ft := formTable[f]
|
||||
n, ok := ft.quickSpan(src, 0, len(s), true)
|
||||
if ok {
|
||||
return s
|
||||
}
|
||||
out := make([]byte, n, len(s))
|
||||
copy(out, s[0:n])
|
||||
rb := reorderBuffer{f: *ft, src: src, nsrc: len(s), out: out, flushF: appendFlush}
|
||||
return string(doAppendInner(&rb, n))
|
||||
}
|
||||
|
||||
// IsNormal returns true if b == f(b).
|
||||
func (f Form) IsNormal(b []byte) bool {
|
||||
src := inputBytes(b)
|
||||
ft := formTable[f]
|
||||
bp, ok := ft.quickSpan(src, 0, len(b), true)
|
||||
if ok {
|
||||
return true
|
||||
}
|
||||
rb := reorderBuffer{f: *ft, src: src, nsrc: len(b)}
|
||||
rb.setFlusher(nil, cmpNormalBytes)
|
||||
for bp < len(b) {
|
||||
rb.out = b[bp:]
|
||||
if bp = decomposeSegment(&rb, bp, true); bp < 0 {
|
||||
return false
|
||||
}
|
||||
bp, _ = rb.f.quickSpan(rb.src, bp, len(b), true)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func cmpNormalBytes(rb *reorderBuffer) bool {
|
||||
b := rb.out
|
||||
for i := 0; i < rb.nrune; i++ {
|
||||
info := rb.rune[i]
|
||||
if int(info.size) > len(b) {
|
||||
return false
|
||||
}
|
||||
p := info.pos
|
||||
pe := p + info.size
|
||||
for ; p < pe; p++ {
|
||||
if b[0] != rb.byte[p] {
|
||||
return false
|
||||
}
|
||||
b = b[1:]
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// IsNormalString returns true if s == f(s).
|
||||
func (f Form) IsNormalString(s string) bool {
|
||||
src := inputString(s)
|
||||
ft := formTable[f]
|
||||
bp, ok := ft.quickSpan(src, 0, len(s), true)
|
||||
if ok {
|
||||
return true
|
||||
}
|
||||
rb := reorderBuffer{f: *ft, src: src, nsrc: len(s)}
|
||||
rb.setFlusher(nil, func(rb *reorderBuffer) bool {
|
||||
for i := 0; i < rb.nrune; i++ {
|
||||
info := rb.rune[i]
|
||||
if bp+int(info.size) > len(s) {
|
||||
return false
|
||||
}
|
||||
p := info.pos
|
||||
pe := p + info.size
|
||||
for ; p < pe; p++ {
|
||||
if s[bp] != rb.byte[p] {
|
||||
return false
|
||||
}
|
||||
bp++
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
for bp < len(s) {
|
||||
if bp = decomposeSegment(&rb, bp, true); bp < 0 {
|
||||
return false
|
||||
}
|
||||
bp, _ = rb.f.quickSpan(rb.src, bp, len(s), true)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// patchTail fixes a case where a rune may be incorrectly normalized
|
||||
// if it is followed by illegal continuation bytes. It returns the
|
||||
// patched buffer and whether the decomposition is still in progress.
|
||||
func patchTail(rb *reorderBuffer) bool {
|
||||
info, p := lastRuneStart(&rb.f, rb.out)
|
||||
if p == -1 || info.size == 0 {
|
||||
return true
|
||||
}
|
||||
end := p + int(info.size)
|
||||
extra := len(rb.out) - end
|
||||
if extra > 0 {
|
||||
// Potentially allocating memory. However, this only
|
||||
// happens with ill-formed UTF-8.
|
||||
x := make([]byte, 0)
|
||||
x = append(x, rb.out[len(rb.out)-extra:]...)
|
||||
rb.out = rb.out[:end]
|
||||
decomposeToLastBoundary(rb)
|
||||
rb.doFlush()
|
||||
rb.out = append(rb.out, x...)
|
||||
return false
|
||||
}
|
||||
buf := rb.out[p:]
|
||||
rb.out = rb.out[:p]
|
||||
decomposeToLastBoundary(rb)
|
||||
if s := rb.ss.next(info); s == ssStarter {
|
||||
rb.doFlush()
|
||||
rb.ss.first(info)
|
||||
} else if s == ssOverflow {
|
||||
rb.doFlush()
|
||||
rb.insertCGJ()
|
||||
rb.ss = 0
|
||||
}
|
||||
rb.insertUnsafe(inputBytes(buf), 0, info)
|
||||
return true
|
||||
}
|
||||
|
||||
func appendQuick(rb *reorderBuffer, i int) int {
|
||||
if rb.nsrc == i {
|
||||
return i
|
||||
}
|
||||
end, _ := rb.f.quickSpan(rb.src, i, rb.nsrc, true)
|
||||
rb.out = rb.src.appendSlice(rb.out, i, end)
|
||||
return end
|
||||
}
|
||||
|
||||
// Append returns f(append(out, b...)).
|
||||
// The buffer out must be nil, empty, or equal to f(out).
|
||||
func (f Form) Append(out []byte, src ...byte) []byte {
|
||||
return f.doAppend(out, inputBytes(src), len(src))
|
||||
}
|
||||
|
||||
func (f Form) doAppend(out []byte, src input, n int) []byte {
|
||||
if n == 0 {
|
||||
return out
|
||||
}
|
||||
ft := formTable[f]
|
||||
// Attempt to do a quickSpan first so we can avoid initializing the reorderBuffer.
|
||||
if len(out) == 0 {
|
||||
p, _ := ft.quickSpan(src, 0, n, true)
|
||||
out = src.appendSlice(out, 0, p)
|
||||
if p == n {
|
||||
return out
|
||||
}
|
||||
rb := reorderBuffer{f: *ft, src: src, nsrc: n, out: out, flushF: appendFlush}
|
||||
return doAppendInner(&rb, p)
|
||||
}
|
||||
rb := reorderBuffer{f: *ft, src: src, nsrc: n}
|
||||
return doAppend(&rb, out, 0)
|
||||
}
|
||||
|
||||
func doAppend(rb *reorderBuffer, out []byte, p int) []byte {
|
||||
rb.setFlusher(out, appendFlush)
|
||||
src, n := rb.src, rb.nsrc
|
||||
doMerge := len(out) > 0
|
||||
if q := src.skipContinuationBytes(p); q > p {
|
||||
// Move leading non-starters to destination.
|
||||
rb.out = src.appendSlice(rb.out, p, q)
|
||||
p = q
|
||||
doMerge = patchTail(rb)
|
||||
}
|
||||
fd := &rb.f
|
||||
if doMerge {
|
||||
var info Properties
|
||||
if p < n {
|
||||
info = fd.info(src, p)
|
||||
if !info.BoundaryBefore() || info.nLeadingNonStarters() > 0 {
|
||||
if p == 0 {
|
||||
decomposeToLastBoundary(rb)
|
||||
}
|
||||
p = decomposeSegment(rb, p, true)
|
||||
}
|
||||
}
|
||||
if info.size == 0 {
|
||||
rb.doFlush()
|
||||
// Append incomplete UTF-8 encoding.
|
||||
return src.appendSlice(rb.out, p, n)
|
||||
}
|
||||
if rb.nrune > 0 {
|
||||
return doAppendInner(rb, p)
|
||||
}
|
||||
}
|
||||
p = appendQuick(rb, p)
|
||||
return doAppendInner(rb, p)
|
||||
}
|
||||
|
||||
func doAppendInner(rb *reorderBuffer, p int) []byte {
|
||||
for n := rb.nsrc; p < n; {
|
||||
p = decomposeSegment(rb, p, true)
|
||||
p = appendQuick(rb, p)
|
||||
}
|
||||
return rb.out
|
||||
}
|
||||
|
||||
// AppendString returns f(append(out, []byte(s))).
|
||||
// The buffer out must be nil, empty, or equal to f(out).
|
||||
func (f Form) AppendString(out []byte, src string) []byte {
|
||||
return f.doAppend(out, inputString(src), len(src))
|
||||
}
|
||||
|
||||
// QuickSpan returns a boundary n such that b[0:n] == f(b[0:n]).
|
||||
// It is not guaranteed to return the largest such n.
|
||||
func (f Form) QuickSpan(b []byte) int {
|
||||
n, _ := formTable[f].quickSpan(inputBytes(b), 0, len(b), true)
|
||||
return n
|
||||
}
|
||||
|
||||
// Span implements transform.SpanningTransformer. It returns a boundary n such
|
||||
// that b[0:n] == f(b[0:n]). It is not guaranteed to return the largest such n.
|
||||
func (f Form) Span(b []byte, atEOF bool) (n int, err error) {
|
||||
n, ok := formTable[f].quickSpan(inputBytes(b), 0, len(b), atEOF)
|
||||
if n < len(b) {
|
||||
if !ok {
|
||||
err = transform.ErrEndOfSpan
|
||||
} else {
|
||||
err = transform.ErrShortSrc
|
||||
}
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// SpanString returns a boundary n such that s[0:n] == f(s[0:n]).
|
||||
// It is not guaranteed to return the largest such n.
|
||||
func (f Form) SpanString(s string, atEOF bool) (n int, err error) {
|
||||
n, ok := formTable[f].quickSpan(inputString(s), 0, len(s), atEOF)
|
||||
if n < len(s) {
|
||||
if !ok {
|
||||
err = transform.ErrEndOfSpan
|
||||
} else {
|
||||
err = transform.ErrShortSrc
|
||||
}
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// quickSpan returns a boundary n such that src[0:n] == f(src[0:n]) and
|
||||
// whether any non-normalized parts were found. If atEOF is false, n will
|
||||
// not point past the last segment if this segment might be become
|
||||
// non-normalized by appending other runes.
|
||||
func (f *formInfo) quickSpan(src input, i, end int, atEOF bool) (n int, ok bool) {
|
||||
var lastCC uint8
|
||||
ss := streamSafe(0)
|
||||
lastSegStart := i
|
||||
for n = end; i < n; {
|
||||
if j := src.skipASCII(i, n); i != j {
|
||||
i = j
|
||||
lastSegStart = i - 1
|
||||
lastCC = 0
|
||||
ss = 0
|
||||
continue
|
||||
}
|
||||
info := f.info(src, i)
|
||||
if info.size == 0 {
|
||||
if atEOF {
|
||||
// include incomplete runes
|
||||
return n, true
|
||||
}
|
||||
return lastSegStart, true
|
||||
}
|
||||
// This block needs to be before the next, because it is possible to
|
||||
// have an overflow for runes that are starters (e.g. with U+FF9E).
|
||||
switch ss.next(info) {
|
||||
case ssStarter:
|
||||
lastSegStart = i
|
||||
case ssOverflow:
|
||||
return lastSegStart, false
|
||||
case ssSuccess:
|
||||
if lastCC > info.ccc {
|
||||
return lastSegStart, false
|
||||
}
|
||||
}
|
||||
if f.composing {
|
||||
if !info.isYesC() {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if !info.isYesD() {
|
||||
break
|
||||
}
|
||||
}
|
||||
lastCC = info.ccc
|
||||
i += int(info.size)
|
||||
}
|
||||
if i == n {
|
||||
if !atEOF {
|
||||
n = lastSegStart
|
||||
}
|
||||
return n, true
|
||||
}
|
||||
return lastSegStart, false
|
||||
}
|
||||
|
||||
// QuickSpanString returns a boundary n such that s[0:n] == f(s[0:n]).
|
||||
// It is not guaranteed to return the largest such n.
|
||||
func (f Form) QuickSpanString(s string) int {
|
||||
n, _ := formTable[f].quickSpan(inputString(s), 0, len(s), true)
|
||||
return n
|
||||
}
|
||||
|
||||
// FirstBoundary returns the position i of the first boundary in b
|
||||
// or -1 if b contains no boundary.
|
||||
func (f Form) FirstBoundary(b []byte) int {
|
||||
return f.firstBoundary(inputBytes(b), len(b))
|
||||
}
|
||||
|
||||
func (f Form) firstBoundary(src input, nsrc int) int {
|
||||
i := src.skipContinuationBytes(0)
|
||||
if i >= nsrc {
|
||||
return -1
|
||||
}
|
||||
fd := formTable[f]
|
||||
ss := streamSafe(0)
|
||||
// We should call ss.first here, but we can't as the first rune is
|
||||
// skipped already. This means FirstBoundary can't really determine
|
||||
// CGJ insertion points correctly. Luckily it doesn't have to.
|
||||
for {
|
||||
info := fd.info(src, i)
|
||||
if info.size == 0 {
|
||||
return -1
|
||||
}
|
||||
if s := ss.next(info); s != ssSuccess {
|
||||
return i
|
||||
}
|
||||
i += int(info.size)
|
||||
if i >= nsrc {
|
||||
if !info.BoundaryAfter() && !ss.isMax() {
|
||||
return -1
|
||||
}
|
||||
return nsrc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FirstBoundaryInString returns the position i of the first boundary in s
|
||||
// or -1 if s contains no boundary.
|
||||
func (f Form) FirstBoundaryInString(s string) int {
|
||||
return f.firstBoundary(inputString(s), len(s))
|
||||
}
|
||||
|
||||
// NextBoundary reports the index of the boundary between the first and next
|
||||
// segment in b or -1 if atEOF is false and there are not enough bytes to
|
||||
// determine this boundary.
|
||||
func (f Form) NextBoundary(b []byte, atEOF bool) int {
|
||||
return f.nextBoundary(inputBytes(b), len(b), atEOF)
|
||||
}
|
||||
|
||||
// NextBoundaryInString reports the index of the boundary between the first and
|
||||
// next segment in b or -1 if atEOF is false and there are not enough bytes to
|
||||
// determine this boundary.
|
||||
func (f Form) NextBoundaryInString(s string, atEOF bool) int {
|
||||
return f.nextBoundary(inputString(s), len(s), atEOF)
|
||||
}
|
||||
|
||||
func (f Form) nextBoundary(src input, nsrc int, atEOF bool) int {
|
||||
if nsrc == 0 {
|
||||
if atEOF {
|
||||
return 0
|
||||
}
|
||||
return -1
|
||||
}
|
||||
fd := formTable[f]
|
||||
info := fd.info(src, 0)
|
||||
if info.size == 0 {
|
||||
if atEOF {
|
||||
return 1
|
||||
}
|
||||
return -1
|
||||
}
|
||||
ss := streamSafe(0)
|
||||
ss.first(info)
|
||||
|
||||
for i := int(info.size); i < nsrc; i += int(info.size) {
|
||||
info = fd.info(src, i)
|
||||
if info.size == 0 {
|
||||
if atEOF {
|
||||
return i
|
||||
}
|
||||
return -1
|
||||
}
|
||||
// TODO: Using streamSafe to determine the boundary isn't the same as
|
||||
// using BoundaryBefore. Determine which should be used.
|
||||
if s := ss.next(info); s != ssSuccess {
|
||||
return i
|
||||
}
|
||||
}
|
||||
if !atEOF && !info.BoundaryAfter() && !ss.isMax() {
|
||||
return -1
|
||||
}
|
||||
return nsrc
|
||||
}
|
||||
|
||||
// LastBoundary returns the position i of the last boundary in b
|
||||
// or -1 if b contains no boundary.
|
||||
func (f Form) LastBoundary(b []byte) int {
|
||||
return lastBoundary(formTable[f], b)
|
||||
}
|
||||
|
||||
func lastBoundary(fd *formInfo, b []byte) int {
|
||||
i := len(b)
|
||||
info, p := lastRuneStart(fd, b)
|
||||
if p == -1 {
|
||||
return -1
|
||||
}
|
||||
if info.size == 0 { // ends with incomplete rune
|
||||
if p == 0 { // starts with incomplete rune
|
||||
return -1
|
||||
}
|
||||
i = p
|
||||
info, p = lastRuneStart(fd, b[:i])
|
||||
if p == -1 { // incomplete UTF-8 encoding or non-starter bytes without a starter
|
||||
return i
|
||||
}
|
||||
}
|
||||
if p+int(info.size) != i { // trailing non-starter bytes: illegal UTF-8
|
||||
return i
|
||||
}
|
||||
if info.BoundaryAfter() {
|
||||
return i
|
||||
}
|
||||
ss := streamSafe(0)
|
||||
v := ss.backwards(info)
|
||||
for i = p; i >= 0 && v != ssStarter; i = p {
|
||||
info, p = lastRuneStart(fd, b[:i])
|
||||
if v = ss.backwards(info); v == ssOverflow {
|
||||
break
|
||||
}
|
||||
if p+int(info.size) != i {
|
||||
if p == -1 { // no boundary found
|
||||
return -1
|
||||
}
|
||||
return i // boundary after an illegal UTF-8 encoding
|
||||
}
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
// decomposeSegment scans the first segment in src into rb. It inserts 0x034f
|
||||
// (Grapheme Joiner) when it encounters a sequence of more than 30 non-starters
|
||||
// and returns the number of bytes consumed from src or iShortDst or iShortSrc.
|
||||
func decomposeSegment(rb *reorderBuffer, sp int, atEOF bool) int {
|
||||
// Force one character to be consumed.
|
||||
info := rb.f.info(rb.src, sp)
|
||||
if info.size == 0 {
|
||||
return 0
|
||||
}
|
||||
if s := rb.ss.next(info); s == ssStarter {
|
||||
// TODO: this could be removed if we don't support merging.
|
||||
if rb.nrune > 0 {
|
||||
goto end
|
||||
}
|
||||
} else if s == ssOverflow {
|
||||
rb.insertCGJ()
|
||||
goto end
|
||||
}
|
||||
if err := rb.insertFlush(rb.src, sp, info); err != iSuccess {
|
||||
return int(err)
|
||||
}
|
||||
for {
|
||||
sp += int(info.size)
|
||||
if sp >= rb.nsrc {
|
||||
if !atEOF && !info.BoundaryAfter() {
|
||||
return int(iShortSrc)
|
||||
}
|
||||
break
|
||||
}
|
||||
info = rb.f.info(rb.src, sp)
|
||||
if info.size == 0 {
|
||||
if !atEOF {
|
||||
return int(iShortSrc)
|
||||
}
|
||||
break
|
||||
}
|
||||
if s := rb.ss.next(info); s == ssStarter {
|
||||
break
|
||||
} else if s == ssOverflow {
|
||||
rb.insertCGJ()
|
||||
break
|
||||
}
|
||||
if err := rb.insertFlush(rb.src, sp, info); err != iSuccess {
|
||||
return int(err)
|
||||
}
|
||||
}
|
||||
end:
|
||||
if !rb.doFlush() {
|
||||
return int(iShortDst)
|
||||
}
|
||||
return sp
|
||||
}
|
||||
|
||||
// lastRuneStart returns the runeInfo and position of the last
|
||||
// rune in buf or the zero runeInfo and -1 if no rune was found.
|
||||
func lastRuneStart(fd *formInfo, buf []byte) (Properties, int) {
|
||||
p := len(buf) - 1
|
||||
for ; p >= 0 && !utf8.RuneStart(buf[p]); p-- {
|
||||
}
|
||||
if p < 0 {
|
||||
return Properties{}, -1
|
||||
}
|
||||
return fd.info(inputBytes(buf), p), p
|
||||
}
|
||||
|
||||
// decomposeToLastBoundary finds an open segment at the end of the buffer
|
||||
// and scans it into rb. Returns the buffer minus the last segment.
|
||||
func decomposeToLastBoundary(rb *reorderBuffer) {
|
||||
fd := &rb.f
|
||||
info, i := lastRuneStart(fd, rb.out)
|
||||
if int(info.size) != len(rb.out)-i {
|
||||
// illegal trailing continuation bytes
|
||||
return
|
||||
}
|
||||
if info.BoundaryAfter() {
|
||||
return
|
||||
}
|
||||
var add [maxNonStarters + 1]Properties // stores runeInfo in reverse order
|
||||
padd := 0
|
||||
ss := streamSafe(0)
|
||||
p := len(rb.out)
|
||||
for {
|
||||
add[padd] = info
|
||||
v := ss.backwards(info)
|
||||
if v == ssOverflow {
|
||||
// Note that if we have an overflow, it the string we are appending to
|
||||
// is not correctly normalized. In this case the behavior is undefined.
|
||||
break
|
||||
}
|
||||
padd++
|
||||
p -= int(info.size)
|
||||
if v == ssStarter || p < 0 {
|
||||
break
|
||||
}
|
||||
info, i = lastRuneStart(fd, rb.out[:p])
|
||||
if int(info.size) != p-i {
|
||||
break
|
||||
}
|
||||
}
|
||||
rb.ss = ss
|
||||
// Copy bytes for insertion as we may need to overwrite rb.out.
|
||||
var buf [maxBufferSize * utf8.UTFMax]byte
|
||||
cp := buf[:copy(buf[:], rb.out[p:])]
|
||||
rb.out = rb.out[:p]
|
||||
for padd--; padd >= 0; padd-- {
|
||||
info = add[padd]
|
||||
rb.insertUnsafe(inputBytes(cp), 0, info)
|
||||
cp = cp[info.size:]
|
||||
}
|
||||
}
|
||||
125
vendor/golang.org/x/text/unicode/norm/readwriter.go
generated
vendored
Normal file
125
vendor/golang.org/x/text/unicode/norm/readwriter.go
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
// Copyright 2011 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 norm
|
||||
|
||||
import "io"
|
||||
|
||||
type normWriter struct {
|
||||
rb reorderBuffer
|
||||
w io.Writer
|
||||
buf []byte
|
||||
}
|
||||
|
||||
// Write implements the standard write interface. If the last characters are
|
||||
// not at a normalization boundary, the bytes will be buffered for the next
|
||||
// write. The remaining bytes will be written on close.
|
||||
func (w *normWriter) Write(data []byte) (n int, err error) {
|
||||
// Process data in pieces to keep w.buf size bounded.
|
||||
const chunk = 4000
|
||||
|
||||
for len(data) > 0 {
|
||||
// Normalize into w.buf.
|
||||
m := len(data)
|
||||
if m > chunk {
|
||||
m = chunk
|
||||
}
|
||||
w.rb.src = inputBytes(data[:m])
|
||||
w.rb.nsrc = m
|
||||
w.buf = doAppend(&w.rb, w.buf, 0)
|
||||
data = data[m:]
|
||||
n += m
|
||||
|
||||
// Write out complete prefix, save remainder.
|
||||
// Note that lastBoundary looks back at most 31 runes.
|
||||
i := lastBoundary(&w.rb.f, w.buf)
|
||||
if i == -1 {
|
||||
i = 0
|
||||
}
|
||||
if i > 0 {
|
||||
if _, err = w.w.Write(w.buf[:i]); err != nil {
|
||||
break
|
||||
}
|
||||
bn := copy(w.buf, w.buf[i:])
|
||||
w.buf = w.buf[:bn]
|
||||
}
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Close forces data that remains in the buffer to be written.
|
||||
func (w *normWriter) Close() error {
|
||||
if len(w.buf) > 0 {
|
||||
_, err := w.w.Write(w.buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Writer returns a new writer that implements Write(b)
|
||||
// by writing f(b) to w. The returned writer may use an
|
||||
// internal buffer to maintain state across Write calls.
|
||||
// Calling its Close method writes any buffered data to w.
|
||||
func (f Form) Writer(w io.Writer) io.WriteCloser {
|
||||
wr := &normWriter{rb: reorderBuffer{}, w: w}
|
||||
wr.rb.init(f, nil)
|
||||
return wr
|
||||
}
|
||||
|
||||
type normReader struct {
|
||||
rb reorderBuffer
|
||||
r io.Reader
|
||||
inbuf []byte
|
||||
outbuf []byte
|
||||
bufStart int
|
||||
lastBoundary int
|
||||
err error
|
||||
}
|
||||
|
||||
// Read implements the standard read interface.
|
||||
func (r *normReader) Read(p []byte) (int, error) {
|
||||
for {
|
||||
if r.lastBoundary-r.bufStart > 0 {
|
||||
n := copy(p, r.outbuf[r.bufStart:r.lastBoundary])
|
||||
r.bufStart += n
|
||||
if r.lastBoundary-r.bufStart > 0 {
|
||||
return n, nil
|
||||
}
|
||||
return n, r.err
|
||||
}
|
||||
if r.err != nil {
|
||||
return 0, r.err
|
||||
}
|
||||
outn := copy(r.outbuf, r.outbuf[r.lastBoundary:])
|
||||
r.outbuf = r.outbuf[0:outn]
|
||||
r.bufStart = 0
|
||||
|
||||
n, err := r.r.Read(r.inbuf)
|
||||
r.rb.src = inputBytes(r.inbuf[0:n])
|
||||
r.rb.nsrc, r.err = n, err
|
||||
if n > 0 {
|
||||
r.outbuf = doAppend(&r.rb, r.outbuf, 0)
|
||||
}
|
||||
if err == io.EOF {
|
||||
r.lastBoundary = len(r.outbuf)
|
||||
} else {
|
||||
r.lastBoundary = lastBoundary(&r.rb.f, r.outbuf)
|
||||
if r.lastBoundary == -1 {
|
||||
r.lastBoundary = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reader returns a new reader that implements Read
|
||||
// by reading data from r and returning f(data).
|
||||
func (f Form) Reader(r io.Reader) io.Reader {
|
||||
const chunk = 4000
|
||||
buf := make([]byte, chunk)
|
||||
rr := &normReader{rb: reorderBuffer{}, r: r, inbuf: buf}
|
||||
rr.rb.init(f, buf)
|
||||
return rr
|
||||
}
|
||||
7658
vendor/golang.org/x/text/unicode/norm/tables10.0.0.go
generated
vendored
Normal file
7658
vendor/golang.org/x/text/unicode/norm/tables10.0.0.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7694
vendor/golang.org/x/text/unicode/norm/tables11.0.0.go
generated
vendored
Normal file
7694
vendor/golang.org/x/text/unicode/norm/tables11.0.0.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7711
vendor/golang.org/x/text/unicode/norm/tables12.0.0.go
generated
vendored
Normal file
7711
vendor/golang.org/x/text/unicode/norm/tables12.0.0.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7761
vendor/golang.org/x/text/unicode/norm/tables13.0.0.go
generated
vendored
Normal file
7761
vendor/golang.org/x/text/unicode/norm/tables13.0.0.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7638
vendor/golang.org/x/text/unicode/norm/tables9.0.0.go
generated
vendored
Normal file
7638
vendor/golang.org/x/text/unicode/norm/tables9.0.0.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
88
vendor/golang.org/x/text/unicode/norm/transform.go
generated
vendored
Normal file
88
vendor/golang.org/x/text/unicode/norm/transform.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright 2013 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 norm
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// Reset implements the Reset method of the transform.Transformer interface.
|
||||
func (Form) Reset() {}
|
||||
|
||||
// Transform implements the Transform method of the transform.Transformer
|
||||
// interface. It may need to write segments of up to MaxSegmentSize at once.
|
||||
// Users should either catch ErrShortDst and allow dst to grow or have dst be at
|
||||
// least of size MaxTransformChunkSize to be guaranteed of progress.
|
||||
func (f Form) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
// Cap the maximum number of src bytes to check.
|
||||
b := src
|
||||
eof := atEOF
|
||||
if ns := len(dst); ns < len(b) {
|
||||
err = transform.ErrShortDst
|
||||
eof = false
|
||||
b = b[:ns]
|
||||
}
|
||||
i, ok := formTable[f].quickSpan(inputBytes(b), 0, len(b), eof)
|
||||
n := copy(dst, b[:i])
|
||||
if !ok {
|
||||
nDst, nSrc, err = f.transform(dst[n:], src[n:], atEOF)
|
||||
return nDst + n, nSrc + n, err
|
||||
}
|
||||
|
||||
if err == nil && n < len(src) && !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
}
|
||||
return n, n, err
|
||||
}
|
||||
|
||||
func flushTransform(rb *reorderBuffer) bool {
|
||||
// Write out (must fully fit in dst, or else it is an ErrShortDst).
|
||||
if len(rb.out) < rb.nrune*utf8.UTFMax {
|
||||
return false
|
||||
}
|
||||
rb.out = rb.out[rb.flushCopy(rb.out):]
|
||||
return true
|
||||
}
|
||||
|
||||
var errs = []error{nil, transform.ErrShortDst, transform.ErrShortSrc}
|
||||
|
||||
// transform implements the transform.Transformer interface. It is only called
|
||||
// when quickSpan does not pass for a given string.
|
||||
func (f Form) transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
// TODO: get rid of reorderBuffer. See CL 23460044.
|
||||
rb := reorderBuffer{}
|
||||
rb.init(f, src)
|
||||
for {
|
||||
// Load segment into reorder buffer.
|
||||
rb.setFlusher(dst[nDst:], flushTransform)
|
||||
end := decomposeSegment(&rb, nSrc, atEOF)
|
||||
if end < 0 {
|
||||
return nDst, nSrc, errs[-end]
|
||||
}
|
||||
nDst = len(dst) - len(rb.out)
|
||||
nSrc = end
|
||||
|
||||
// Next quickSpan.
|
||||
end = rb.nsrc
|
||||
eof := atEOF
|
||||
if n := nSrc + len(dst) - nDst; n < end {
|
||||
err = transform.ErrShortDst
|
||||
end = n
|
||||
eof = false
|
||||
}
|
||||
end, ok := rb.f.quickSpan(rb.src, nSrc, end, eof)
|
||||
n := copy(dst[nDst:], rb.src.bytes[nSrc:end])
|
||||
nSrc += n
|
||||
nDst += n
|
||||
if ok {
|
||||
if err == nil && n < rb.nsrc && !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
}
|
||||
}
|
||||
54
vendor/golang.org/x/text/unicode/norm/trie.go
generated
vendored
Normal file
54
vendor/golang.org/x/text/unicode/norm/trie.go
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2011 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 norm
|
||||
|
||||
type valueRange struct {
|
||||
value uint16 // header: value:stride
|
||||
lo, hi byte // header: lo:n
|
||||
}
|
||||
|
||||
type sparseBlocks struct {
|
||||
values []valueRange
|
||||
offset []uint16
|
||||
}
|
||||
|
||||
var nfcSparse = sparseBlocks{
|
||||
values: nfcSparseValues[:],
|
||||
offset: nfcSparseOffset[:],
|
||||
}
|
||||
|
||||
var nfkcSparse = sparseBlocks{
|
||||
values: nfkcSparseValues[:],
|
||||
offset: nfkcSparseOffset[:],
|
||||
}
|
||||
|
||||
var (
|
||||
nfcData = newNfcTrie(0)
|
||||
nfkcData = newNfkcTrie(0)
|
||||
)
|
||||
|
||||
// lookupValue determines the type of block n and looks up the value for b.
|
||||
// For n < t.cutoff, the block is a simple lookup table. Otherwise, the block
|
||||
// is a list of ranges with an accompanying value. Given a matching range r,
|
||||
// the value for b is by r.value + (b - r.lo) * stride.
|
||||
func (t *sparseBlocks) lookup(n uint32, b byte) uint16 {
|
||||
offset := t.offset[n]
|
||||
header := t.values[offset]
|
||||
lo := offset + 1
|
||||
hi := lo + uint16(header.lo)
|
||||
for lo < hi {
|
||||
m := lo + (hi-lo)/2
|
||||
r := t.values[m]
|
||||
if r.lo <= b && b <= r.hi {
|
||||
return r.value + uint16(b-r.lo)*header.value
|
||||
}
|
||||
if b < r.lo {
|
||||
hi = m
|
||||
} else {
|
||||
lo = m + 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
Reference in New Issue
Block a user