github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/exp/shiny/screen/screen.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package screen provides interfaces for portable two-dimensional graphics and
     6  // input events.
     7  //
     8  // Screens are not created directly. Instead, driver packages provide access to
     9  // the screen through a Main function that is designed to be called by the
    10  // program's main function. The golang.org/x/exp/shiny/driver package provides
    11  // the default driver for the system, such as the X11 driver for desktop Linux,
    12  // but other drivers, such as the OpenGL driver, can be explicitly invoked by
    13  // calling that driver's Main function. To use the default driver:
    14  //
    15  //	package main
    16  //
    17  //	import (
    18  //		"golang.org/x/exp/shiny/driver"
    19  //		"golang.org/x/exp/shiny/screen"
    20  //	)
    21  //
    22  //	func main() {
    23  //		driver.Main(func(s screen.Screen) {
    24  //			w, err := s.NewWindow(nil)
    25  //			if err != nil {
    26  //				handleError(err)
    27  //				return
    28  //			}
    29  //			for e := range w.Events() {
    30  //				handleEvent(e)
    31  //			}
    32  //		})
    33  //	}
    34  package screen
    35  
    36  import (
    37  	"image"
    38  	"image/color"
    39  	"image/draw"
    40  
    41  	"golang.org/x/image/math/f64"
    42  )
    43  
    44  // TODO: specify image format (Alpha or Gray, not just RGBA) for NewBuffer
    45  // and/or NewTexture?
    46  
    47  // Screen creates Buffers, Textures and Windows.
    48  type Screen interface {
    49  	// NewBuffer returns a new Buffer for this screen.
    50  	NewBuffer(size image.Point) (Buffer, error)
    51  
    52  	// NewTexture returns a new Texture for this screen.
    53  	NewTexture(size image.Point) (Texture, error)
    54  
    55  	// NewWindow returns a new Window for this screen.
    56  	NewWindow(opts *NewWindowOptions) (Window, error)
    57  }
    58  
    59  // TODO: rename Buffer to Image, to be less confusing with a Window's back and
    60  // front buffers.
    61  
    62  // Buffer is an in-memory pixel buffer. Its pixels can be modified by any Go
    63  // code that takes an *image.RGBA, such as the standard library's image/draw
    64  // package.
    65  //
    66  // To see a Buffer's contents on a screen, upload it to a Texture (and then
    67  // draw the Texture on a Window) or upload it directly to a Window.
    68  //
    69  // When specifying a sub-Buffer via Upload, a Buffer's top-left pixel is always
    70  // (0, 0) in its own coordinate space.
    71  type Buffer interface {
    72  	// Release releases the Buffer's resources, after all pending uploads and
    73  	// draws resolve. The behavior of the Buffer after Release is undefined.
    74  	Release()
    75  
    76  	// Size returns the size of the Buffer's image.
    77  	Size() image.Point
    78  
    79  	// Bounds returns the bounds of the Buffer's image. It is equal to
    80  	// image.Rectangle{Max: b.Size()}.
    81  	Bounds() image.Rectangle
    82  
    83  	// RGBA returns the pixel buffer as an *image.RGBA.
    84  	//
    85  	// Its contents should not be accessed while the Buffer is uploading.
    86  	RGBA() *image.RGBA
    87  }
    88  
    89  // Texture is a pixel buffer, but not one that is directly accessible as a
    90  // []byte. Conceptually, it could live on a GPU, in another process or even be
    91  // across a network, instead of on a CPU in this process.
    92  //
    93  // Buffers can be uploaded to Textures, and Textures can be drawn on Windows.
    94  //
    95  // When specifying a sub-Texture via Draw, a Texture's top-left pixel is always
    96  // (0, 0) in its own coordinate space.
    97  type Texture interface {
    98  	// Release releases the Texture's resources, after all pending uploads and
    99  	// draws resolve. The behavior of the Texture after Release is undefined.
   100  	Release()
   101  
   102  	// Size returns the size of the Texture's image.
   103  	Size() image.Point
   104  
   105  	// Bounds returns the bounds of the Texture's image. It is equal to
   106  	// image.Rectangle{Max: t.Size()}.
   107  	Bounds() image.Rectangle
   108  
   109  	Uploader
   110  
   111  	// TODO: also implement Drawer? If so, merge the Uploader and Drawer
   112  	// interfaces??
   113  }
   114  
   115  // Window is a top-level, double-buffered GUI window.
   116  type Window interface {
   117  	// Release closes the window and its event channel.
   118  	Release()
   119  
   120  	// Events returns the window's event channel, which carries key, mouse,
   121  	// paint and other events.
   122  	//
   123  	// TODO: define and describe these events.
   124  	Events() <-chan interface{}
   125  
   126  	// Send sends an event to the window.
   127  	Send(event interface{})
   128  
   129  	Uploader
   130  
   131  	Drawer
   132  
   133  	// Publish flushes any pending Upload and Draw calls to the window, and
   134  	// swaps the back buffer to the front.
   135  	Publish() PublishResult
   136  }
   137  
   138  // PublishResult is the result of an Window.Publish call.
   139  type PublishResult struct {
   140  	// BackBufferPreserved is whether the contents of the back buffer was
   141  	// preserved. If false, the contents are undefined.
   142  	BackBufferPreserved bool
   143  }
   144  
   145  // NewWindowOptions are optional arguments to NewWindow.
   146  type NewWindowOptions struct {
   147  	// Width and Height specify the dimensions of the new window. If Width
   148  	// or Height are zero, a driver-dependent default will be used for each
   149  	// zero value dimension.
   150  	Width, Height int
   151  
   152  	// TODO: fullscreen, title, icon, cursorHidden?
   153  }
   154  
   155  // Uploader is something you can upload a Buffer to.
   156  type Uploader interface {
   157  	// Upload uploads the sub-Buffer defined by src and sr to the destination
   158  	// (the method receiver), such that sr.Min in src-space aligns with dp in
   159  	// dst-space. The destination's contents are overwritten; the draw operator
   160  	// is implicitly draw.Src.
   161  	//
   162  	// It is valid to upload a Buffer while another upload of the same Buffer
   163  	// is in progress, but a Buffer's image.RGBA pixel contents should not be
   164  	// accessed while it is uploading. A Buffer is re-usable, in that its pixel
   165  	// contents can be further modified, once all outstanding calls to Upload
   166  	// have returned.
   167  	//
   168  	// When uploading to a Window, there will not be any visible effect until
   169  	// Publish is called.
   170  	Upload(dp image.Point, src Buffer, sr image.Rectangle)
   171  
   172  	// Fill fills that part of the destination (the method receiver) defined by
   173  	// dr with the given color.
   174  	//
   175  	// When filling a Window, there will not be any visible effect until
   176  	// Publish is called.
   177  	Fill(dr image.Rectangle, src color.Color, op draw.Op)
   178  }
   179  
   180  // TODO: have a Downloader interface? Not every graphical app needs to be
   181  // interactive or involve a window. You could use the GPU for hardware-
   182  // accelerated image manipulation: upload a buffer, do some texture ops, then
   183  // download the result.
   184  
   185  // Drawer is something you can draw Textures on.
   186  type Drawer interface {
   187  	// Draw draws the sub-Texture defined by src and sr to the destination (the
   188  	// method receiver). src2dst defines how to transform src coordinates to
   189  	// dst coordinates. For example, if src2dst is the matrix
   190  	//
   191  	// m00 m01 m02
   192  	// m10 m11 m12
   193  	//
   194  	// then the src-space point (sx, sy) maps to the dst-space point
   195  	// (m00*sx + m01*sy + m02, m10*sx + m11*sy + m12).
   196  	//
   197  	// When drawing on a Window, there will not be any visible effect until
   198  	// Publish is called.
   199  	Draw(src2dst f64.Aff3, src Texture, sr image.Rectangle, op draw.Op, opts *DrawOptions)
   200  }
   201  
   202  // Copy copies the sub-Texture defined by src and sr to dst, such that sr.Min
   203  // in src-space aligns with dp in dst-space.
   204  //
   205  // When drawing on a Window, there will not be any visible effect until Publish
   206  // is called.
   207  func Copy(dst Drawer, dp image.Point, src Texture, sr image.Rectangle, op draw.Op, opts *DrawOptions) {
   208  	dst.Draw(f64.Aff3{
   209  		1, 0, float64(dp.X - sr.Min.X),
   210  		0, 1, float64(dp.Y - sr.Min.Y),
   211  	}, src, sr, op, opts)
   212  }
   213  
   214  // Scale scales the sub-Texture defined by src and sr to dst, such that sr in
   215  // src-space is mapped to dr in dst-space.
   216  //
   217  // When drawing on a Window, there will not be any visible effect until Publish
   218  // is called.
   219  func Scale(dst Drawer, dr image.Rectangle, src Texture, sr image.Rectangle, op draw.Op, opts *DrawOptions) {
   220  	rx := float64(dr.Dx()) / float64(sr.Dx())
   221  	ry := float64(dr.Dy()) / float64(sr.Dy())
   222  	dst.Draw(f64.Aff3{
   223  		rx, 0, float64(dr.Min.X) - rx*float64(sr.Min.X),
   224  		0, ry, float64(dr.Min.Y) - ry*float64(sr.Min.Y),
   225  	}, src, sr, op, opts)
   226  }
   227  
   228  // These draw.Op constants are provided so that users of this package don't
   229  // have to explicitly import "image/draw".
   230  const (
   231  	Over = draw.Over
   232  	Src  = draw.Src
   233  )
   234  
   235  // DrawOptions are optional arguments to Draw.
   236  type DrawOptions struct {
   237  	// TODO: transparency in [0x0000, 0xffff]?
   238  	// TODO: scaler (nearest neighbor vs linear)?
   239  }