// SPDX-License-Identifier: Unlicense OR BSD-3-Clause

package tables

import (
	"encoding/binary"
	"fmt"
)

// Code generated by binarygen from glyphs_bitmap_src.go. DO NOT EDIT

func (item *BigGlyphMetrics) mustParse(src []byte) {
	_ = src[7] // early bound checking
	item.SmallGlyphMetrics.mustParse(src[0:])
	item.vertBearingX = int8(src[5])
	item.vertBearingY = int8(src[6])
	item.vertAdvance = src[7]
}

func (item *BitmapSize) mustParse(src []byte) {
	_ = src[47] // early bound checking
	item.indexSubTableArrayOffset = Offset32(binary.BigEndian.Uint32(src[0:]))
	item.indexTablesSize = binary.BigEndian.Uint32(src[4:])
	item.numberOfIndexSubTables = binary.BigEndian.Uint32(src[8:])
	item.colorRef = binary.BigEndian.Uint32(src[12:])
	item.Hori.mustParse(src[16:])
	item.Vert.mustParse(src[28:])
	item.startGlyphIndex = binary.BigEndian.Uint16(src[40:])
	item.endGlyphIndex = binary.BigEndian.Uint16(src[42:])
	item.PpemX = src[44]
	item.PpemY = src[45]
	item.bitDepth = src[46]
	item.flags = int8(src[47])
}

func (item *GlyphIdOffsetPair) mustParse(src []byte) {
	_ = src[3] // early bound checking
	item.GlyphID = binary.BigEndian.Uint16(src[0:])
	item.SbitOffset = Offset16(binary.BigEndian.Uint16(src[2:]))
}

func (item *IndexData2) mustParse(src []byte) {
	_ = src[11] // early bound checking
	item.ImageSize = binary.BigEndian.Uint32(src[0:])
	item.BigMetrics.mustParse(src[4:])
}

func (item *IndexSubTableHeader) mustParse(src []byte) {
	_ = src[7] // early bound checking
	item.FirstGlyph = binary.BigEndian.Uint16(src[0:])
	item.LastGlyph = binary.BigEndian.Uint16(src[2:])
	item.additionalOffsetToIndexSubtable = Offset32(binary.BigEndian.Uint32(src[4:]))
}

func ParseBitmapData17(src []byte) (BitmapData17, int, error) {
	var item BitmapData17
	n := 0
	if L := len(src); L < 9 {
		return item, 0, fmt.Errorf("reading BitmapData17: "+"EOF: expected length: 9, got %d", L)
	}
	_ = src[8] // early bound checking
	item.SmallGlyphMetrics.mustParse(src[0:])
	arrayLengthImage := int(binary.BigEndian.Uint32(src[5:]))
	n += 9

	{

		L := int(9 + arrayLengthImage)
		if len(src) < L {
			return item, 0, fmt.Errorf("reading BitmapData17: "+"EOF: expected length: %d, got %d", L, len(src))
		}
		item.Image = src[9:L]
		n = L
	}
	return item, n, nil
}

func ParseBitmapData18(src []byte) (BitmapData18, int, error) {
	var item BitmapData18
	n := 0
	if L := len(src); L < 12 {
		return item, 0, fmt.Errorf("reading BitmapData18: "+"EOF: expected length: 12, got %d", L)
	}
	_ = src[11] // early bound checking
	item.BigGlyphMetrics.mustParse(src[0:])
	arrayLengthImage := int(binary.BigEndian.Uint32(src[8:]))
	n += 12

	{

		L := int(12 + arrayLengthImage)
		if len(src) < L {
			return item, 0, fmt.Errorf("reading BitmapData18: "+"EOF: expected length: %d, got %d", L, len(src))
		}
		item.Image = src[12:L]
		n = L
	}
	return item, n, nil
}

func ParseBitmapData19(src []byte) (BitmapData19, int, error) {
	var item BitmapData19
	n := 0
	if L := len(src); L < 4 {
		return item, 0, fmt.Errorf("reading BitmapData19: "+"EOF: expected length: 4, got %d", L)
	}
	arrayLengthImage := int(binary.BigEndian.Uint32(src[0:]))
	n += 4

	{

		L := int(4 + arrayLengthImage)
		if len(src) < L {
			return item, 0, fmt.Errorf("reading BitmapData19: "+"EOF: expected length: %d, got %d", L, len(src))
		}
		item.Image = src[4:L]
		n = L
	}
	return item, n, nil
}

