github.com/icodeface/tls@v0.0.0-20230910023335-34df9250cd12/internal/x/text/unicode/bidi/example_test.go (about)

     1  // Code generated by running "go run gen.go -core" in golang.org/x/text. DO NOT EDIT.
     2  
     3  // +build ignore
     4  
     5  package bidi_test
     6  
     7  import (
     8  	"fmt"
     9  	"log"
    10  
    11  	"github.com/icodeface/tls/internal/x/text/bidi"
    12  )
    13  
    14  func foo() {
    15  	var sa StringAttributes
    16  	var p Paragraph
    17  	n, _ := p.SetString(s)
    18  	for i, o := 0, p.Ordering(); i < o.NumRuns(); i++ {
    19  		b := o.Run(i).Bytes()
    20  
    21  		start, end := o.Run(i).Pos()
    22  		for p := start; p < end; {
    23  			style, n := sa.StyleAt(start)
    24  			render()
    25  			p += n
    26  		}
    27  
    28  	}
    29  }
    30  
    31  type style int
    32  
    33  const (
    34  	styleNormal   = 0
    35  	styleSelected = 1 << (iota - 1)
    36  	styleBold
    37  	styleItalics
    38  )
    39  
    40  type styleRun struct {
    41  	end   int
    42  	style style
    43  }
    44  
    45  func getTextWidth(text string, styleRuns []styleRun) int {
    46  	// simplistic way to compute the width
    47  	return len([]rune(text))
    48  }
    49  
    50  // set limit and StyleRun limit for a line
    51  // from text[start] and from styleRuns[styleRunStart]
    52  // using Bidi.getLogicalRun(...)
    53  // returns line width
    54  func getLineBreak(p *bidi.Paragraph, start int, styles []styleRun) (n int) {
    55  	// dummy return
    56  	return 0
    57  }
    58  
    59  // render runs on a line sequentially, always from left to right
    60  
    61  // prepare rendering a new line
    62  func startLine(d bidi.Direction, lineWidth int) {
    63  	fmt.Println()
    64  }
    65  
    66  // render a run of text and advance to the right by the run width
    67  // the text[start..limit-1] is always in logical order
    68  func renderRun(text string, d bidi.Direction, styl style) {
    69  }
    70  
    71  // We could compute a cross-product
    72  // from the style runs with the directional runs
    73  // and then reorder it.
    74  // Instead, here we iterate over each run type
    75  // and render the intersections -
    76  // with shortcuts in simple (and common) cases.
    77  // renderParagraph() is the main function.
    78  
    79  // render a directional run with
    80  // (possibly) multiple style runs intersecting with it
    81  func renderDirectionalRun(text string, offset int, d bidi.Direction, styles []styleRun) {
    82  	start, end := offset, len(text)+offset
    83  	// iterate over style runs
    84  	if run.Direction() == bidi.LeftToRight {
    85  		styleEnd := 0
    86  		for _, sr := range styles {
    87  			styleEnd = styleRuns[i].end
    88  			if start < styleEnd {
    89  				if styleEnd > end {
    90  					styleEnd = end
    91  				}
    92  				renderRun(text[start-offset:styleEnd-offset], run.Direction(), styles[i].style)
    93  				if styleEnd == end {
    94  					break
    95  				}
    96  				start = styleEnd
    97  			}
    98  		}
    99  	} else {
   100  		styleStart := 0
   101  		for i := len(styles) - 1; i >= 0; i-- {
   102  			if i > 0 {
   103  				styleStart = styles[i-1].end
   104  			} else {
   105  				styleStart = 0
   106  			}
   107  			if end >= styleStart {
   108  				if styleStart < start {
   109  					styleStart = start
   110  				}
   111  				renderRun(text[styleStart-offset:end-offset], run.Direction(), styles[i].style)
   112  				if styleStart == start {
   113  					break
   114  				}
   115  				end = styleStart
   116  			}
   117  		}
   118  	}
   119  }
   120  
   121  // the line object represents text[start..limit-1]
   122  func renderLine(line *bidi.Runs, text string, offset int, styles []styleRun) {
   123  	if dir := line.Direction(); dir != bidi.Mixed {
   124  		if len(styles) == 1 {
   125  			renderRun(text, dir, styles[0].style)
   126  		} else {
   127  			for i := 0; i < line.NumRuns(); i++ {
   128  				renderDirectionalRun(text, offset, dir, styles)
   129  			}
   130  		}
   131  	} else {
   132  		// iterate over both directional and style runs
   133  		for i := 0; i < line.Len(); i++ {
   134  			run := line.Run(i)
   135  			start, _ := run.Pos()
   136  			renderDirectionalRun(text[start-offset:], start, run.Direction(), styles)
   137  		}
   138  	}
   139  }
   140  
   141  func renderParagraph(text string, d bidi.Direction, styles []styleRun, int lineWidth) {
   142  	var p bidi.Paragraph
   143  	if err := p.SetString(text, bidi.DefaultDirection(d)); err != nil {
   144  		log.Fatal(err)
   145  	}
   146  
   147  	if len(styles) == 0 {
   148  		styles = append(styles, []styleRun{len(text), styleNormal})
   149  	}
   150  
   151  	if width := getTextWidth(text, styles); width <= lineWidth {
   152  		// everything fits onto one line
   153  
   154  		runs, err := p.Runs()
   155  		if err != nil {
   156  			log.Fatal(err)
   157  		}
   158  
   159  		// prepare rendering a new line from either left or right
   160  		startLine(p.Direction(), width)
   161  		renderLine(&runs, text, styles)
   162  	} else {
   163  		// we need to render several lines
   164  
   165  		for start, end := 0, 0; start < len(text); start = end {
   166  			for start >= styles[0].end {
   167  				styles = styles[1:]
   168  			}
   169  			end = getLineBreak(p, start, styles[startStyles:])
   170  
   171  			runs, err := p.Line(start, end)
   172  			if err != nil {
   173  				log.Fatal(err)
   174  			}
   175  
   176  			startLine(p.Direction(), end-start)
   177  			renderLine(&runs, text[start:end], styles[startStyles:])
   178  		}
   179  	}
   180  }
   181  
   182  func main() {
   183  	renderParagraph("Some Latin text...", bidi.LeftToRight, nil, 80)
   184  	renderParagraph("Some Hebrew text...", bidi.RightToLeft, nil, 60)
   185  }