func readBitBox()

in arm64/arm64spec/spec.go [428:617]


func readBitBox(name string, content pdf.Content, text []pdf.Text, i int) (string, int) {
	// Bits headings
	y3 := 0.0
	x1 := 0.0
	for i < len(text) && match(text[i], "Arial", 8, "") {
		if y3 == 0 {
			y3 = text[i].Y
		}
		if x1 == 0 {
			x1 = text[i].X
		}
		if text[i].Y != y3 {
			break
		}
		i++
	}
	// Bits fields in box
	x2 := 0.0
	y2 := 0.0
	dy1 := 0.0
	for i < len(text) && match(text[i], "Arial", 8, "") {
		if x2 < text[i].X+text[i].W {
			x2 = text[i].X + text[i].W
		}
		if y2 == 0 {
			y2 = text[i].Y
		}
		if text[i].Y != y2 {
			break
		}
		dy1 = text[i].FontSize
		i++
	}
	// Bits fields below box
	x3 := 0.0
	y1 := 0.0
	for i < len(text) && match(text[i], "Arial", 8, "") {
		if x3 < text[i].X+text[i].W {
			x3 = text[i].X + text[i].W
		}
		y1 = text[i].Y
		if text[i].Y != y1 {
			break
		}
		i++
	}
	//no bits fields below box
	below_flag := true
	if y1 == 0.0 {
		below_flag = false
		y1 = y2
	}
	// Encoding box
	if debugPage > 0 {
		fmt.Println("encoding box", x1, y3, x2, y1)
	}

	// Find lines (thin rectangles) separating bit fields.
	var bottom, top pdf.Rect
	const (
		yMargin = 0.25 * 72
		xMargin = 2 * 72
	)
	cont := 0
	if below_flag == true {
		for _, r := range content.Rect {
			cont = cont + 1
			if x1-xMargin < r.Min.X && r.Min.X < x1 && x2 < r.Max.X && r.Max.X < x2+xMargin {
				if y1-yMargin < r.Min.Y && r.Min.Y < y2-dy1 {
					bottom = r
				}
				if y2+dy1 < r.Min.Y && r.Min.Y < y3+yMargin {
					top = r
				}
			}
		}
	} else {
		for _, r := range content.Rect {
			cont = cont + 1
			if x1-xMargin < r.Min.X && r.Min.X < x1 && x2 < r.Max.X && r.Max.X < x2+xMargin {
				if y1-yMargin-dy1 < r.Min.Y && r.Min.Y < y3-dy1 {
					bottom = r
				}
				if y2+dy1 < r.Min.Y && r.Min.Y < y3+yMargin {
					top = r
				}
			}
		}
	}

	if debugPage > 0 {
		fmt.Println("top", top, "bottom", bottom, "content.Rect number", cont)
	}

	const ε = 0.5 * 72
	cont_1 := 0
	var bars []pdf.Rect
	for _, r := range content.Rect {
		if math.Abs(r.Min.X-r.Max.X) < bottom.Max.X-bottom.Min.X-(ε/2) && math.Abs(r.Min.Y-bottom.Min.Y) < ε && math.Abs(r.Max.Y-top.Min.Y) < ε {
			cont_1 = cont_1 + 1
			bars = append(bars, r)
		}
	}
	sort.Sort(RectHorizontal(bars))
	if debugPage > 0 {
		fmt.Println("==bars number==", cont_1)
	}

	// There are 16-bit and 32-bit encodings.
	// In practice, they are about 2.65 and 5.3 inches wide, respectively.
	// Use 4 inches as a cutoff.
	nbit := 32
	dx := top.Max.X - top.Min.X
	if top.Max.X-top.Min.X < 4*72 {
		nbit = 16
	}

	total := 0
	var buf bytes.Buffer
	for i := 0; i < len(bars); i++ {
		if i > 0 {
			fmt.Fprintf(&buf, "|")
		}
		var sub []pdf.Text
		x1, x2 := bars[i].Min.X, bars[i].Max.X
		for _, t := range content.Text {
			tx := t.X + t.W/2
			ty := t.Y
			if x1 < tx && tx < x2 && y2-dy1 < ty && ty < y2+dy1 {
				sub = append(sub, t)
			}
		}
		var str []string
		for _, t := range findWords(sub) {
			str = append(str, t.S)
		}
		s := strings.Join(str, " ")
		s = strings.Replace(s, ")(", ") (", -1)

		// If bits contain "!" or "x", be replaced by the bits below it.
		if strings.Contains(s, "!") || strings.Contains(s, "x") {
			var sub1 []pdf.Text
			for _, t := range content.Text {
				tx := t.X + t.W/2
				ty := t.Y
				if x1 < tx && tx < x2 && y1-dy1 < ty && ty < y1+dy1 {
					sub1 = append(sub1, t)
				}

			}
			var str1 []string
			for _, t := range findWords(sub1) {
				str1 = append(str1, t.S)
			}
			s = strings.Join(str1, " ")
			s = strings.Replace(s, ")(", ") (", -1)
		}

		n := len(strings.Fields(s))

		var b int
		if IMMRE.MatchString(s) {
			bitNum := strings.TrimPrefix(s, "imm")
			b, _ = strconv.Atoi(bitNum)
		} else if s == "immhi" {
			b = 19
		} else {
			b = int(float64(nbit)*(x2-x1)/dx + 0.5)
		}
		if n == b {
			for k, f := range strings.Fields(s) {
				if k > 0 {
					fmt.Fprintf(&buf, "|")
				}
				fmt.Fprintf(&buf, "%s", f)
			}
		} else {
			if n != 1 {
				fmt.Fprintf(os.Stderr, "%s - multi-field %d-bit encoding: %s\n", name, n, s)
			}
			fmt.Fprintf(&buf, "%s:%d", s, b)
		}
		total += b
	}

	if total != nbit || total == 0 {
		fmt.Fprintf(os.Stderr, "%s - %d-bit encoding\n", name, total)
	}
	return buf.String(), i
}