name: inverse layout: true class: center, middle, inverse --- # Introduction to Drawing Lauren Bricker CSE 340 Spring 2020 --- layout: false [//]: # (Outline Slide) # Today's goals - Administrivia - Warmups - Checks for understanding - Practicing with breakouts, polleverywhere, and Ed - Quick view of resources - Abstractions for drawing on the screen - Drawing in Android - Clipping and other transformations --- # Administrivia - Please remember to take the first day [survey](https://catalyst.uw.edu/webq/survey/bricker/387508) if you have not already - Ed-iquette - Please tag your posts with the most appropriate tag, e.g., if you are posting about doodle please tag it with as1-doodle - Please search to see if someone has already answered your question before posting! (these tags can help!) - Lab videos were posted - Important [Ed Post about a change to Part1.java](https://us.edstem.org/courses/381/discussion/24015) --- # Trying new things! 1. Breakout rooms - Today I've randomly assigned you to breakout rooms with one TA each. - In the future, we will experiment with a system where you can choose your breakout partners - Goal: Meet other students, answer some questions. - Please turn your cameras on in the breakouts - Introduce yourself, and say what color socks your wearing. - Work together on the question posed.... 2. Warmup 1: pollev.com/docbrick - answer the question - try to think of a one unique answer per person in your breakout - Each person should answer the poll separately - We'll come back together and see the results. 3. Warmup 2: Ed sway - We'll go back into the breakout rooms and try to work together to answer questions on Sway - Each person should submit their answers. --- Warmup 1
--- # Quick view of resources One commong "Good Programming Practice" is to remove "static" resources from your code and store them in a resource area to be used by your program. Think of this like the "No Magic Numbers" principle you learned early in 142). - Often used in internationalization or localization - Often used in A/B testing in software development Android resources are stored in `.xml` files in subdirectories of the `app/res` directory may include - `drawable` - images you might draw on the screen in various formats - `layout` - layouts of various screens - `menu` - the menus for your application - `values` - might contain `colors.xml` and `strings.xml` --- ## Developer roles .left-column[
graph LR ip[Interface Programmer] w[Component Developer] l[Library Extender] a[Architecture Extender] t[Toolkit Builder] classDef yellow font-size:14pt,text-align:center classDef green font-size:14pt,text-align:center class t,l,a,w yellow class ip green
] .right-column[ From [last class](toolkits.html) we briefly discussed of the roles a developer can play in app development. - Today we're going to focus on being an Interface Developer (adding existing components like `ImageView` objects to the `doodleView`) - We might get to touch on being a Component Developer and thinking about how to create that new `LineView` component ] --- # Drawing on the Screen - Take out your phone. Open an App. What do you see on your screen? --- # Drawing on the Screen - Take out your phone. Open an App. What do you see on your screen? .left-column[ ![:img Example poll everywhere mobile presenter application screen, 100%](img/drawing/pollevscreen.jpeg)] .right-column[ (this is what I currently see) What is an app made up of? ] --- # What is on your screen? .left-column[ ![:img Example poll everywhere mobile presenter application screen, 100%](img/drawing/pollevscreen.jpeg) ] .right-column[ App is made up of? Interactors Last class we discussed the "tree" of components. Think about what this hierarchy might look like. - What is at the "root" ? - How is this divided up into sections - In each section, how are things further divided up? ] --- # What is on your screen? .left-column[ ![:img Example poll everywhere mobile presenter application screen, 100%](img/drawing/pollevscreen.jpeg)] .right-column[
graph LR W(Window) --> T[Title Bar] W --> L[Label: My Folders] W --> F[Folders] W --> B[Toolbar] T --> TA[Icon] T --> TB[Label: Activities] T --> TC[Button: Search] T --> TD[Button: Folder] T --> TE[Button: Add] F --> F1[Folder 1] F --> F2[Folder 2] F --> F3[Folder 3] F1 --> I[Icon] F1 --> N[Folder Name] F1 --> C[Activity Count] B --> H[Button:Home] B --> A[Button: Activities] B --> R[Button: Reports] B --> P[Button: Profile] classDef start font-size:12pt,text-align:center classDef blue font-size:12pt,text-align:center class W start class T,L,E,F,B,TA,TB,TC,TD,TE,F1,F2,F3,H,A,R,P,I,N,C blue
] --- # What is on your screen? .left-column[ ![:img Example poll everywhere mobile presenter application screen, 100%](img/drawing/pollevscreen.jpeg) ] .right-column[ App is made up of? Interactors What are Interactors made up of? ] ??? Should push them down to the lowest level on the screen App is made up of? Interactors Interactors are made up of? lines, circles, text Lines, circles and text are made up of? Pixels --- # What is on your screen? .left-column[ ![:img Example poll everywhere mobile presenter application screen, 100%](img/drawing/pollevscreen.jpeg)] .right-column[ App is made up of? Interactors Interactors are made up of? lines, circles, text Lines, circles and text are made up of? Pixels (picture elements) ] --- # Aside: Displaying a Pixel .left-column30[ Do you know how pixels are lit up in color or greyscale? - on your computer or TV screen? - on a projector? ] -- .right-column50[ [Cathode Ray Tube](https://en.wikipedia.org/wiki/Cathode-ray_tube) | [LED Display](https://en.wikipedia.org/wiki/LED_display) :--: | :--: ![:img Magnified view of a delta-gun shadow mask color CRT, 90%](img/drawing/CRT_display.jpg) | ![:img Detail view of a LED display with a matrix of red green and blue diodes, 90%](img/drawing/LED_display.jpg) ] ??? Get them to at least realize that the actual pixels on their screen are LEDs --- # Drawing on the Screen What are we going to control as we build this application? -- - Interactors -- - from the Toolkit - they know how to draw themselves and possibly react to input -- In Android, we call these Interactors `Views` - *Aside: Widgets, Interactors, and `Views` are all variations on the same term* -- What if you were to build an interactor from scratch? -- - You'd need basic drawing capabilities from the toolkit such as drawing lines, circles, and so on --- # Toolkit Support for Basic Drawing .left-column[ ![:img Example poll everywhere mobile presenter application screen, 85%](img/drawing/DrawingPanel.png)] .right-column[ All toolkits have some sort of `Canvas` object or abstraction - `Canvas` is an object level abstraction for performing drawing operations - Each `View` has a `Canvas` in Android - You can access it in the `onDraw(Canvas canvas)` method When is `onDraw()` called? ] ??? Connect to DrawingPanel in 143? --- # Toolkit Support for Basic Drawing .left-column[ ![:img Example poll everywhere mobile presenter application screen, 85%](img/drawing/DrawingPanel.png)] .right-column[ All toolkits have some sort of `Canvas` object or abstraction - `Canvas` is an object level abstraction for performing drawing operations - Each `View` has a `Canvas` in Android - You can access it in the `onDraw(Canvas canvas)` method When is `onDraw()` called? - Handled automatically for you by toolkit - Triggered whenever the pixels are *dirty* (there's been a change to what needs to be viewed) - You can trigger this with `invalidate()` (we'll use this in the future) ] ??? Lots to discuss here. Mainly focus on introducing the concept of a library (a bunch of views you can pick from, Canvas and its methods, etc) vs an architecture (which controls when and in what order things happen). We'll learn about both in this class. You need to understand both to use a toolkit. --- # How does Canvas work? - Drawing is done by calling methods for different kinds of objects -- - For example: `drawRect`, `drawOval`, `drawLine`, `drawPath` ... [Full List in the API Documentation](https://developer.android.com/reference/android/graphics/Canvas.html) --- # How does Canvas work? - Drawing is done by calling methods for different kinds of objects - Lots happens under the covers... let's look at an example... -- "I want to draw a line on the screen" -- So I would likely call `drawLine` on the `Canvas`. -- So... how do I tell the computer where the start and end of the line will be? --- # How is location decided? - (0,0) is at the top left of the screen - The screen is drawn pixel by pixel from top left to bottom right in "raster" lines ![:img Picture of a very old CRT based TV display, 25%](img/drawing/analogtv.jpg) ![:img Picture of raster scanning going from top left to top right; down a row; and so on, 25%](img/drawing/rasterscanning.png) [Source: Wikipedia](https://en.wikipedia.org/wiki/Analog_television#Displaying_an_image) --- # How is a drawing object rendered on screen? - An object (like a line) would be converted into one or more **strokes** - A stroke has properties such as width or color - The stroke is converted to **pixels** (correspond to dots on your screen) - These pixels are put in a `Bitmap` (frame buffer) first, then updated on the screen all at once ??? top left is from old-style raster graphics, where a beam of light literally moved down the screen from top left to bottom right, causing chemical excitation when on and thus lighting the screen the last is left over from when both graphics and drawing were slower and more linear Still most reliable approach --- # How is a stroke converted to pixels? - Strokes (can be) size independent. Pixels are not - Strokes are continuous. Pixels are not - Anti-aliasing Essentially converting from **vector** to **raster** graphics ([Bresenham's algorithm](https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm)) --- # Quick understanding test What internal data structure (abstraction) represents an entire picture to display on a color screen? -- pixels in a 2D array ![:img The left side of this image displays the RGB pixel values of the image of GitGrade's Hopper on the right side 3%](img/drawing/pixelcalc.png) Pixel Calculator (Tanimoto 2010) ??? **A frame buffer (2D array) (picture)** The following are wrong, they represent a single pixel (but we haven't studied this yet) - A pixel (R,G,B) - A number from 0 to 255 --- # What is the [Paint](https://developer.android.com/reference/android/graphics/Paint.html) Object? .left-column[ ![:img Picture of a phone screen with a blue and green circle drawn on it at different vertical positions (50 and 150 y center point), 80%](img/drawing/circles.png) ] .right-column[A Paint object is an abstraction that determines how drawing operations should look ```java Paint drawPaint = new Paint(); drawPaint.setColor(Color.BLUE); drawPaint.setAntiAlias(true); drawPaint.setStrokeWidth(5); drawPaint.setStyle(Paint.Style.STROKE); canvas.drawCircle(500, 500, 400, drawPaint); drawPaint.setStrokeJoin(Paint.Join.ROUND); drawPaint.setStrokeCap(Paint.Cap.ROUND); drawPaint.setColor(Color.GREEN); drawPaint.setStrokeWidth(15); canvas.drawLine(350, 300, 500,600, drawPaint); ```] --- # What is the [Paint](https://developer.android.com/reference/android/graphics/Paint.html) Object? - Abstraction that determines how drawing operations should look - Drawing style: stroked, filled - Line Characteristics: color, line width, join, cap styles - Fill Characteristics (color) ![:img example dotted line--unfilled,15%](img/drawing/dotted.png) ![:img example solid filled,15%](img/drawing/filled.png) ![:img example solid unfilled,15%](img/drawing/unfilled.png) --- # Other Paint properties - Text Characteristics: font family, style, size, alignment settings, etc. -- - font: shapes for chars (called *glyphs*) plus layout - family or typeface ![:img examples of different types of fonts,40%](img/drawing/fonts.png) --- # Other Paint properties - Text Characteristics: font family, style, size, alignment settings, etc. - font: shapes for chars (called *glyphs*) plus layout - family or typeface - style: plain, *italic*, **bold**, **_both_**, ~~strikethrough~~, *etc.* -- - points: 72.27 points per inch ??? because french inches were different (72 per inch) Really just a guideline these days It is the *width* of a capital M (no height specified) --- # The Path Object - Canvas supports drawing primitive shapes _and_ arbitrary paths: `void drawPath(Path p, Paint paint);` -- - Declaring a `Path` can be done by combining basic primitive shapes (e.g rectangles, circles, ovals, curves like arc, cubic, etc.) -- - What drawing model does creating a path in this way correspond to? - Raster model - Vector model --- # The Path Object - Canvas supports drawing primitive shapes _and_ arbitrary paths: `void drawPath(Path p, Paint paint);` - Declaring a `Path` can be done by combining basic primitive shapes (e.g rectangles, circles, ovals, curves like arc, cubic, etc.) - Which is more scalable? - Raster model - Vector model ??? XXXX could do in-class [drawing exercise](https://github.com/mriveralee/ssui-mobile-exercises-2016/tree/master/exercises/lab05/CustomDrawing) IF time XXXX needs updating --- # Bounding box of an object A bounding box (or sometimes [Minimum Bounding Box](https://en.wikipedia.org/wiki/Minimum_bounding_box)) is a term used in coordinate geometry to describe the smallest rectangular area that contains an object or set of objects. Great example to play with: https://www.mathopenref.com/coordbounds.html Drawing Demo - things to think about - What is the bounding box of a line that is drawn diagonally - from upper left to lower right? - lower right to the upper left? - from the upper right to the lower left? - from the lower s` - What is bounding box of a vertical line? - What is the bounding box of a horizontal line? --- # Doodle assignment: practice with drawing Inspired by Google's Doodles, and will include animation (to be discussed) First we will create holders for things you might draw - Android already provides an `ImageView` and a `TextView` - You will create a `LineView` - You will produce some things we specify - Then you will have a chance to create any animation you want! --- # [Example from 19sp](img/drawing/doodlevid.mp4) .left-column[ Note that we use a `View` for **each** thing on the screen ] .right-column[ ![:youtube Animation showing images of food moving in a line down the page around a U finally forming a W, Sx8oiJGjaIM] ] --- # Why so many separate `Views`? .left-column-half[ Useful later when we want to do animation Also provides **separation of concerns** and good high level control - Can have a different paint object for each view - Can easily change z-order (what is on top of what) - Can store information used to draw that thing (whatever it is) - Can either make the size of the whole screen or resize around what is drawn Views can also be re-used easily ] .right-column20[ ![:img Picture of an android device with 3 Views each one containing a line circle and square a different size with different backgrounds, 80%](img/drawing/views.png) ] ??? This could be a good place to ask them to think about what that means and demonstrating two things with different z order. --- # Coordinates of the Views - The coordinate system for each View has the (0, 0) point in the upper left hand corner (remember why?) - The width and height of the View is determined it's `ViewGroup.LayoutParams` - - These will be used by the layout system for positioning. - We will learn more about these next week. - - The `View` also has a position on the screen. - `View#SetX(int)` and `View.SetY(int)` set the left and top most coordinate of the `View` in its parent. --- # Advanced Canvas: Coordinate Transformations .left-column[ ## How does the android toolkit move the various objects on this screen? ] .right-column[ ![:youtube A phone screen with patterned circles spinning in different directions on it, w7DEWWtIlrs] ] ??? Be sure to orally narrate what is happening for low-vision people in the room --- # Linear ("affine") Transformations available Translate, Scale, Rotate, Shear (and any combination thereof) -- - Translate: Move origin (and everything else) in x and y ![:img a large moon and a large moon moved to the right a few pixels, 15%](img/drawing/translate.png) ??? used extensively in GUIS because child objects just draw themselves at *their* origin, so a component doesn't have to calculate how to draw itself based on its position -- - Scale: change size (negative == flip) ![:img a large and small moon, 15%](img/drawing/scale.png) -- - Rotate and Shear ![:img a rotated and angled moon, 25%](img/drawing/shear.png) --- # Coordinate Transformations - Can modify any shape, including text. - In practice, complex transformations are done with matrices, and matrices are using `concat(Matrix)` - But Android helps with this by providing methods in the [Canvas](https://developer.android.com/reference/android/graphics/Canvas) object to transform a canvas such as ```java translate(float dx, float dy) rotate(float degrees) // the whole canvas around the canvas origin rotate (float degrees, float px, float py) // around a particular point scale(float, float) scale (float sx, float sy, float px, float py) // around a pivot point skew(float sx, float sy) // skew by sx and sy save() // save the current transform restore() // restore the previous transform ``` ??? - important thing to point out here: This is a value proposition for a toolkit again – Affine transformations are based on two-dimensional matrices of the following form: P' = T*P where P is 1x3 and T is the transform matrix (3x3) with the bottom row 0 0 1 Thus, x' = ax + cy + t_x and y' = bx + dy + t_y *Note* Any sequence of transform, rotate and shear can be represented in a single matrix of this form (just multiple the matrices together) --- # Question: How to rotate about the center of an object
??? [raise your hands] - A: Translate, rotate, translate - B: Rotate, Translate, Rotate - C: Scale, Rotate, Scale - D: Rotate XX define exercise maybe put this after android stuff? I usually draw this out on a piece of paper using the document camera to help --- # Solution: How to rotate about the center of an object .left-column[ ![:img a blue square and then a translated and rotated green square, 80%](img/drawing/trans-rotate.png)] .right-column[ ```java int rectHeight = 300; int rectWidth = 300; int rectY = 100; int rectX = 100; float px = (rectWidth - rectX)/2 + rectX; float py = (rectHeight - rectY)/2 + rectY; canvas.drawRect(rectX, rectY, rectWidth, rectHeight, paint); for (int i = 15; i < 360; i += 15) { int color = (i % 2 == 0) ? Color.GREEN : Color.BLUE; paint.setColor(color); canvas.drawRect(rectX, rectY, rectWidth, rectHeight, paint); canvas.translate(px, py); canvas.rotate(i); canvas.translate(-px, -py); } ``` ] --- # Summary & revisiting learning goals for this week - What are the layers of the application stack - What are the roles of developers at each layer - How to add interactors to the app - How interactors are drawn - Pixel & stroke models - Canvas & Paint & Paths in Android - Maybe...Rotating around an object