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

package opentype

import (
	
	
	
	
)

// An Entry in an OpenType table.
type otfEntry struct {
	Tag      Tag
	CheckSum uint32
	Offset   uint32
	Length   uint32
}

const (
	otfHeaderSize = 12
	otfEntrySize  = 16
)

func readOTFHeader( io.Reader) ( Tag,  uint16,  error) {
	var  [otfHeaderSize]byte
	if ,  := .Read([:]);  != nil {
		return 0, 0, fmt.Errorf("invalid OpenType header: %s", )
	}

	return NewTag([0], [1], [2], [3]), binary.BigEndian.Uint16([4:6]), nil
}

func readOTFEntry( io.Reader) (otfEntry, error) {
	var (
		   [otfEntrySize]byte
		 otfEntry
	)
	if ,  := io.ReadFull(, [:]);  != nil {
		return , fmt.Errorf("invalid directory entry: %s", )
	}

	.Tag = Tag(binary.BigEndian.Uint32([0:4]))
	.CheckSum = binary.BigEndian.Uint32([4:8])
	.Offset = binary.BigEndian.Uint32([8:12])
	.Length = binary.BigEndian.Uint32([12:16])

	return , nil
}

// parseOTF reads an OpenTyp (.otf) or TrueType (.ttf) file and returns a Font.
// If the parsing fails, then an error is returned and Font will be nil.
// `offset` is the beginning of the ressource in the file (non zero for collections)
// `relativeOffset` is true when the table offset are expresed relatively to the ressource start
// (that is, `offset`) rather than to the file start.
func parseOTF( Resource,  uint32,  bool) (*Loader, error) {
	,  := .Seek(int64(), io.SeekStart)
	if  != nil {
		return nil, fmt.Errorf("invalid offset: %s", )
	}

	, ,  := readOTFHeader()
	if  != nil {
		return nil, 
	}

	 := &Loader{
		file:   ,
		tables: make(map[Tag]tableSection, ),
		Type:   ,
	}

	for  := 0;  < int(); ++ {
		,  := readOTFEntry()
		if  != nil {
			return nil, 
		}

		if ,  := .tables[.Tag];  {
			// ignore duplicate tables – the first one wins
			continue
		}

		 := tableSection{
			offset: .Offset,
			length: .Length,
		}
		// adapt the relative offsets
		if  {
			.offset += 
			if .offset <  { // check for overflow
				return nil, errors.New("unsupported table offset or length")
			}
		}
		.tables[.Tag] = 
	}

	return , nil
}