| // 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) |
| } |