1// Copyright 2015 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// This example shows how to draw some bi-directional text using the raw 6// interface to the engine. 7 8import 'dart:typed_data'; 9import 'dart:ui' as ui; 10 11// A paragraph represents a rectangular region that contains some text. 12ui.Paragraph paragraph; 13 14ui.Picture paint(ui.Rect paintBounds) { 15 final ui.PictureRecorder recorder = ui.PictureRecorder(); 16 final ui.Canvas canvas = ui.Canvas(recorder, paintBounds); 17 18 final double devicePixelRatio = ui.window.devicePixelRatio; 19 final ui.Size logicalSize = ui.window.physicalSize / devicePixelRatio; 20 21 canvas.translate(logicalSize.width / 2.0, logicalSize.height / 2.0); 22 canvas.drawRect(const ui.Rect.fromLTRB(-100.0, -100.0, 100.0, 100.0), 23 ui.Paint()..color = const ui.Color.fromARGB(255, 0, 255, 0)); 24 25 // The paint method of Paragraph draws the contents of the paragraph onto the 26 // given canvas. 27 canvas.drawParagraph(paragraph, ui.Offset(-paragraph.width / 2.0, (paragraph.width / 2.0) - 125.0)); 28 29 return recorder.endRecording(); 30} 31 32ui.Scene composite(ui.Picture picture, ui.Rect paintBounds) { 33 final double devicePixelRatio = ui.window.devicePixelRatio; 34 final Float64List deviceTransform = Float64List(16) 35 ..[0] = devicePixelRatio 36 ..[5] = devicePixelRatio 37 ..[10] = 1.0 38 ..[15] = 1.0; 39 final ui.SceneBuilder sceneBuilder = ui.SceneBuilder() 40 ..pushTransform(deviceTransform) 41 ..addPicture(ui.Offset.zero, picture) 42 ..pop(); 43 return sceneBuilder.build(); 44} 45 46void beginFrame(Duration timeStamp) { 47 final ui.Rect paintBounds = ui.Offset.zero & (ui.window.physicalSize / ui.window.devicePixelRatio); 48 final ui.Picture picture = paint(paintBounds); 49 final ui.Scene scene = composite(picture, paintBounds); 50 ui.window.render(scene); 51} 52 53void main() { 54 // To create a paragraph of text, we use ParagraphBuilder. 55 final ui.ParagraphBuilder builder = ui.ParagraphBuilder( 56 // The text below has a primary direction of left-to-right. 57 // The embedded text has other directions. 58 // If this was TextDirection.rtl, the "Hello, world" text would end up on 59 // the other side of the right-to-left text. 60 ui.ParagraphStyle(textDirection: ui.TextDirection.ltr), 61 ) 62 // We first push a style that turns the text blue. 63 ..pushStyle(ui.TextStyle(color: const ui.Color(0xFF0000FF))) 64 ..addText('Hello, ') 65 // The next run of text will be bold. 66 ..pushStyle(ui.TextStyle(fontWeight: ui.FontWeight.bold)) 67 ..addText('world. ') 68 // The pop() command signals the end of the bold styling. 69 ..pop() 70 // We add text to the paragraph in logical order. The paragraph object 71 // understands bi-directional text and will compute the visual ordering 72 // during layout. 73 ..addText('هذا هو قليلا طويلة من النص الذي يجب التفاف .') 74 // The second pop() removes the blue color. 75 ..pop() 76 // We can add more text with the default styling. 77 ..addText(' و أكثر قليلا لجعله أطول. ') 78 ..addText('สวัสดี'); 79 // When we're done adding styles and text, we build the Paragraph object, at 80 // which time we can apply styling that affects the entire paragraph, such as 81 // left, right, or center alignment. Once built, the contents of the paragraph 82 // cannot be altered, but sizing and positioning information can be updated. 83 paragraph = builder.build() 84 // Next, we supply a width that the text is permitted to occupy and we ask 85 // the paragraph to the visual position of each its glyphs as well as its 86 // overall size, subject to its sizing constraints. 87 ..layout(const ui.ParagraphConstraints(width: 180.0)); 88 89 // Finally, we register our beginFrame callback and kick off the first frame. 90 ui.window.onBeginFrame = beginFrame; 91 ui.window.scheduleFrame(); 92} 93