A simple yet powerful library for controlling graphical displays. Multiple display controllers are supported using inheritance.
Dependents: mbed_rifletool Hexi_Bubble_Game Hexi_Catch-the-dot_Game Hexi_Acceleromagnetic_Synth
NOTE: This library is in beta right now. As far as I know, everything here works, but there are many features that are lacking so far. Most notably containers, button handling, and display drivers other than the SSD1306.
Abstracts/Canvas.cpp@3:a8f72d4864e6, 2014-05-27 (annotated)
- Committer:
- neilt6
- Date:
- Tue May 27 21:41:28 2014 +0000
- Revision:
- 3:a8f72d4864e6
- Parent:
- 1:f7003ec66a51
Syntax improvements
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
neilt6 | 0:b876cf091464 | 1 | /* NeatGUI Library |
neilt6 | 0:b876cf091464 | 2 | * Copyright (c) 2013 Neil Thiessen |
neilt6 | 0:b876cf091464 | 3 | * |
neilt6 | 0:b876cf091464 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
neilt6 | 0:b876cf091464 | 5 | * you may not use this file except in compliance with the License. |
neilt6 | 0:b876cf091464 | 6 | * You may obtain a copy of the License at |
neilt6 | 0:b876cf091464 | 7 | * |
neilt6 | 0:b876cf091464 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
neilt6 | 0:b876cf091464 | 9 | * |
neilt6 | 0:b876cf091464 | 10 | * Unless required by applicable law or agreed to in writing, software |
neilt6 | 0:b876cf091464 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
neilt6 | 0:b876cf091464 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
neilt6 | 0:b876cf091464 | 13 | * See the License for the specific language governing permissions and |
neilt6 | 0:b876cf091464 | 14 | * limitations under the License. |
neilt6 | 0:b876cf091464 | 15 | */ |
neilt6 | 0:b876cf091464 | 16 | |
neilt6 | 0:b876cf091464 | 17 | #include "Canvas.h" |
neilt6 | 0:b876cf091464 | 18 | |
neilt6 | 0:b876cf091464 | 19 | Canvas::Canvas(int w, int h) |
neilt6 | 0:b876cf091464 | 20 | { |
neilt6 | 0:b876cf091464 | 21 | m_Width = w; |
neilt6 | 0:b876cf091464 | 22 | m_Height = h; |
neilt6 | 0:b876cf091464 | 23 | } |
neilt6 | 0:b876cf091464 | 24 | |
neilt6 | 0:b876cf091464 | 25 | void Canvas::clear(unsigned int c) |
neilt6 | 0:b876cf091464 | 26 | { |
neilt6 | 0:b876cf091464 | 27 | fillRect(0, 0, m_Width, m_Height, c); |
neilt6 | 0:b876cf091464 | 28 | } |
neilt6 | 0:b876cf091464 | 29 | |
neilt6 | 0:b876cf091464 | 30 | void Canvas::drawLine(int x0, int y0, int x1, int y1, unsigned int c) |
neilt6 | 0:b876cf091464 | 31 | { |
neilt6 | 0:b876cf091464 | 32 | int steep = abs(y1 - y0) > abs(x1 - x0); |
neilt6 | 0:b876cf091464 | 33 | if (steep) { |
neilt6 | 0:b876cf091464 | 34 | int temp = x0; |
neilt6 | 0:b876cf091464 | 35 | x0 = y0; |
neilt6 | 0:b876cf091464 | 36 | y0 = temp; |
neilt6 | 0:b876cf091464 | 37 | |
neilt6 | 0:b876cf091464 | 38 | temp = x1; |
neilt6 | 0:b876cf091464 | 39 | x1 = y1; |
neilt6 | 0:b876cf091464 | 40 | y1 = temp; |
neilt6 | 0:b876cf091464 | 41 | } |
neilt6 | 0:b876cf091464 | 42 | |
neilt6 | 0:b876cf091464 | 43 | if (x0 > x1) { |
neilt6 | 0:b876cf091464 | 44 | int temp = x0; |
neilt6 | 0:b876cf091464 | 45 | x0 = x1; |
neilt6 | 0:b876cf091464 | 46 | x1 = temp; |
neilt6 | 0:b876cf091464 | 47 | |
neilt6 | 0:b876cf091464 | 48 | temp = y0; |
neilt6 | 0:b876cf091464 | 49 | y0 = y1; |
neilt6 | 0:b876cf091464 | 50 | y1 = temp; |
neilt6 | 0:b876cf091464 | 51 | } |
neilt6 | 0:b876cf091464 | 52 | |
neilt6 | 0:b876cf091464 | 53 | int dx, dy; |
neilt6 | 0:b876cf091464 | 54 | dx = x1 - x0; |
neilt6 | 0:b876cf091464 | 55 | dy = abs(y1 - y0); |
neilt6 | 0:b876cf091464 | 56 | |
neilt6 | 0:b876cf091464 | 57 | int err = dx / 2; |
neilt6 | 0:b876cf091464 | 58 | int ystep; |
neilt6 | 0:b876cf091464 | 59 | |
neilt6 | 0:b876cf091464 | 60 | if (y0 < y1) { |
neilt6 | 0:b876cf091464 | 61 | ystep = 1; |
neilt6 | 0:b876cf091464 | 62 | } else { |
neilt6 | 0:b876cf091464 | 63 | ystep = -1; |
neilt6 | 0:b876cf091464 | 64 | } |
neilt6 | 0:b876cf091464 | 65 | |
neilt6 | 0:b876cf091464 | 66 | for (; x0 <= x1; x0++) { |
neilt6 | 0:b876cf091464 | 67 | if (steep) { |
neilt6 | 0:b876cf091464 | 68 | drawPixel(y0, x0, c); |
neilt6 | 0:b876cf091464 | 69 | } else { |
neilt6 | 0:b876cf091464 | 70 | drawPixel(x0, y0, c); |
neilt6 | 0:b876cf091464 | 71 | } |
neilt6 | 0:b876cf091464 | 72 | err -= dy; |
neilt6 | 0:b876cf091464 | 73 | if (err < 0) { |
neilt6 | 0:b876cf091464 | 74 | y0 += ystep; |
neilt6 | 0:b876cf091464 | 75 | err += dx; |
neilt6 | 0:b876cf091464 | 76 | } |
neilt6 | 0:b876cf091464 | 77 | } |
neilt6 | 0:b876cf091464 | 78 | } |
neilt6 | 0:b876cf091464 | 79 | |
neilt6 | 0:b876cf091464 | 80 | void Canvas::drawHLine(int x, int y, int w, unsigned int c) |
neilt6 | 0:b876cf091464 | 81 | { |
neilt6 | 0:b876cf091464 | 82 | drawLine(x, y, x + w - 1, y, c); |
neilt6 | 0:b876cf091464 | 83 | } |
neilt6 | 0:b876cf091464 | 84 | |
neilt6 | 0:b876cf091464 | 85 | void Canvas::drawVLine(int x, int y, int h, unsigned int c) |
neilt6 | 0:b876cf091464 | 86 | { |
neilt6 | 0:b876cf091464 | 87 | drawLine(x, y, x, y + h - 1, c); |
neilt6 | 0:b876cf091464 | 88 | } |
neilt6 | 0:b876cf091464 | 89 | |
neilt6 | 0:b876cf091464 | 90 | void Canvas::drawRect(int x, int y, int w, int h, unsigned int c) |
neilt6 | 0:b876cf091464 | 91 | { |
neilt6 | 0:b876cf091464 | 92 | drawHLine(x, y, w, c); |
neilt6 | 0:b876cf091464 | 93 | drawHLine(x, y + h - 1, w, c); |
neilt6 | 0:b876cf091464 | 94 | drawVLine(x, y, h, c); |
neilt6 | 0:b876cf091464 | 95 | drawVLine(x + w - 1, y, h, c); |
neilt6 | 0:b876cf091464 | 96 | } |
neilt6 | 0:b876cf091464 | 97 | |
neilt6 | 0:b876cf091464 | 98 | void Canvas::fillRect(int x, int y, int w, int h, unsigned int c) |
neilt6 | 0:b876cf091464 | 99 | { |
neilt6 | 0:b876cf091464 | 100 | for (int i = x; i < x + w; i++) { |
neilt6 | 0:b876cf091464 | 101 | drawVLine(i, y, h, c); |
neilt6 | 0:b876cf091464 | 102 | } |
neilt6 | 0:b876cf091464 | 103 | } |
neilt6 | 0:b876cf091464 | 104 | |
neilt6 | 0:b876cf091464 | 105 | void Canvas::drawTriangle(int x0, int y0, int x1, int y1, int x2, int y2, unsigned int c) |
neilt6 | 0:b876cf091464 | 106 | { |
neilt6 | 0:b876cf091464 | 107 | drawLine(x0, y0, x1, y1, c); |
neilt6 | 0:b876cf091464 | 108 | drawLine(x1, y1, x2, y2, c); |
neilt6 | 0:b876cf091464 | 109 | drawLine(x2, y2, x0, y0, c); |
neilt6 | 0:b876cf091464 | 110 | } |
neilt6 | 0:b876cf091464 | 111 | |
neilt6 | 0:b876cf091464 | 112 | void Canvas::fillTriangle(int x0, int y0, int x1, int y1, int x2, int y2, unsigned int c) |
neilt6 | 0:b876cf091464 | 113 | { |
neilt6 | 0:b876cf091464 | 114 | int a, b, y, last; |
neilt6 | 0:b876cf091464 | 115 | |
neilt6 | 0:b876cf091464 | 116 | //Sort coordinates by Y order (y2 >= y1 >= y0) |
neilt6 | 0:b876cf091464 | 117 | if (y0 > y1) { |
neilt6 | 0:b876cf091464 | 118 | int temp = y0; |
neilt6 | 0:b876cf091464 | 119 | y0 = y1; |
neilt6 | 0:b876cf091464 | 120 | y1 = temp; |
neilt6 | 0:b876cf091464 | 121 | |
neilt6 | 0:b876cf091464 | 122 | temp = x0; |
neilt6 | 0:b876cf091464 | 123 | x0 = x1; |
neilt6 | 0:b876cf091464 | 124 | x1 = temp; |
neilt6 | 0:b876cf091464 | 125 | } |
neilt6 | 0:b876cf091464 | 126 | if (y1 > y2) { |
neilt6 | 0:b876cf091464 | 127 | int temp = y1; |
neilt6 | 0:b876cf091464 | 128 | x1 = y2; |
neilt6 | 0:b876cf091464 | 129 | y2 = temp; |
neilt6 | 0:b876cf091464 | 130 | |
neilt6 | 0:b876cf091464 | 131 | temp = x1; |
neilt6 | 0:b876cf091464 | 132 | x1 = x2; |
neilt6 | 0:b876cf091464 | 133 | x2 = temp; |
neilt6 | 0:b876cf091464 | 134 | } |
neilt6 | 0:b876cf091464 | 135 | if (y0 > y1) { |
neilt6 | 0:b876cf091464 | 136 | int temp = y0; |
neilt6 | 0:b876cf091464 | 137 | y0 = y1; |
neilt6 | 0:b876cf091464 | 138 | y1 = temp; |
neilt6 | 0:b876cf091464 | 139 | |
neilt6 | 0:b876cf091464 | 140 | temp = x0; |
neilt6 | 0:b876cf091464 | 141 | x0 = x1; |
neilt6 | 0:b876cf091464 | 142 | x1 = temp; |
neilt6 | 0:b876cf091464 | 143 | } |
neilt6 | 0:b876cf091464 | 144 | |
neilt6 | 0:b876cf091464 | 145 | //Handle awkward all-on-same-line case as its own thing |
neilt6 | 0:b876cf091464 | 146 | if(y0 == y2) { |
neilt6 | 0:b876cf091464 | 147 | a = b = x0; |
neilt6 | 0:b876cf091464 | 148 | if(x1 < a) |
neilt6 | 0:b876cf091464 | 149 | a = x1; |
neilt6 | 0:b876cf091464 | 150 | else if(x1 > b) |
neilt6 | 0:b876cf091464 | 151 | b = x1; |
neilt6 | 0:b876cf091464 | 152 | if(x2 < a) |
neilt6 | 0:b876cf091464 | 153 | a = x2; |
neilt6 | 0:b876cf091464 | 154 | else if(x2 > b) |
neilt6 | 0:b876cf091464 | 155 | b = x2; |
neilt6 | 0:b876cf091464 | 156 | |
neilt6 | 0:b876cf091464 | 157 | drawHLine(a, y0, b - a + 1, c); |
neilt6 | 0:b876cf091464 | 158 | |
neilt6 | 0:b876cf091464 | 159 | return; |
neilt6 | 0:b876cf091464 | 160 | } |
neilt6 | 0:b876cf091464 | 161 | |
neilt6 | 0:b876cf091464 | 162 | int dx01 = x1 - x0; |
neilt6 | 0:b876cf091464 | 163 | int dy01 = y1 - y0; |
neilt6 | 0:b876cf091464 | 164 | int dx02 = x2 - x0; |
neilt6 | 0:b876cf091464 | 165 | int dy02 = y2 - y0; |
neilt6 | 0:b876cf091464 | 166 | int dx12 = x2 - x1; |
neilt6 | 0:b876cf091464 | 167 | int dy12 = y2 - y1; |
neilt6 | 0:b876cf091464 | 168 | int sa = 0; |
neilt6 | 0:b876cf091464 | 169 | int sb = 0; |
neilt6 | 0:b876cf091464 | 170 | |
neilt6 | 0:b876cf091464 | 171 | //For upper part of triangle, find scanline crossings for segments |
neilt6 | 0:b876cf091464 | 172 | //0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 |
neilt6 | 0:b876cf091464 | 173 | //is included here (and second loop will be skipped, avoiding a /0 |
neilt6 | 0:b876cf091464 | 174 | //error there), otherwise scanline y1 is skipped here and handled |
neilt6 | 0:b876cf091464 | 175 | //in the second loop...which also avoids a /0 error here if y0=y1 |
neilt6 | 0:b876cf091464 | 176 | //(flat-topped triangle). |
neilt6 | 0:b876cf091464 | 177 | if(y1 == y2) |
neilt6 | 0:b876cf091464 | 178 | last = y1; //Include y1 scanline |
neilt6 | 0:b876cf091464 | 179 | else |
neilt6 | 0:b876cf091464 | 180 | last = y1 - 1; //Skip it |
neilt6 | 0:b876cf091464 | 181 | |
neilt6 | 0:b876cf091464 | 182 | for(y = y0; y <= last; y++) { |
neilt6 | 0:b876cf091464 | 183 | a = x0 + sa / dy01; |
neilt6 | 0:b876cf091464 | 184 | b = x0 + sb / dy02; |
neilt6 | 0:b876cf091464 | 185 | sa += dx01; |
neilt6 | 0:b876cf091464 | 186 | sb += dx02; |
neilt6 | 0:b876cf091464 | 187 | |
neilt6 | 0:b876cf091464 | 188 | if(a > b) { |
neilt6 | 0:b876cf091464 | 189 | int temp = a; |
neilt6 | 0:b876cf091464 | 190 | a = b; |
neilt6 | 0:b876cf091464 | 191 | b = temp; |
neilt6 | 0:b876cf091464 | 192 | } |
neilt6 | 0:b876cf091464 | 193 | drawHLine(a, y, b - a + 1, c); |
neilt6 | 0:b876cf091464 | 194 | } |
neilt6 | 0:b876cf091464 | 195 | |
neilt6 | 0:b876cf091464 | 196 | //For lower part of triangle, find scanline crossings for segments |
neilt6 | 0:b876cf091464 | 197 | //0-2 and 1-2. This loop is skipped if y1=y2. |
neilt6 | 0:b876cf091464 | 198 | sa = dx12 * (y - y1); |
neilt6 | 0:b876cf091464 | 199 | sb = dx02 * (y - y0); |
neilt6 | 0:b876cf091464 | 200 | for(; y <= y2; y++) { |
neilt6 | 0:b876cf091464 | 201 | a = x1 + sa / dy12; |
neilt6 | 0:b876cf091464 | 202 | b = x0 + sb / dy02; |
neilt6 | 0:b876cf091464 | 203 | sa += dx12; |
neilt6 | 0:b876cf091464 | 204 | sb += dx02; |
neilt6 | 0:b876cf091464 | 205 | |
neilt6 | 0:b876cf091464 | 206 | if(a > b) { |
neilt6 | 0:b876cf091464 | 207 | int temp = a; |
neilt6 | 0:b876cf091464 | 208 | a = b; |
neilt6 | 0:b876cf091464 | 209 | b = temp; |
neilt6 | 0:b876cf091464 | 210 | } |
neilt6 | 0:b876cf091464 | 211 | drawHLine(a, y, b - a + 1, c); |
neilt6 | 0:b876cf091464 | 212 | } |
neilt6 | 0:b876cf091464 | 213 | } |
neilt6 | 0:b876cf091464 | 214 | |
neilt6 | 0:b876cf091464 | 215 | void Canvas::drawCircle(int x, int y, int r, unsigned int c) |
neilt6 | 0:b876cf091464 | 216 | { |
neilt6 | 0:b876cf091464 | 217 | int f = 1 - r; |
neilt6 | 0:b876cf091464 | 218 | int ddF_x = 1; |
neilt6 | 0:b876cf091464 | 219 | int ddF_y = -2 * r; |
neilt6 | 0:b876cf091464 | 220 | int i = 0; |
neilt6 | 0:b876cf091464 | 221 | int j = r; |
neilt6 | 0:b876cf091464 | 222 | |
neilt6 | 0:b876cf091464 | 223 | drawPixel(x, y + r, c); |
neilt6 | 0:b876cf091464 | 224 | drawPixel(x, y - r, c); |
neilt6 | 0:b876cf091464 | 225 | drawPixel(x + r, y, c); |
neilt6 | 0:b876cf091464 | 226 | drawPixel(x - r, y, c); |
neilt6 | 0:b876cf091464 | 227 | |
neilt6 | 0:b876cf091464 | 228 | while(i < j) { |
neilt6 | 0:b876cf091464 | 229 | if(f >= 0) { |
neilt6 | 0:b876cf091464 | 230 | j--; |
neilt6 | 0:b876cf091464 | 231 | ddF_y += 2; |
neilt6 | 0:b876cf091464 | 232 | f += ddF_y; |
neilt6 | 0:b876cf091464 | 233 | } |
neilt6 | 0:b876cf091464 | 234 | i++; |
neilt6 | 0:b876cf091464 | 235 | ddF_x += 2; |
neilt6 | 0:b876cf091464 | 236 | f += ddF_x; |
neilt6 | 0:b876cf091464 | 237 | drawPixel(x + i, y + j, c); |
neilt6 | 0:b876cf091464 | 238 | drawPixel(x - i, y + j, c); |
neilt6 | 0:b876cf091464 | 239 | drawPixel(x + i, y - j, c); |
neilt6 | 0:b876cf091464 | 240 | drawPixel(x - i, y - j, c); |
neilt6 | 0:b876cf091464 | 241 | drawPixel(x + j, y + i, c); |
neilt6 | 0:b876cf091464 | 242 | drawPixel(x - j, y + i, c); |
neilt6 | 0:b876cf091464 | 243 | drawPixel(x + j, y - i, c); |
neilt6 | 0:b876cf091464 | 244 | drawPixel(x - j, y - i, c); |
neilt6 | 0:b876cf091464 | 245 | } |
neilt6 | 0:b876cf091464 | 246 | } |
neilt6 | 0:b876cf091464 | 247 | |
neilt6 | 0:b876cf091464 | 248 | void Canvas::fillCircle(int x, int y, int r, unsigned int c) |
neilt6 | 0:b876cf091464 | 249 | { |
neilt6 | 0:b876cf091464 | 250 | drawVLine(x, y - r, 2 * r + 1, c); |
neilt6 | 0:b876cf091464 | 251 | fillCircleHelper(x, y, r, 3, 0, c); |
neilt6 | 0:b876cf091464 | 252 | } |
neilt6 | 0:b876cf091464 | 253 | |
neilt6 | 0:b876cf091464 | 254 | void Canvas::drawRoundRect(int x, int y, int w, int h, int r, unsigned int c) |
neilt6 | 0:b876cf091464 | 255 | { |
neilt6 | 0:b876cf091464 | 256 | //Draw the four lines |
neilt6 | 0:b876cf091464 | 257 | drawHLine(x + r, y, w - 2 * r, c); //Top |
neilt6 | 0:b876cf091464 | 258 | drawHLine(x + r, y + h - 1, w - 2 * r, c); //Bottom |
neilt6 | 0:b876cf091464 | 259 | drawVLine(x, y + r, h - 2 * r, c); //Left |
neilt6 | 0:b876cf091464 | 260 | drawVLine(x + w - 1, y + r, h - 2 * r, c); //Right |
neilt6 | 0:b876cf091464 | 261 | |
neilt6 | 0:b876cf091464 | 262 | //Draw the four corners |
neilt6 | 0:b876cf091464 | 263 | drawCircleHelper(x + r, y + r, r, 1, c); |
neilt6 | 0:b876cf091464 | 264 | drawCircleHelper(x + w - r - 1, y + r, r, 2, c); |
neilt6 | 0:b876cf091464 | 265 | drawCircleHelper(x + w - r - 1, y + h - r - 1, r, 4, c); |
neilt6 | 0:b876cf091464 | 266 | drawCircleHelper(x + r, y + h - r - 1, r, 8, c); |
neilt6 | 0:b876cf091464 | 267 | } |
neilt6 | 0:b876cf091464 | 268 | |
neilt6 | 0:b876cf091464 | 269 | void Canvas::fillRoundRect(int x, int y, int w, int h, int r, unsigned int c) |
neilt6 | 0:b876cf091464 | 270 | { |
neilt6 | 0:b876cf091464 | 271 | //Draw the body |
neilt6 | 0:b876cf091464 | 272 | fillRect(x + r, y, w - 2 * r, h, c); |
neilt6 | 0:b876cf091464 | 273 | |
neilt6 | 0:b876cf091464 | 274 | //Draw the four corners |
neilt6 | 0:b876cf091464 | 275 | fillCircleHelper(x + w - r - 1, y + r, r, 1, h - 2 * r - 1, c); |
neilt6 | 0:b876cf091464 | 276 | fillCircleHelper(x+r, y + r, r, 2, h - 2 * r - 1, c); |
neilt6 | 0:b876cf091464 | 277 | } |
neilt6 | 0:b876cf091464 | 278 | |
neilt6 | 1:f7003ec66a51 | 279 | void Canvas::drawImage(Image* img, int x, int y) |
neilt6 | 0:b876cf091464 | 280 | { |
neilt6 | 0:b876cf091464 | 281 | for (int j = 0; j < img->height(); j++) { |
neilt6 | 0:b876cf091464 | 282 | for (int i = 0; i < img->width(); i++) { |
neilt6 | 0:b876cf091464 | 283 | drawPixel(i + x, j + y, img->pixel(i, j)); |
neilt6 | 0:b876cf091464 | 284 | } |
neilt6 | 0:b876cf091464 | 285 | } |
neilt6 | 0:b876cf091464 | 286 | } |
neilt6 | 0:b876cf091464 | 287 | |
neilt6 | 1:f7003ec66a51 | 288 | int Canvas::drawChar(char c, Font* fnt, int x, int y) |
neilt6 | 0:b876cf091464 | 289 | { |
neilt6 | 0:b876cf091464 | 290 | //Get the character glyph |
neilt6 | 0:b876cf091464 | 291 | BitmapImage glyph = fnt->glyph(c); |
neilt6 | 0:b876cf091464 | 292 | |
neilt6 | 0:b876cf091464 | 293 | //Draw the character glyph |
neilt6 | 0:b876cf091464 | 294 | drawImage(&glyph, x, y); |
neilt6 | 0:b876cf091464 | 295 | |
neilt6 | 0:b876cf091464 | 296 | //Return the width of the glyph |
neilt6 | 0:b876cf091464 | 297 | return glyph.width(); |
neilt6 | 0:b876cf091464 | 298 | } |
neilt6 | 0:b876cf091464 | 299 | |
neilt6 | 1:f7003ec66a51 | 300 | void Canvas::drawString(const char* str, Font* fnt, int x, int y) |
neilt6 | 0:b876cf091464 | 301 | { |
neilt6 | 0:b876cf091464 | 302 | int cursX = 0; |
neilt6 | 0:b876cf091464 | 303 | int cursY = 0; |
neilt6 | 0:b876cf091464 | 304 | |
neilt6 | 0:b876cf091464 | 305 | while(*str != NULL) { |
neilt6 | 0:b876cf091464 | 306 | //Check for a new line character |
neilt6 | 0:b876cf091464 | 307 | if (*str == '\n') { |
neilt6 | 0:b876cf091464 | 308 | //Go to a new line |
neilt6 | 0:b876cf091464 | 309 | cursX = 0; |
neilt6 | 0:b876cf091464 | 310 | cursY += fnt->height(); |
neilt6 | 0:b876cf091464 | 311 | |
neilt6 | 0:b876cf091464 | 312 | //We're done for this character |
neilt6 | 0:b876cf091464 | 313 | str++; |
neilt6 | 0:b876cf091464 | 314 | continue; |
neilt6 | 0:b876cf091464 | 315 | } |
neilt6 | 0:b876cf091464 | 316 | |
neilt6 | 0:b876cf091464 | 317 | //Check for a carriage return character |
neilt6 | 0:b876cf091464 | 318 | if (*str == '\r') { |
neilt6 | 0:b876cf091464 | 319 | //Ignore it, we're done for this character |
neilt6 | 0:b876cf091464 | 320 | str++; |
neilt6 | 0:b876cf091464 | 321 | continue; |
neilt6 | 0:b876cf091464 | 322 | } |
neilt6 | 0:b876cf091464 | 323 | |
neilt6 | 0:b876cf091464 | 324 | //Draw the character |
neilt6 | 0:b876cf091464 | 325 | cursX += drawChar(*str++, fnt, x + cursX, y + cursY); |
neilt6 | 0:b876cf091464 | 326 | } |
neilt6 | 0:b876cf091464 | 327 | } |
neilt6 | 0:b876cf091464 | 328 | |
neilt6 | 1:f7003ec66a51 | 329 | void Canvas::drawString(const char* str, Font* fnt, int x, int y, int w, int h) |
neilt6 | 0:b876cf091464 | 330 | { |
neilt6 | 0:b876cf091464 | 331 | int cursX = 0; |
neilt6 | 0:b876cf091464 | 332 | int cursY = 0; |
neilt6 | 0:b876cf091464 | 333 | |
neilt6 | 0:b876cf091464 | 334 | while(*str != NULL) { |
neilt6 | 0:b876cf091464 | 335 | //Check for a new line character |
neilt6 | 0:b876cf091464 | 336 | if (*str == '\n') { |
neilt6 | 0:b876cf091464 | 337 | //Check if we can fit another line |
neilt6 | 0:b876cf091464 | 338 | if ((cursY + 2 * fnt->height()) < h) { |
neilt6 | 0:b876cf091464 | 339 | //Yes we can |
neilt6 | 0:b876cf091464 | 340 | cursX = 0; |
neilt6 | 0:b876cf091464 | 341 | cursY += fnt->height(); |
neilt6 | 0:b876cf091464 | 342 | |
neilt6 | 0:b876cf091464 | 343 | //We're done for this character |
neilt6 | 0:b876cf091464 | 344 | str++; |
neilt6 | 0:b876cf091464 | 345 | continue; |
neilt6 | 0:b876cf091464 | 346 | } else { |
neilt6 | 0:b876cf091464 | 347 | //Nope, we can't print any more so return |
neilt6 | 0:b876cf091464 | 348 | return; |
neilt6 | 0:b876cf091464 | 349 | } |
neilt6 | 0:b876cf091464 | 350 | } |
neilt6 | 0:b876cf091464 | 351 | |
neilt6 | 0:b876cf091464 | 352 | //Check for a carriage return character |
neilt6 | 0:b876cf091464 | 353 | if (*str == '\r') { |
neilt6 | 0:b876cf091464 | 354 | //Ignore it, we're done for this character |
neilt6 | 0:b876cf091464 | 355 | str++; |
neilt6 | 0:b876cf091464 | 356 | continue; |
neilt6 | 0:b876cf091464 | 357 | } |
neilt6 | 0:b876cf091464 | 358 | |
neilt6 | 0:b876cf091464 | 359 | //Check for entire words first |
neilt6 | 0:b876cf091464 | 360 | if ((*str > ' ') && (*str <= 0x7E)) { |
neilt6 | 0:b876cf091464 | 361 | //Draw entire word on canvas with correct wrapping |
neilt6 | 0:b876cf091464 | 362 | //int i = 0; |
neilt6 | 0:b876cf091464 | 363 | int wlen; |
neilt6 | 0:b876cf091464 | 364 | |
neilt6 | 0:b876cf091464 | 365 | //Determine the length of the next word |
neilt6 | 0:b876cf091464 | 366 | wlen = fnt->measureWord(str); |
neilt6 | 0:b876cf091464 | 367 | |
neilt6 | 0:b876cf091464 | 368 | //Will the length of the next word exceed the margins? |
neilt6 | 0:b876cf091464 | 369 | if ((wlen + cursX) > w) { |
neilt6 | 0:b876cf091464 | 370 | //Only do a newline if the word will fit on it |
neilt6 | 0:b876cf091464 | 371 | if (wlen <= w) { |
neilt6 | 0:b876cf091464 | 372 | //Check if we can fit another line |
neilt6 | 0:b876cf091464 | 373 | if ((cursY + 2 * fnt->height()) < h) { |
neilt6 | 0:b876cf091464 | 374 | //Yes we can |
neilt6 | 0:b876cf091464 | 375 | cursX = 0; |
neilt6 | 0:b876cf091464 | 376 | cursY += fnt->height(); |
neilt6 | 0:b876cf091464 | 377 | } else { |
neilt6 | 0:b876cf091464 | 378 | //Nope, we can't print any more so return |
neilt6 | 0:b876cf091464 | 379 | return; |
neilt6 | 0:b876cf091464 | 380 | } |
neilt6 | 0:b876cf091464 | 381 | } |
neilt6 | 0:b876cf091464 | 382 | } |
neilt6 | 0:b876cf091464 | 383 | |
neilt6 | 0:b876cf091464 | 384 | //Put just the word characters on the display up to the next non-whitespace character or the end of the string |
neilt6 | 0:b876cf091464 | 385 | while ((*str > ' ') && (*str <= 0x7E)) { |
neilt6 | 0:b876cf091464 | 386 | //Check if the character will fit on the screen |
neilt6 | 0:b876cf091464 | 387 | if ((fnt->glyph(*str).width() + cursX) > w) { |
neilt6 | 0:b876cf091464 | 388 | //Check if we can fit another line |
neilt6 | 0:b876cf091464 | 389 | if ((cursY + 2 * fnt->height()) < h) { |
neilt6 | 0:b876cf091464 | 390 | //Yes we can |
neilt6 | 0:b876cf091464 | 391 | cursX = 0; |
neilt6 | 0:b876cf091464 | 392 | cursY += fnt->height(); |
neilt6 | 0:b876cf091464 | 393 | } else { |
neilt6 | 0:b876cf091464 | 394 | //Nope, we can't print any more so return |
neilt6 | 0:b876cf091464 | 395 | return; |
neilt6 | 0:b876cf091464 | 396 | } |
neilt6 | 0:b876cf091464 | 397 | } |
neilt6 | 0:b876cf091464 | 398 | |
neilt6 | 0:b876cf091464 | 399 | //Draw the character |
neilt6 | 0:b876cf091464 | 400 | cursX += drawChar(*str++, fnt, x + cursX, y + cursY); |
neilt6 | 0:b876cf091464 | 401 | } |
neilt6 | 0:b876cf091464 | 402 | } else { |
neilt6 | 0:b876cf091464 | 403 | //Check if the character will fit on the screen |
neilt6 | 0:b876cf091464 | 404 | if ((fnt->glyph(*str).width() + cursX) > w) { |
neilt6 | 0:b876cf091464 | 405 | //Check if we can fit another line |
neilt6 | 0:b876cf091464 | 406 | if ((cursY + 2 * fnt->height()) < h) { |
neilt6 | 0:b876cf091464 | 407 | //Yes we can |
neilt6 | 0:b876cf091464 | 408 | cursX = 0; |
neilt6 | 0:b876cf091464 | 409 | cursY += fnt->height(); |
neilt6 | 0:b876cf091464 | 410 | } else { |
neilt6 | 0:b876cf091464 | 411 | //Nope, we can't print any more so return |
neilt6 | 0:b876cf091464 | 412 | return; |
neilt6 | 0:b876cf091464 | 413 | } |
neilt6 | 0:b876cf091464 | 414 | } |
neilt6 | 0:b876cf091464 | 415 | |
neilt6 | 0:b876cf091464 | 416 | //Draw the character |
neilt6 | 0:b876cf091464 | 417 | cursX += drawChar(*str++, fnt, x + cursX, y + cursY); |
neilt6 | 0:b876cf091464 | 418 | } |
neilt6 | 0:b876cf091464 | 419 | } |
neilt6 | 0:b876cf091464 | 420 | } |
neilt6 | 0:b876cf091464 | 421 | |
neilt6 | 1:f7003ec66a51 | 422 | int Canvas::width() |
neilt6 | 0:b876cf091464 | 423 | { |
neilt6 | 0:b876cf091464 | 424 | return m_Width; |
neilt6 | 0:b876cf091464 | 425 | } |
neilt6 | 0:b876cf091464 | 426 | |
neilt6 | 1:f7003ec66a51 | 427 | int Canvas::height() |
neilt6 | 0:b876cf091464 | 428 | { |
neilt6 | 0:b876cf091464 | 429 | return m_Height; |
neilt6 | 0:b876cf091464 | 430 | } |
neilt6 | 0:b876cf091464 | 431 | |
neilt6 | 0:b876cf091464 | 432 | void Canvas::drawCircleHelper(int x, int y, int r, unsigned int corner, unsigned int c) |
neilt6 | 0:b876cf091464 | 433 | { |
neilt6 | 0:b876cf091464 | 434 | int f = 1 - r; |
neilt6 | 0:b876cf091464 | 435 | int ddF_x = 1; |
neilt6 | 0:b876cf091464 | 436 | int ddF_y = -2 * r; |
neilt6 | 0:b876cf091464 | 437 | int i = 0; |
neilt6 | 0:b876cf091464 | 438 | int j = r; |
neilt6 | 0:b876cf091464 | 439 | |
neilt6 | 0:b876cf091464 | 440 | while (i < j) { |
neilt6 | 0:b876cf091464 | 441 | if (f >= 0) { |
neilt6 | 0:b876cf091464 | 442 | j--; |
neilt6 | 0:b876cf091464 | 443 | ddF_y += 2; |
neilt6 | 0:b876cf091464 | 444 | f += ddF_y; |
neilt6 | 0:b876cf091464 | 445 | } |
neilt6 | 0:b876cf091464 | 446 | i++; |
neilt6 | 0:b876cf091464 | 447 | ddF_x += 2; |
neilt6 | 0:b876cf091464 | 448 | f += ddF_x; |
neilt6 | 0:b876cf091464 | 449 | if (corner & 0x4) { |
neilt6 | 0:b876cf091464 | 450 | drawPixel(x + i, y + j, c); |
neilt6 | 0:b876cf091464 | 451 | drawPixel(x + j, y + i, c); |
neilt6 | 0:b876cf091464 | 452 | } |
neilt6 | 0:b876cf091464 | 453 | if (corner & 0x2) { |
neilt6 | 0:b876cf091464 | 454 | drawPixel(x + i, y - j, c); |
neilt6 | 0:b876cf091464 | 455 | drawPixel(x + j, y - i, c); |
neilt6 | 0:b876cf091464 | 456 | } |
neilt6 | 0:b876cf091464 | 457 | if (corner & 0x8) { |
neilt6 | 0:b876cf091464 | 458 | drawPixel(x - j, y + i, c); |
neilt6 | 0:b876cf091464 | 459 | drawPixel(x - i, y + j, c); |
neilt6 | 0:b876cf091464 | 460 | } |
neilt6 | 0:b876cf091464 | 461 | if (corner & 0x1) { |
neilt6 | 0:b876cf091464 | 462 | drawPixel(x - j, y - i, c); |
neilt6 | 0:b876cf091464 | 463 | drawPixel(x - i, y - j, c); |
neilt6 | 0:b876cf091464 | 464 | } |
neilt6 | 0:b876cf091464 | 465 | } |
neilt6 | 0:b876cf091464 | 466 | } |
neilt6 | 0:b876cf091464 | 467 | |
neilt6 | 0:b876cf091464 | 468 | void Canvas::fillCircleHelper(int x, int y, int r, unsigned int corner, int delta, unsigned int c) |
neilt6 | 0:b876cf091464 | 469 | { |
neilt6 | 0:b876cf091464 | 470 | int f = 1 - r; |
neilt6 | 0:b876cf091464 | 471 | int ddF_x = 1; |
neilt6 | 0:b876cf091464 | 472 | int ddF_y = -2 * r; |
neilt6 | 0:b876cf091464 | 473 | int i = 0; |
neilt6 | 0:b876cf091464 | 474 | int j = r; |
neilt6 | 0:b876cf091464 | 475 | |
neilt6 | 0:b876cf091464 | 476 | while (i < j) { |
neilt6 | 0:b876cf091464 | 477 | if (f >= 0) { |
neilt6 | 0:b876cf091464 | 478 | j--; |
neilt6 | 0:b876cf091464 | 479 | ddF_y += 2; |
neilt6 | 0:b876cf091464 | 480 | f += ddF_y; |
neilt6 | 0:b876cf091464 | 481 | } |
neilt6 | 0:b876cf091464 | 482 | i++; |
neilt6 | 0:b876cf091464 | 483 | ddF_x += 2; |
neilt6 | 0:b876cf091464 | 484 | f += ddF_x; |
neilt6 | 0:b876cf091464 | 485 | |
neilt6 | 0:b876cf091464 | 486 | if (corner & 0x1) { |
neilt6 | 0:b876cf091464 | 487 | drawVLine(x + i, y - j, 2 * j + 1 + delta, c); |
neilt6 | 0:b876cf091464 | 488 | drawVLine(x + j, y - i, 2 * i + 1 + delta, c); |
neilt6 | 0:b876cf091464 | 489 | } |
neilt6 | 0:b876cf091464 | 490 | if (corner & 0x2) { |
neilt6 | 0:b876cf091464 | 491 | drawVLine(x - i, y - j, 2 * j + 1 + delta, c); |
neilt6 | 0:b876cf091464 | 492 | drawVLine(x - j, y - i, 2 * i + 1 + delta, c); |
neilt6 | 0:b876cf091464 | 493 | } |
neilt6 | 0:b876cf091464 | 494 | } |
neilt6 | 0:b876cf091464 | 495 | } |