| // Code generated by running "go run gen.go -core" in golang.org/x/text. DO NOT EDIT. | |
| // +build ignore | |
| package bidi_test | |
| import ( | |
| "fmt" | |
| "log" | |
| "internal/x/text/bidi" | |
| ) | |
| func foo() { | |
| var sa StringAttributes | |
| var p Paragraph | |
| n, _ := p.SetString(s) | |
| for i, o := 0, p.Ordering(); i < o.NumRuns(); i++ { | |
| b := o.Run(i).Bytes() | |
| start, end := o.Run(i).Pos() | |
| for p := start; p < end; { | |
| style, n := sa.StyleAt(start) | |
| render() | |
| p += n | |
| } | |
| } | |
| } | |
| type style int | |
| const ( | |
| styleNormal = 0 | |
| styleSelected = 1 << (iota - 1) | |
| styleBold | |
| styleItalics | |
| ) | |
| type styleRun struct { | |
| end int | |
| style style | |
| } | |
| func getTextWidth(text string, styleRuns []styleRun) int { | |
| // simplistic way to compute the width | |
| return len([]rune(text)) | |
| } | |
| // set limit and StyleRun limit for a line | |
| // from text[start] and from styleRuns[styleRunStart] | |
| // using Bidi.getLogicalRun(...) | |
| // returns line width | |
| func getLineBreak(p *bidi.Paragraph, start int, styles []styleRun) (n int) { | |
| // dummy return | |
| return 0 | |
| } | |
| // render runs on a line sequentially, always from left to right | |
| // prepare rendering a new line | |
| func startLine(d bidi.Direction, lineWidth int) { | |
| fmt.Println() | |
| } | |
| // render a run of text and advance to the right by the run width | |
| // the text[start..limit-1] is always in logical order | |
| func renderRun(text string, d bidi.Direction, styl style) { | |
| } | |
| // We could compute a cross-product | |
| // from the style runs with the directional runs | |
| // and then reorder it. | |
| // Instead, here we iterate over each run type | |
| // and render the intersections - | |
| // with shortcuts in simple (and common) cases. | |
| // renderParagraph() is the main function. | |
| // render a directional run with | |
| // (possibly) multiple style runs intersecting with it | |
| func renderDirectionalRun(text string, offset int, d bidi.Direction, styles []styleRun) { | |
| start, end := offset, len(text)+offset | |
| // iterate over style runs | |
| if run.Direction() == bidi.LeftToRight { | |
| styleEnd := 0 | |
| for _, sr := range styles { | |
| styleEnd = styleRuns[i].end | |
| if start < styleEnd { | |
| if styleEnd > end { | |
| styleEnd = end | |
| } | |
| renderRun(text[start-offset:styleEnd-offset], run.Direction(), styles[i].style) | |
| if styleEnd == end { | |
| break | |
| } | |
| start = styleEnd | |
| } | |
| } | |
| } else { | |
| styleStart := 0 | |
| for i := len(styles) - 1; i >= 0; i-- { | |
| if i > 0 { | |
| styleStart = styles[i-1].end | |
| } else { | |
| styleStart = 0 | |
| } | |
| if end >= styleStart { | |
| if styleStart < start { | |
| styleStart = start | |
| } | |
| renderRun(text[styleStart-offset:end-offset], run.Direction(), styles[i].style) | |
| if styleStart == start { | |
| break | |
| } | |
| end = styleStart | |
| } | |
| } | |
| } | |
| } | |
| // the line object represents text[start..limit-1] | |
| func renderLine(line *bidi.Runs, text string, offset int, styles []styleRun) { | |
| if dir := line.Direction(); dir != bidi.Mixed { | |
| if len(styles) == 1 { | |
| renderRun(text, dir, styles[0].style) | |
| } else { | |
| for i := 0; i < line.NumRuns(); i++ { | |
| renderDirectionalRun(text, offset, dir, styles) | |
| } | |
| } | |
| } else { | |
| // iterate over both directional and style runs | |
| for i := 0; i < line.Len(); i++ { | |
| run := line.Run(i) | |
| start, _ := run.Pos() | |
| renderDirectionalRun(text[start-offset:], start, run.Direction(), styles) | |
| } | |
| } | |
| } | |
| func renderParagraph(text string, d bidi.Direction, styles []styleRun, int lineWidth) { | |
| var p bidi.Paragraph | |
| if err := p.SetString(text, bidi.DefaultDirection(d)); err != nil { | |
| log.Fatal(err) | |
| } | |
| if len(styles) == 0 { | |
| styles = append(styles, []styleRun{len(text), styleNormal}) | |
| } | |
| if width := getTextWidth(text, styles); width <= lineWidth { | |
| // everything fits onto one line | |
| runs, err := p.Runs() | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| // prepare rendering a new line from either left or right | |
| startLine(p.Direction(), width) | |
| renderLine(&runs, text, styles) | |
| } else { | |
| // we need to render several lines | |
| for start, end := 0, 0; start < len(text); start = end { | |
| for start >= styles[0].end { | |
| styles = styles[1:] | |
| } | |
| end = getLineBreak(p, start, styles[startStyles:]) | |
| runs, err := p.Line(start, end) | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| startLine(p.Direction(), end-start) | |
| renderLine(&runs, text[start:end], styles[startStyles:]) | |
| } | |
| } | |
| } | |
| func main() { | |
| renderParagraph("Some Latin text...", bidi.LeftToRight, nil, 80) | |
| renderParagraph("Some Hebrew text...", bidi.RightToLeft, nil, 60) | |
| } |