This repository has been archived by the owner on Dec 31, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 101
/
AllocatedGlyphRanges.go
86 lines (78 loc) · 2.53 KB
/
AllocatedGlyphRanges.go
1
2
3
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package imgui
// #include <stdlib.h>
import "C"
import (
"unsafe"
)
// AllocatedGlyphRanges are GlyphRanges dynamically allocated by the application.
// Such ranges need to be freed when they are no longer in use to avoid resource leak.
type AllocatedGlyphRanges struct {
GlyphRanges
}
// Free releases the underlying memory of the ranges.
// Call this method when the ranges are no longer in use.
func (ranges *AllocatedGlyphRanges) Free() {
C.free(unsafe.Pointer(ranges.GlyphRanges.handle()))
ranges.GlyphRanges = 0
}
// GlyphRangesBuilder can be used to create a new, combined, set of ranges.
type GlyphRangesBuilder struct {
ranges []glyphRange
}
// Build combines all the currently registered ranges and creates a new instance.
// The returned ranges object needs to be explicitly freed in order to release resources.
func (builder *GlyphRangesBuilder) Build() AllocatedGlyphRanges {
const bytesPerUint16 = 2
const uint16PerRangeEntry = 2
ranges := builder.mergedRanges()
raw := C.malloc(C.size_t(bytesPerUint16 * ((len(ranges) * uint16PerRangeEntry) + 1)))
rawSlice := ptrToUint16Slice(raw)
outIndex := 0
for _, r := range ranges {
rawSlice[outIndex+0] = r.from
rawSlice[outIndex+1] = r.to
outIndex += 2
}
rawSlice[outIndex] = 0
return AllocatedGlyphRanges{GlyphRanges: GlyphRanges(raw)}
}
// AddExisting adds the given set of ranges to the builder.
// The provided ranges are immediately extracted.
func (builder *GlyphRangesBuilder) AddExisting(ranges ...GlyphRanges) {
for _, rawRange := range ranges {
builder.ranges = append(builder.ranges, rawRange.extract()...)
}
}
// Add extends the builder with the given range (inclusive).
// from must be smaller, or equal to, to - otherwise the range is ignored.
func (builder *GlyphRangesBuilder) Add(from, to rune) {
if from > to {
return
}
builder.ranges = append(builder.ranges, glyphRange{from: uint16(from), to: uint16(to)})
}
func (builder *GlyphRangesBuilder) mergedRanges() []glyphRange {
result := make([]glyphRange, 0, len(builder.ranges))
add := func(candidate glyphRange) {
merged := false
for index := 0; !merged && (index < len(result)); index++ {
existing := &result[index]
if (existing.from <= candidate.to) && (existing.to >= candidate.from) {
if existing.from > candidate.from {
existing.from = candidate.from
}
if existing.to < candidate.to {
existing.to = candidate.to
}
merged = true
}
}
if !merged {
result = append(result, candidate)
}
}
for _, candidate := range builder.ranges {
add(candidate)
}
return result
}