func ParseBitmapData2(src []byte) (BitmapData2, int, error) {
	var item BitmapData2
	n := 0
	if L := len(src); L < 5 {
		return item, 0, fmt.Errorf("reading BitmapData2: "+"EOF: expected length: 5, got %d", L)
	}
	item.SmallGlyphMetrics.mustParse(src[0:])
	n += 5

	{

		item.Image = src[5:]
		n = len(src)
	}
	return item, n, nil
}

func ParseBitmapData5(src []byte) (BitmapData5, int, error) {
	var item BitmapData5
	n := 0
	{

		item.Image = src[0:]
		n = len(src)
	}
	return item, n, nil
}

func ParseCBLC(src []byte) (CBLC, int, error) {
	var item CBLC
	n := 0
	if L := len(src); L < 8 {
		return item, 0, fmt.Errorf("reading CBLC: "+"EOF: expected length: 8, got %d", L)
	}
	_ = src[7] // early bound checking
	item.majorVersion = binary.BigEndian.Uint16(src[0:])
	item.minorVersion = binary.BigEndian.Uint16(src[2:])
	arrayLengthBitmapSizes := int(binary.BigEndian.Uint32(src[4:]))
	n += 8

	{

		if L := len(src); L < 8+arrayLengthBitmapSizes*48 {
			return item, 0, fmt.Errorf("reading CBLC: "+"EOF: expected length: %d, got %d", 8+arrayLengthBitmapSizes*48, L)
		}

		item.BitmapSizes = make([]BitmapSize, arrayLengthBitmapSizes) // allocation guarded by the previous check
		for i := range item.BitmapSizes {
			item.BitmapSizes[i].mustParse(src[8+i*48:])
		}
		n += arrayLengthBitmapSizes * 48
	}
	{

		err := item.parseIndexSubTables(src[:])
		if err != nil {
			return item, 0, fmt.Errorf("reading CBLC: %s", err)
		}
	}
	return item, n, nil
}

func ParseIndexData1(src []byte, sbitOffsetsCount int) (IndexData1, int, error) {
	var item IndexData1
	n := 0
	{

		if L := len(src); L < sbitOffsetsCount*4 {
			return item, 0, fmt.Errorf("reading IndexData1: "+"EOF: expected length: %d, got %d", sbitOffsetsCount*4, L)
		}

		item.SbitOffsets = make([]Offset32, sbitOffsetsCount) // allocation guarded by the previous check
		for i := range item.SbitOffsets {
			item.SbitOffsets[i] = Offset32(binary.BigEndian.Uint32(src[i*4:]))
		}
		n += sbitOffsetsCount * 4
	}
	return item, n, nil
}

func ParseIndexData2(src []byte) (IndexData2, int, error) {
	var item IndexData2
	n := 0
	if L := len(src); L < 12 {
		return item, 0, fmt.Errorf("reading IndexData2: "+"EOF: expected length: 12, got %d", L)
	}
	item.mustParse(src)
	n += 12
	return item, n, nil
}

func ParseIndexData3(src []byte, sbitOffsetsCount int) (IndexData3, int, error) {
	var item IndexData3
	n := 0
	{

		if L := len(src); L < sbitOffsetsCount*2 {
			return item, 0, fmt.Errorf("reading IndexData3: "+"EOF: expected length: %d, got %d", sbitOffsetsCount*2, L)
		}

		item.SbitOffsets = make([]Offset16, sbitOffsetsCount) // allocation guarded by the previous check
		for i := range item.SbitOffsets {
			item.SbitOffsets[i] = Offset16(binary.BigEndian.Uint16(src[i*2:]))
		}
		n += sbitOffsetsCount * 2
	}
	return item, n, nil
}

func ParseIndexData4(src []byte) (IndexData4, int, error) {
	var item IndexData4
	n := 0
	if L := len(src); L < 4 {
		return item, 0, fmt.Errorf("reading IndexData4: "+"EOF: expected length: 4, got %d", L)
	}
	item.numGlyphs = binary.BigEndian.Uint32(src[0:])
	n += 4

	{
		arrayLength := int(item.numGlyphs + 1)

		if L := len(src); L < 4+arrayLength*4 {
			return item, 0, fmt.Errorf("reading IndexData4: "+"EOF: expected length: %d, got %d", 4+arrayLength*4, L)
		}

		item.GlyphArray = make([]GlyphIdOffsetPair, arrayLength) // allocation guarded by the previous check
		for i := range item.GlyphArray {
			item.GlyphArray[i].mustParse(src[4+i*4:])
		}
		n += arrayLength * 4
	}
	return item, n, nil
}

func ParseIndexData5(src []byte) (IndexData5, int, error) {
	var item IndexData5
	n := 0
	if L := len(src); L < 16 {
		return item, 0, fmt.Errorf("reading IndexData5: "+"EOF: expected length: 16, got %d", L)
	}
	_ = src[15] // early bound checking
	item.ImageSize = binary.BigEndian.Uint32(src[0:])
	item.BigMetrics.mustParse(src[4:])
	arrayLengthGlyphIdArray := int(binary.BigEndian.Uint32(src[12:]))
	n += 16

	{

		if L := len(src); L < 16+arrayLengthGlyphIdArray*2 {
			return item, 0, fmt.Errorf("reading IndexData5: "+"EOF: expected length: %d, got %d", 16+arrayLengthGlyphIdArray*2, L)
		}

		item.GlyphIdArray = make([]uint16, arrayLengthGlyphIdArray) // allocation guarded by the previous check
		for i := range item.GlyphIdArray {
			item.GlyphIdArray[i] = binary.BigEndian.Uint16(src[16+i*2:])
		}
		n += arrayLengthGlyphIdArray * 2
	}
	return item, n, nil
}

func ParseIndexSubHeader(src []byte, sbitOffsetsCount int) (IndexSubHeader, int, error) {
	var item IndexSubHeader
	n := 0
	if L := len(src); L < 8 {
		return item, 0, fmt.Errorf("reading IndexSubHeader: "+"EOF: expected length: 8, got %d", L)
	}
	_ = src[7] // early bound checking
	item.indexFormat = indexVersion(binary.BigEndian.Uint16(src[0:]))
	item.ImageFormat = binary.BigEndian.Uint16(src[2:])
	item.ImageDataOffset = Offset32(binary.BigEndian.Uint32(src[4:]))
	n += 8

	{
		var (
			read int
			err  error
		)
		switch item.indexFormat {
		case indexVersion1:
			item.IndexData, read, err = ParseIndexData1(src[8:], sbitOffsetsCount)
		case indexVersion2:
			item.IndexData, read, err = ParseIndexData2(src[8:])
		case indexVersion3:
			item.IndexData, read, err = ParseIndexData3(src[8:], sbitOffsetsCount)
		case indexVersion4:
			item.IndexData, read, err = ParseIndexData4(src[8:])
		case indexVersion5:
			item.IndexData, read, err = ParseIndexData5(src[8:])
		default:
			err = fmt.Errorf("unsupported IndexDataVersion %d", item.indexFormat)
		}
		if err != nil {
			return item, 0, fmt.Errorf("reading IndexSubHeader: %s", err)
		}
		n += read
	}
	return item, n, nil
}

func ParseIndexSubTableArray(src []byte, subtablesCount int) (IndexSubTableArray, int, error) {
	var item IndexSubTableArray
	n := 0
	{

		if L := len(src); L < subtablesCount*8 {
			return item, 0, fmt.Errorf("reading IndexSubTableArray: "+"EOF: expected length: %d, got %d", subtablesCount*8, L)
		}

		item.Subtables = make([]IndexSubTableHeader, subtablesCount) // allocation guarded by the previous check
		for i := range item.Subtables {
			item.Subtables[i].mustParse(src[i*8:])
		}
		n += subtablesCount * 8
	}
	return item, n, nil
}

func (item *SbitLineMetrics) mustParse(src []byte) {
	_ = src[11] // early bound checking
	item.Ascender = int8(src[0])
	item.Descender = int8(src[1])
	item.widthMax = src[2]
	item.caretSlopeNumerator = int8(src[3])
	item.caretSlopeDenominator = int8(src[4])
	item.caretOffset = int8(src[5])
	item.minOriginSB = int8(src[6])
	item.minAdvanceSB = int8(src[7])
	item.MaxBeforeBL = int8(src[8])
	item.MinAfterBL = int8(src[9])
	item.pad1 = int8(src[10])
	item.pad2 = int8(src[11])
}

func (item *SmallGlyphMetrics) mustParse(src []byte) {
	_ = src[4] // early bound checking
	item.Height = src[0]
	item.Width = src[1]
	item.BearingX = int8(src[2])
	item.BearingY = int8(src[3])
	item.Advance = src[4]
}
