Subversion Repositories group.electronics

Rev

Rev 182 | Rev 184 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
182 pfowler 1
using System;
2
using System.Collections;
3
using System.Collections.Generic;
4
using System.Drawing;
5
using System.IO;
6
using System.Linq;
7
using System.Text;
8
using System.Threading.Tasks;
9
 
10
namespace nitdcscore {
11
    public class Oled {
12
        public const int LCD_WIDTH = 128;
13
        public const int LCD_HEIGHT = 64;
14
 
15
        public const int EXTERNALVCC = 0x01;
16
        public const int SWITCHCAPVCC = 0x02;
17
        public const int SETLOWCOLUMN = 0x00;
18
        public const int SETHIGHCOLUMN = 0x10;
19
        public const int MEMORYMODE = 0x20;
20
        public const int COLUMNADDR = 0x21;
21
        public const int PAGEADDR = 0x22;
22
        public const int DEACTIVATESCROLL = 0x2E;
23
        public const int SETSTARTLINE = 0x40;
24
 
25
        public const int SETCONTRAST = 0x81;
26
        public const int CHARGEPUMP = 0x8D;
27
 
28
        public const int SEGREMAP = 0xA0;
29
        public const int DISPLAYALLON_RESUME = 0xA4;
30
        public const int DISPLAYALLON = 0xA5;
31
        public const int NORMALDISPLAY = 0xA6;
32
        public const int INVERTDISPLAY = 0xA7;
33
        public const int SETMULTIPLEX = 0xA8;
34
        public const int DISPLAYOFF = 0xAE;
35
        public const int DISPLAYON = 0xAF;
36
 
37
        public const int COMSCANINC = 0xC0;
38
        public const int COMSCANDEC = 0xC8;
39
 
40
        public const int SETDISPLAYOFFSET = 0xD3;
41
        public const int SETCOMPINS = 0xDA;
42
        public const int SETVCOMDETECT = 0xDB;
43
        public const int SETDISPLAYCLOCKDIV = 0xD5;
44
        public const int SETPRECHARGE = 0xD9;
45
 
46
        public static byte[] buffer = new byte[Oled.LCD_WIDTH / 8 * Oled.LCD_HEIGHT];
47
 
48
        public int vccstate { get; set; }
49
        public int i2caddr { get; set; }
50
 
51
        public i2cmaster i2c { get; set; }
52
 
183 pfowler 53
        public Oled(int vccstate, int i2caddr, i2cmaster i2c) {
182 pfowler 54
            this.vccstate = vccstate;
55
            this.i2caddr = i2caddr;
56
            this.i2c = i2c;
183 pfowler 57
        }
182 pfowler 58
 
183 pfowler 59
        public void init() {
182 pfowler 60
            // Init sequence
61
            oled_command(DISPLAYOFF);
62
            oled_command(SETDISPLAYCLOCKDIV);
63
            oled_command(0x80); // Suggested ratio
64
 
65
            oled_command(SETMULTIPLEX);
66
            oled_command(LCD_HEIGHT - 1);
67
 
68
            oled_command(SETDISPLAYOFFSET);
69
            oled_command(0x00); // No offset
70
            oled_command(SETSTARTLINE | 0x00); // Start line 0
71
            oled_command(CHARGEPUMP);
72
            if (this.vccstate == EXTERNALVCC)
73
                oled_command(0x10);
74
            else
75
                oled_command(0x14);
76
 
77
            oled_command(MEMORYMODE);
78
            oled_command(0x00);
79
            oled_command(SEGREMAP | 0x01);
80
            oled_command(COMSCANDEC);
81
 
82
            // 128-64 specific
83
            oled_command(SETCOMPINS);
84
            oled_command(0x12);
85
            oled_command(SETCONTRAST);
86
            if (this.vccstate == EXTERNALVCC)
87
                oled_command(0x9F);
88
            else
89
                oled_command(0xCF);
90
 
91
            oled_command(SETPRECHARGE);
92
            if (this.vccstate == EXTERNALVCC)
93
                oled_command(0x22);
94
            else
95
                oled_command(0xF1);
96
 
97
            oled_command(SETVCOMDETECT);
98
            oled_command(0x40);
99
            oled_command(DISPLAYALLON_RESUME);
100
            oled_command(NORMALDISPLAY);
101
            oled_command(DEACTIVATESCROLL);
102
 
103
            oled_command(DISPLAYON);
104
 
105
        }
106
 
107
        public void display() {
108
            oled_command(COLUMNADDR);
109
            oled_command(0x00);         // Column start address
110
            oled_command(LCD_WIDTH - 1);  // Column end address
111
 
112
            oled_command(PAGEADDR);
113
            oled_command(0x00); // Page start address
114
            oled_command(7);    // Page end address (7 for 64 pixels)
115
 
116
            for (int i = 0; i < (LCD_WIDTH * LCD_HEIGHT / 8); i++) {
117
                byte[] data = new byte[16];
118
                for (int j = 0; j < 16; j++) {
119
                    data[j] = buffer[i];
120
                    i++;
121
                }
122
                i--;
123
                i2c.WriteI2cData((byte)this.i2caddr, data, 16);
124
            }
125
        }
126
 
127
        public int oled_command(byte c) {
128
            byte control = 0x00;
129
            byte[] data = { control };
130
            i2c.WriteI2cData((byte)this.i2caddr, data, 1);
131
            data[0] = c;
132
            i2c.WriteI2cData((byte)this.i2caddr, data, 1);
133
            return 0;
134
        }
135
    }
136
 
137
    public class BmpImage {
138
        public string filename;     // The image filename
139
        public int filesize;        // Total size of the 
140
        public int datastart;       // Location of the start of image data
141
        public int imagesize;       // The size of actual image data
142
        public int width;           // Width of the image
143
        public int height;          // Height of the image
144
        public int bpp;             // Bits per pixel of the image
145
        public int bytepad;         // Bytes padded to align image row
146
        public byte[] data;         // The bmp image data
147
        public BitArray[] bitdata;  // Data in bitarray format
148
 
149
        public BmpImage(string filename) {
150
            this.filename = filename;
151
            filesize = 0;
152
            datastart = 0xffffff;
153
            imagesize = 0;
154
            width = 0;
155
            height = 0;
156
            bpp = 0;
157
            bytepad = 0;
158
            data = new byte[8192];
159
            bitdata = new BitArray[1];
160
 
161
            this.load();
162
        }
163
 
164
        public int load() {
165
            using (BinaryReader b = new BinaryReader(File.Open(this.filename, FileMode.Open))) {
166
                int pos = 0;
167
 
168
                int readLen = (int)b.BaseStream.Length;
169
                while (pos < readLen) {
170
                    // Read the image data from the file
171
                    if (pos >= this.datastart) {
172
 
173
                        // BMP format stored in 'data'
174
                        int imgptr = 0;
175
                        while (imgptr < this.imagesize) {
176
                            this.data[imgptr++] = b.ReadByte();
177
                        }
178
                        //Console.WriteLine("Read " + imgptr.ToString() + " bytes");
179
 
180
                        // Raw decoded data stored in 'bitdata'
181
                        this.bitdata = new BitArray[this.height];
182
                        int x = 0;      // Cursor X position
183
                        int y = 0;      // Cursor Y position
184
                        int i = 0;    // Current byte position
185
                        //Console.WriteLine("W:{0} H:{1}", img.width.ToString(), img.height.ToString());
186
 
187
                        for (y = this.height - 1; y >= 0; y--) {
188
 
189
                            this.bitdata[y] = new BitArray(this.width);
190
                            x = 0;
191
                            while (x < this.width) {
192
                                if (x >= this.width)
193
                                    break;
194
                                // Reverse the bit cause its stored back to front in bmp format
195
                                byte br;
196
                                br = this.data[i];
197
                                br = (byte)((br * 0x0202020202 & 0x010884422010) % 1023);
198
 
199
                                for (int bitidx = 0; bitidx < 8; bitidx++) {
200
                                    int bitpos = x + bitidx;
201
                                    if (bitpos >= this.width)
202
                                        break;
203
                                    int val = br >> bitidx & 0x01;
204
                                    //Console.WriteLine("X:{0} Y:{1}", x.ToString(), y.ToString());
205
                                    this.bitdata[y].Set(bitpos, Convert.ToBoolean(val));
206
                                }
207
                                x += 8;
208
                                i++;
209
                            }
210
                            i += this.bytepad; // Account for the padding
211
                        }
212
                        break;
213
                    }
214
 
215
                    // Read the header data from the file
216
                    switch (pos) {
217
                        // Magic number header ("BM")
218
                        case 0x00: {
219
                                byte t1 = b.ReadByte();
220
                                byte t2 = b.ReadByte();
221
                                pos += 2;
222
                                string text = ((char)t1).ToString();
223
                                text += ((char)t2).ToString();
224
                            }
225
                            break;
226
                        // The size of the image file
227
                        case 0x02: {
228
                                this.filesize = (int)b.ReadUInt32();
229
                                pos += 4;
230
                                if (this.filesize != b.BaseStream.Length)
231
                                    Console.WriteLine("Size mismatch: " + this.filesize.ToString() + ":" + b.BaseStream.Length.ToString());
232
                                else
233
                                    Console.WriteLine("Size: " + this.filesize.ToString());
234
                            }
235
                            break;
236
                        // The start of image data location
237
                        case 0x0a: {
238
                                this.datastart = (int)b.ReadUInt32();
239
                                pos += 4;
240
                            }
241
                            break;
242
                        // The DIB header file size
243
                        case 0x0e: {
244
                                //UInt32 dibhs = b.ReadUInt32();
245
                                b.ReadUInt32();
246
                                pos += 4;
247
                            }
248
                            break;
249
                        // Bitmap width in pixels
250
                        case 0x12: {
251
                                this.width = (int)b.ReadInt32();
252
                                pos += 4;
253
 
254
                                // Rows aligned to a DWORD
255
                                int bitsOver = this.width % 32;
256
                                if (bitsOver > 0) {
257
                                    this.bytepad = (32 - bitsOver) / 8;
258
                                }
259
                            }
260
                            break;
261
                        // Bitmap height in pixels
262
                        case 0x16: {
263
                                this.height = (int)b.ReadInt32();
264
                                pos += 4;
265
                            }
266
                            break;
267
                        // Bitmap bytes per pixel
268
                        case 0x1c: {
269
                                this.bpp = (int)b.ReadUInt16();
270
                                pos += 2;
271
                            }
272
                            break;
273
                        // Bitmap size
274
                        case 0x22: {
275
                                this.imagesize = (int)b.ReadUInt32();
276
                                pos += 4;
277
                            }
278
                            break;
279
 
280
                        // Not an important piece of data; dump it
281
                        default:
282
                            b.ReadByte();
283
                            pos++;
284
                            break;
285
                    }
286
                }
287
            }
288
            return 0;
289
        }
290
 
291
    }
292
 
293
    public class BitImage {
294
 
295
        public BitArray[] bitdata;
296
        public int width;
297
        public int height;
298
 
299
        public BitImage(int width, int height) {
300
            this.width = width;
301
            this.height = height;
302
            this.bitdata = new BitArray[this.height];
303
 
304
            for (int i = 0; i < this.height; i++) {
305
                this.bitdata[i] = new BitArray(this.width);
306
            }
307
        }
308
 
309
        public BitImage(BitArray[] matrix) {
310
            this.width = matrix[0].Length;
311
            this.height = matrix.Length;
312
            this.bitdata = BitImage.copy(matrix);
313
        }
314
 
315
        public BitImage(BmpImage bmp) {
316
            this.width = bmp.width;
317
            this.height = bmp.height;
318
            this.bitdata = BitImage.copy(bmp.bitdata);
319
        }
320
 
321
        public BitImage(BitImage bit) {
322
            this.width = bit.width;
323
            this.height = bit.height;
324
            this.bitdata = BitImage.copy(bit.bitdata);
325
        }
326
 
327
        public BitImage(Bitmap bmp) {
328
            //Bitmap bmp = new Bitmap(nitdcscore.Properties.Resources.flap_bg);
329
            //BitImage bi = new BitImage(new Bitmap(Resources.flap_needle));
330
            this.width = bmp.Width;
331
            this.height = bmp.Height;
332
            this.bitdata = new BitArray[this.height];
333
 
334
            for (int y = 0; y < this.height; y++) {
335
                this.bitdata[y] = new BitArray(this.width);
336
                for (int x = 0; x < this.height; x++) {
337
                    Color c = bmp.GetPixel(x, y);
338
 
339
                    if (c.GetBrightness() == 0)
340
                        this.bitdata[y].Set(x, false);
341
                    else
342
                        this.bitdata[y].Set(x, true);
343
                }
344
            }
345
        }
346
 
347
 
348
 
349
        public void fillAll(bool color) {
350
            for (int i = 0; i < this.height; i++) {
351
                this.bitdata[i].SetAll(color);
352
            }
353
        }
354
 
355
        public void drawPixel(int x, int y, bool color) {
356
            if (x < 0 || y < 0 || x >= this.width || y >= this.height)
357
                return;
358
            this.bitdata[y].Set(x, color);
359
        }
360
 
361
        public void drawVLine(int x, int y, int h, bool color) {
362
 
363
            if (x < 0 || x >= this.width)
364
                return;
365
 
366
            if (y < 0) {
367
                h += y;
368
                y = 0;
369
            }
370
 
371
            if ((y + h) > this.height)
372
                h = this.height - y;
373
 
374
            if (h <= 0)
375
                return;
376
 
377
            for (int i = y; i < y + h; i++) {
378
                this.bitdata[i].Set(x, color);
379
            }
380
        }
381
 
382
        public void drawHLine(int x, int y, int w, bool color) {
383
            if (y < 0 || y >= this.height)
384
                return;
385
            if (x < 0) {
386
                w += x;
387
                x = 0;
388
            }
389
 
390
            if ((x + w) > this.width)
391
                w = this.width - x;
392
 
393
            if (w <= 0)
394
                return;
395
 
396
            for (int i = x; i < x + height; i++) {
397
                this.bitdata[y].Set(i, color);
398
            }
399
        }
400
 
401
 
402
        public void drawLine(int x0, int y0, int x1, int y1, bool color) {
403
            bool steep = Math.Abs(y1 - y0) > Math.Abs(x1 - x0);
404
            if (steep) {
405
                swap(ref x0, ref y0);
406
                swap(ref x1, ref y1);
407
            }
408
 
409
            if (x0 > x1) {
410
                swap(ref x0, ref x1);
411
                swap(ref y0, ref y1);
412
            }
413
 
414
            int dx, dy;
415
            dx = x1 - x0;
416
            dy = Math.Abs(y1 - y0);
417
 
418
            int err = dx / 2;
419
            int ystep;
420
 
421
            if (y0 < y1)
422
                ystep = 1;
423
            else
424
                ystep = -1;
425
 
426
            for (; x0 <= x1; x0++) {
427
                if (steep)
428
                    drawPixel(y0, x0, color);
429
                else
430
                    drawPixel(x0, y0, color);
431
 
432
                err -= dy;
433
                if (err < 0) {
434
                    y0 += ystep;
435
                    err += dx;
436
                }
437
            }
438
        }
439
 
440
        public void drawRect(int x, int y, int w, int h, bool color) {
441
            drawHLine(x, y, w, color);
442
            drawHLine(x, y + h - 1, w, color);
443
            drawVLine(x, y, h, color);
444
            drawVLine(x + w - 1, y, h, color);
445
        }
446
 
447
        public void fillRect(int x, int y, int w, int h, bool color) {
448
            for (int i = x; i < x + w; i++) {
449
                drawVLine(i, y, h, color);
450
            }
451
        }
452
 
453
 
454
        public void drawCircle(int x0, int y0, int r, bool color) {
455
            int f = 1 - r;
456
            int ddF_x = 1;
457
            int ddF_y = -2 * r;
458
            int x = 0;
459
            int y = r;
460
 
461
            drawPixel(x0, y0 + r, color);
462
            drawPixel(x0, y0 - r, color);
463
            drawPixel(x0 + r, y0, color);
464
            drawPixel(x0 - r, y0, color);
465
 
466
            while (x < y) {
467
                if (f >= 0) {
468
                    y--;
469
                    ddF_y += 2;
470
                    f += ddF_y;
471
                }
472
                x++;
473
                ddF_x += 2;
474
                f += ddF_x;
475
 
476
                drawPixel(x0 + x, y0 + y, color);
477
                drawPixel(x0 - x, y0 + y, color);
478
                drawPixel(x0 + x, y0 - y, color);
479
                drawPixel(x0 - x, y0 - y, color);
480
                drawPixel(x0 + y, y0 + x, color);
481
                drawPixel(x0 - y, y0 + x, color);
482
                drawPixel(x0 + y, y0 - x, color);
483
                drawPixel(x0 - y, y0 - x, color);
484
            }
485
        }
486
 
487
        public void fillCircle(int x0, int y0, int r, bool color) {
488
            drawVLine(x0, y0 - r, 2 * r + 1, color);
489
            fillCircleHelper(x0, y0, r, 3, 0, color);
490
        }
491
 
492
        public void fillCircleHelper(int x0, int y0, int r, int corner, int delta, bool color) {
493
            int f = 1 - r;
494
            int ddF_x = 1;
495
            int ddF_y = -2 * r;
496
            int x = 0;
497
            int y = r;
498
 
499
            while (x < y) {
500
                if (f >= 0) {
501
                    y--;
502
                    ddF_y += 2;
503
                    f += ddF_y;
504
                }
505
                x++;
506
                ddF_x += 2;
507
                f += ddF_x;
508
 
509
                if ((corner & 0x01) > 0) {
510
                    drawVLine(x0 + x, y0 - y, 2 * y + 1 + delta, color);
511
                    drawVLine(x0 + y, y0 - x, 2 * x + 1 + delta, color);
512
                }
513
 
514
                if ((corner & 0x02) > 0) {
515
                    drawVLine(x0 - x, y0 - y, 2 * y + 1 + delta, color);
516
                    drawVLine(x0 - y, y0 - x, 2 * x + 1 + delta, color);
517
                }
518
            }
519
        }
520
 
521
        public void drawTriangle(int x0, int y0, int x1, int y1, int x2, int y2, bool color) {
522
            drawLine(x0, y0, x1, y1, color);
523
            drawLine(x1, y1, x2, y2, color);
524
            drawLine(x2, y2, x0, y0, color);
525
        }
526
 
527
        public void drawPoly(Point[] points, bool color) {
528
            int idx = 1;
529
            int c = points.Length;
530
            while (idx < c) {
531
                drawLine(points[idx - 1].X, points[idx - 1].Y, points[idx].X, points[idx].Y, color);
532
                idx++;
533
            }
534
            drawLine(points[c - 1].X, points[c - 1].Y, points[0].X, points[0].Y, color);
535
        }
536
 
537
        public void drawChar(int x, int y, byte c, bool color, int size) {
538
            for (int i = 0; i < 6; i++) {
539
                byte line;
540
                if (i < 5)
541
                    line = Font.classic[c * 5 + i];
542
                else
543
                    line = 0x00;
544
                for (int j = 0; j < 8; j++, line >>= 1) {
545
                    if ((line & 0x01) > 0) {
546
                        if (size == 1)
547
                            drawPixel(x + i, y + j, color);
548
                        else
549
                            fillRect(x + (i * size), y + (j * size), size, size, color);
550
                    }
551
                    /*
552
                    } else {
553
                        if (size == 1)
554
                            drawPixel(x + i, y + j, !color);
555
                        else
556
                            fillRect(x+i*size, y+j*size, size, size, !color);
557
                    }
558
                    */
559
                }
560
 
561
            }
562
        }
563
 
564
        public void write(string text, int x, int y, bool color, int size) {
565
            Point cur = new Point(x, y);
566
            foreach (byte c in text) {
567
                if (c == '\n') {
568
                    cur.Y += size * 8;
569
                    cur.X = x;
570
                } else if (c == '\r') {
571
 
572
                } else if (c == ' ') {
573
                    // Quicker then calling drawChar function
574
                    cur.X += size * 6;
575
                } else {
576
                    drawChar(cur.X, cur.Y, c, color, size);
577
                    cur.X += size * 6;
578
                }
579
            }
580
        }
581
 
582
        public static void swap(ref int i, ref int j) {
583
            int t = i; i = j; j = t;
584
        }
585
 
586
 
587
        /// <summary>
588
        /// Copies the provided image onto the objects image, at position specified
589
        /// by the ox and oy parms. Only copies lit bits (not dark)
590
        /// </summary>
591
        /// <param name="bit">The bit image to paste onto this image</param>
592
        /// <param name="ox">The X origin</param>
593
        /// <param name="oy">The Y origin</param>
594
        public void blit(BitImage bit, int ox, int oy) {
595
            int x = 0;
596
            int y = 0;
597
 
598
            for (y = 0; y < bit.height; y++) {
599
                for (x = 0; x < bit.width; x++) {
600
                    if (bit.bitdata[y].Get(x)) {
601
                        this.bitdata[oy + y].Set(ox + x, true);
602
                    }
603
                }
604
            }
605
        }
606
 
607
        /// <summary>
608
        /// Rotate the image by the specified degrees.
609
        /// </summary>
610
        /// <param name="degrees">Degrees to rotate</param>
611
        public void rotate(int degrees) {
612
            this.bitdata = (BitArray[])BitImage.rotateMatrix(this.bitdata, degrees).bitdata;
613
            this.width = this.bitdata[0].Length;
614
            this.height = this.bitdata.Length;
615
        }
616
 
617
        public byte[] toByteArray() {
618
            return BitImage.toByteArray(this.bitdata);
619
        }
620
 
621
        public static BitArray[] copy(BitArray[] ba) {
622
            int width = ba[0].Length;
623
            int height = ba.Length;
624
 
625
            BitArray[] newba = new BitArray[height];
626
 
627
            for (int y = 0; y < height; y++) {
628
                newba[y] = new BitArray(width);
629
                for (int x = 0; x < width; x++) {
630
                    if (ba[y].Get(x)) {
631
                        newba[y].Set(x, true);
632
                    }
633
                }
634
            }
635
            return newba;
636
        }
637
 
638
        public static byte[] toByteArray(BitArray[] ba) {
639
            int width = ba[0].Length;
640
            int height = ba.Length;
641
 
642
            int size = width * height / 8;
643
            byte[] buffer = new byte[size];
644
            if (size % 8 != 0) {
645
                Console.WriteLine("toByteArray only supports mod 8 array (size: {0}, misalinged by {1})", size, size % 8);
646
                return null;
647
            }
648
 
649
            for (int y = 0; y < ba.Length; y++) {
650
                byte[] bytes = new byte[ba[0].Length / 8];
651
                ba[y].CopyTo(bytes, 0);
652
                for (int i = 0; i < bytes.Length; i++) {
653
                    buffer[y * bytes.Length + i] = bytes[i];
654
                }
655
            }
656
 
657
            return buffer;
658
        }
659
 
660
        /// <summary>
661
        /// Rotates a matrix by provided degrees. Note that the size of the
662
        ///  image may change with this process
663
        /// </summary>
664
        /// <returns>A matrix with the rotated elements</returns>
665
        /// <param name="matrix">The BitArray matrix to be rotated</param>
666
        /// <param name="degrees">The degress to rotate the matrix by</param>
667
        public static BitImage rotateMatrix(BitArray[] matrix, int degrees) {
668
            // Widths of the matrix
669
            int oldwidth = matrix[0].Length;
670
            int oldheight = matrix.Length;
671
 
672
            // If no rotation nessecary, just return a new BitImage
673
            if (degrees == 0 || degrees == 360) {
674
                BitImage bit = new BitImage(oldwidth, oldheight);
675
                bit.bitdata = (BitArray[])matrix;
676
                return bit;
677
            }
678
 
679
            // Calc the new image meta data
680
            double rads = degrees * Math.PI / 180;
681
            double tcos = Math.Cos(rads);
682
            double tsin = Math.Sin(rads);
683
 
684
            Point p1 = new Point((int)(-oldheight * tsin), (int)(oldheight * tcos));
685
            Point p2 = new Point((int)(oldwidth * tcos - oldheight * tsin),
686
                (int)(oldheight * tcos + oldwidth * tsin));
687
            Point p3 = new Point((int)(oldwidth * tcos), (int)(oldwidth * tsin));
688
            Point min = new Point(Math.Min(0, Math.Min(p1.X, Math.Min(p2.X, p3.X))),
689
                Math.Min(0, Math.Min(p1.Y, Math.Min(p2.Y, p3.Y))));
690
            Point max = new Point(Math.Max(p1.X, Math.Max(p2.X, p3.X)),
691
                Math.Max(p1.Y, Math.Max(p2.Y, p3.Y)));
692
            Point size = new Point(max.X - min.X, max.Y - min.Y);
693
 
694
            // Prepopulate the bitarray
695
            BitArray[] bitmatrix = new BitArray[size.Y];
696
            for (int y = 0; y < size.Y; y++) {
697
                bitmatrix[y] = new BitArray(size.X);
698
            }
699
 
700
            // Transform pixel by pixel
701
            for (int y = 0; y < size.Y - 1; y++) {
702
                for (int x = 0; x < size.X - 1; x++) {
703
                    int sourcex = (int)((x + min.X) * tcos + (y + min.Y) * tsin);
704
                    int sourcey = (int)((y + min.Y) * tcos - (x + min.X) * tsin);
705
 
706
                    if (sourcex < 0 || sourcex > oldwidth - 1 || sourcey < 0 || sourcey > oldheight - 1)
707
                        continue;
708
                    if (x < 0 || x > size.X - 1 || y < 0 || y > size.Y - 1)
709
                        continue;
710
 
711
                    bitmatrix[y].Set(x, matrix[sourcey].Get(sourcex));
712
                }
713
            }
714
 
715
            BitImage bi = new BitImage(bitmatrix[0].Length, bitmatrix.Length);
716
            bi.bitdata = (BitArray[])bitmatrix;
717
            return bi;
718
        }
719
 
720
    }
721
 
722
    public struct Point {
723
        private int x;
724
        private int y;
725
 
726
        public int X {
727
            get {
728
                return this.x;
729
            }
730
            set {
731
                this.x = value;
732
            }
733
        }
734
 
735
        public int Y {
736
            get {
737
                return this.y;
738
            }
739
            set {
740
                this.y = value;
741
            }
742
        }
743
 
744
        public Point(int x, int y) {
745
            this.x = x;
746
            this.y = y;
747
        }
748
    }
749
 
750
    public class Font {
751
        public Font() {
752
        }
753
 
754
        public static byte[] classic = new byte[] {
755
            0x00, 0x00, 0x00, 0x00, 0x00,
756
            0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
757
            0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
758
            0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
759
            0x18, 0x3C, 0x7E, 0x3C, 0x18,
760
            0x1C, 0x57, 0x7D, 0x57, 0x1C,
761
            0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
762
            0x00, 0x18, 0x3C, 0x18, 0x00,
763
            0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
764
            0x00, 0x18, 0x24, 0x18, 0x00,
765
            0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
766
            0x30, 0x48, 0x3A, 0x06, 0x0E,
767
            0x26, 0x29, 0x79, 0x29, 0x26,
768
            0x40, 0x7F, 0x05, 0x05, 0x07,
769
            0x40, 0x7F, 0x05, 0x25, 0x3F,
770
            0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
771
            0x7F, 0x3E, 0x1C, 0x1C, 0x08,
772
            0x08, 0x1C, 0x1C, 0x3E, 0x7F,
773
            0x14, 0x22, 0x7F, 0x22, 0x14,
774
            0x5F, 0x5F, 0x00, 0x5F, 0x5F,
775
            0x06, 0x09, 0x7F, 0x01, 0x7F,
776
            0x00, 0x66, 0x89, 0x95, 0x6A,
777
            0x60, 0x60, 0x60, 0x60, 0x60,
778
            0x94, 0xA2, 0xFF, 0xA2, 0x94,
779
            0x08, 0x04, 0x7E, 0x04, 0x08,
780
            0x10, 0x20, 0x7E, 0x20, 0x10,
781
            0x08, 0x08, 0x2A, 0x1C, 0x08,
782
            0x08, 0x1C, 0x2A, 0x08, 0x08,
783
            0x1E, 0x10, 0x10, 0x10, 0x10,
784
            0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
785
            0x30, 0x38, 0x3E, 0x38, 0x30,
786
            0x06, 0x0E, 0x3E, 0x0E, 0x06,
787
            0x00, 0x00, 0x00, 0x00, 0x00,
788
            0x00, 0x00, 0x5F, 0x00, 0x00,
789
            0x00, 0x07, 0x00, 0x07, 0x00,
790
            0x14, 0x7F, 0x14, 0x7F, 0x14,
791
            0x24, 0x2A, 0x7F, 0x2A, 0x12,
792
            0x23, 0x13, 0x08, 0x64, 0x62,
793
            0x36, 0x49, 0x56, 0x20, 0x50,
794
            0x00, 0x08, 0x07, 0x03, 0x00,
795
            0x00, 0x1C, 0x22, 0x41, 0x00,
796
            0x00, 0x41, 0x22, 0x1C, 0x00,
797
            0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
798
            0x08, 0x08, 0x3E, 0x08, 0x08,
799
            0x00, 0x80, 0x70, 0x30, 0x00,
800
            0x08, 0x08, 0x08, 0x08, 0x08,
801
            0x00, 0x00, 0x60, 0x60, 0x00,
802
            0x20, 0x10, 0x08, 0x04, 0x02,
803
            0x3E, 0x51, 0x49, 0x45, 0x3E,
804
            0x00, 0x42, 0x7F, 0x40, 0x00,
805
            0x72, 0x49, 0x49, 0x49, 0x46,
806
            0x21, 0x41, 0x49, 0x4D, 0x33,
807
            0x18, 0x14, 0x12, 0x7F, 0x10,
808
            0x27, 0x45, 0x45, 0x45, 0x39,
809
            0x3C, 0x4A, 0x49, 0x49, 0x31,
810
            0x41, 0x21, 0x11, 0x09, 0x07,
811
            0x36, 0x49, 0x49, 0x49, 0x36,
812
            0x46, 0x49, 0x49, 0x29, 0x1E,
813
            0x00, 0x00, 0x14, 0x00, 0x00,
814
            0x00, 0x40, 0x34, 0x00, 0x00,
815
            0x00, 0x08, 0x14, 0x22, 0x41,
816
            0x14, 0x14, 0x14, 0x14, 0x14,
817
            0x00, 0x41, 0x22, 0x14, 0x08,
818
            0x02, 0x01, 0x59, 0x09, 0x06,
819
            0x3E, 0x41, 0x5D, 0x59, 0x4E,
820
            0x7C, 0x12, 0x11, 0x12, 0x7C,
821
            0x7F, 0x49, 0x49, 0x49, 0x36,
822
            0x3E, 0x41, 0x41, 0x41, 0x22,
823
            0x7F, 0x41, 0x41, 0x41, 0x3E,
824
            0x7F, 0x49, 0x49, 0x49, 0x41,
825
            0x7F, 0x09, 0x09, 0x09, 0x01,
826
            0x3E, 0x41, 0x41, 0x51, 0x73,
827
            0x7F, 0x08, 0x08, 0x08, 0x7F,
828
            0x00, 0x41, 0x7F, 0x41, 0x00,
829
            0x20, 0x40, 0x41, 0x3F, 0x01,
830
            0x7F, 0x08, 0x14, 0x22, 0x41,
831
            0x7F, 0x40, 0x40, 0x40, 0x40,
832
            0x7F, 0x02, 0x1C, 0x02, 0x7F,
833
            0x7F, 0x04, 0x08, 0x10, 0x7F,
834
            0x3E, 0x41, 0x41, 0x41, 0x3E,
835
            0x7F, 0x09, 0x09, 0x09, 0x06,
836
            0x3E, 0x41, 0x51, 0x21, 0x5E,
837
            0x7F, 0x09, 0x19, 0x29, 0x46,
838
            0x26, 0x49, 0x49, 0x49, 0x32,
839
            0x03, 0x01, 0x7F, 0x01, 0x03,
840
            0x3F, 0x40, 0x40, 0x40, 0x3F,
841
            0x1F, 0x20, 0x40, 0x20, 0x1F,
842
            0x3F, 0x40, 0x38, 0x40, 0x3F,
843
            0x63, 0x14, 0x08, 0x14, 0x63,
844
            0x03, 0x04, 0x78, 0x04, 0x03,
845
            0x61, 0x59, 0x49, 0x4D, 0x43,
846
            0x00, 0x7F, 0x41, 0x41, 0x41,
847
            0x02, 0x04, 0x08, 0x10, 0x20,
848
            0x00, 0x41, 0x41, 0x41, 0x7F,
849
            0x04, 0x02, 0x01, 0x02, 0x04,
850
            0x40, 0x40, 0x40, 0x40, 0x40,
851
            0x00, 0x03, 0x07, 0x08, 0x00,
852
            0x20, 0x54, 0x54, 0x78, 0x40,
853
            0x7F, 0x28, 0x44, 0x44, 0x38,
854
            0x38, 0x44, 0x44, 0x44, 0x28,
855
            0x38, 0x44, 0x44, 0x28, 0x7F,
856
            0x38, 0x54, 0x54, 0x54, 0x18,
857
            0x00, 0x08, 0x7E, 0x09, 0x02,
858
            0x18, 0xA4, 0xA4, 0x9C, 0x78,
859
            0x7F, 0x08, 0x04, 0x04, 0x78,
860
            0x00, 0x44, 0x7D, 0x40, 0x00,
861
            0x20, 0x40, 0x40, 0x3D, 0x00,
862
            0x7F, 0x10, 0x28, 0x44, 0x00,
863
            0x00, 0x41, 0x7F, 0x40, 0x00,
864
            0x7C, 0x04, 0x78, 0x04, 0x78,
865
            0x7C, 0x08, 0x04, 0x04, 0x78,
866
            0x38, 0x44, 0x44, 0x44, 0x38,
867
            0xFC, 0x18, 0x24, 0x24, 0x18,
868
            0x18, 0x24, 0x24, 0x18, 0xFC,
869
            0x7C, 0x08, 0x04, 0x04, 0x08,
870
            0x48, 0x54, 0x54, 0x54, 0x24,
871
            0x04, 0x04, 0x3F, 0x44, 0x24,
872
            0x3C, 0x40, 0x40, 0x20, 0x7C,
873
            0x1C, 0x20, 0x40, 0x20, 0x1C,
874
            0x3C, 0x40, 0x30, 0x40, 0x3C,
875
            0x44, 0x28, 0x10, 0x28, 0x44,
876
            0x4C, 0x90, 0x90, 0x90, 0x7C,
877
            0x44, 0x64, 0x54, 0x4C, 0x44,
878
            0x00, 0x08, 0x36, 0x41, 0x00,
879
            0x00, 0x00, 0x77, 0x00, 0x00,
880
            0x00, 0x41, 0x36, 0x08, 0x00,
881
            0x02, 0x01, 0x02, 0x04, 0x02,
882
            0x3C, 0x26, 0x23, 0x26, 0x3C,
883
            0x1E, 0xA1, 0xA1, 0x61, 0x12,
884
            0x3A, 0x40, 0x40, 0x20, 0x7A,
885
            0x38, 0x54, 0x54, 0x55, 0x59,
886
            0x21, 0x55, 0x55, 0x79, 0x41,
887
            0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut
888
            0x21, 0x55, 0x54, 0x78, 0x40,
889
            0x20, 0x54, 0x55, 0x79, 0x40,
890
            0x0C, 0x1E, 0x52, 0x72, 0x12,
891
            0x39, 0x55, 0x55, 0x55, 0x59,
892
            0x39, 0x54, 0x54, 0x54, 0x59,
893
            0x39, 0x55, 0x54, 0x54, 0x58,
894
            0x00, 0x00, 0x45, 0x7C, 0x41,
895
            0x00, 0x02, 0x45, 0x7D, 0x42,
896
            0x00, 0x01, 0x45, 0x7C, 0x40,
897
            0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut
898
            0xF0, 0x28, 0x25, 0x28, 0xF0,
899
            0x7C, 0x54, 0x55, 0x45, 0x00,
900
            0x20, 0x54, 0x54, 0x7C, 0x54,
901
            0x7C, 0x0A, 0x09, 0x7F, 0x49,
902
            0x32, 0x49, 0x49, 0x49, 0x32,
903
            0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut
904
            0x32, 0x4A, 0x48, 0x48, 0x30,
905
            0x3A, 0x41, 0x41, 0x21, 0x7A,
906
            0x3A, 0x42, 0x40, 0x20, 0x78,
907
            0x00, 0x9D, 0xA0, 0xA0, 0x7D,
908
            0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut
909
            0x3D, 0x40, 0x40, 0x40, 0x3D,
910
            0x3C, 0x24, 0xFF, 0x24, 0x24,
911
            0x48, 0x7E, 0x49, 0x43, 0x66,
912
            0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
913
            0xFF, 0x09, 0x29, 0xF6, 0x20,
914
            0xC0, 0x88, 0x7E, 0x09, 0x03,
915
            0x20, 0x54, 0x54, 0x79, 0x41,
916
            0x00, 0x00, 0x44, 0x7D, 0x41,
917
            0x30, 0x48, 0x48, 0x4A, 0x32,
918
            0x38, 0x40, 0x40, 0x22, 0x7A,
919
            0x00, 0x7A, 0x0A, 0x0A, 0x72,
920
            0x7D, 0x0D, 0x19, 0x31, 0x7D,
921
            0x26, 0x29, 0x29, 0x2F, 0x28,
922
            0x26, 0x29, 0x29, 0x29, 0x26,
923
            0x30, 0x48, 0x4D, 0x40, 0x20,
924
            0x38, 0x08, 0x08, 0x08, 0x08,
925
            0x08, 0x08, 0x08, 0x08, 0x38,
926
            0x2F, 0x10, 0xC8, 0xAC, 0xBA,
927
            0x2F, 0x10, 0x28, 0x34, 0xFA,
928
            0x00, 0x00, 0x7B, 0x00, 0x00,
929
            0x08, 0x14, 0x2A, 0x14, 0x22,
930
            0x22, 0x14, 0x2A, 0x14, 0x08,
931
            0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code
932
            0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block
933
            0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block
934
            0x00, 0x00, 0x00, 0xFF, 0x00,
935
            0x10, 0x10, 0x10, 0xFF, 0x00,
936
            0x14, 0x14, 0x14, 0xFF, 0x00,
937
            0x10, 0x10, 0xFF, 0x00, 0xFF,
938
            0x10, 0x10, 0xF0, 0x10, 0xF0,
939
            0x14, 0x14, 0x14, 0xFC, 0x00,
940
            0x14, 0x14, 0xF7, 0x00, 0xFF,
941
            0x00, 0x00, 0xFF, 0x00, 0xFF,
942
            0x14, 0x14, 0xF4, 0x04, 0xFC,
943
            0x14, 0x14, 0x17, 0x10, 0x1F,
944
            0x10, 0x10, 0x1F, 0x10, 0x1F,
945
            0x14, 0x14, 0x14, 0x1F, 0x00,
946
            0x10, 0x10, 0x10, 0xF0, 0x00,
947
            0x00, 0x00, 0x00, 0x1F, 0x10,
948
            0x10, 0x10, 0x10, 0x1F, 0x10,
949
            0x10, 0x10, 0x10, 0xF0, 0x10,
950
            0x00, 0x00, 0x00, 0xFF, 0x10,
951
            0x10, 0x10, 0x10, 0x10, 0x10,
952
            0x10, 0x10, 0x10, 0xFF, 0x10,
953
            0x00, 0x00, 0x00, 0xFF, 0x14,
954
            0x00, 0x00, 0xFF, 0x00, 0xFF,
955
            0x00, 0x00, 0x1F, 0x10, 0x17,
956
            0x00, 0x00, 0xFC, 0x04, 0xF4,
957
            0x14, 0x14, 0x17, 0x10, 0x17,
958
            0x14, 0x14, 0xF4, 0x04, 0xF4,
959
            0x00, 0x00, 0xFF, 0x00, 0xF7,
960
            0x14, 0x14, 0x14, 0x14, 0x14,
961
            0x14, 0x14, 0xF7, 0x00, 0xF7,
962
            0x14, 0x14, 0x14, 0x17, 0x14,
963
            0x10, 0x10, 0x1F, 0x10, 0x1F,
964
            0x14, 0x14, 0x14, 0xF4, 0x14,
965
            0x10, 0x10, 0xF0, 0x10, 0xF0,
966
            0x00, 0x00, 0x1F, 0x10, 0x1F,
967
            0x00, 0x00, 0x00, 0x1F, 0x14,
968
            0x00, 0x00, 0x00, 0xFC, 0x14,
969
            0x00, 0x00, 0xF0, 0x10, 0xF0,
970
            0x10, 0x10, 0xFF, 0x10, 0xFF,
971
            0x14, 0x14, 0x14, 0xFF, 0x14,
972
            0x10, 0x10, 0x10, 0x1F, 0x00,
973
            0x00, 0x00, 0x00, 0xF0, 0x10,
974
            0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
975
            0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
976
            0xFF, 0xFF, 0xFF, 0x00, 0x00,
977
            0x00, 0x00, 0x00, 0xFF, 0xFF,
978
            0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
979
            0x38, 0x44, 0x44, 0x38, 0x44,
980
            0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta
981
            0x7E, 0x02, 0x02, 0x06, 0x06,
982
            0x02, 0x7E, 0x02, 0x7E, 0x02,
983
            0x63, 0x55, 0x49, 0x41, 0x63,
984
            0x38, 0x44, 0x44, 0x3C, 0x04,
985
            0x40, 0x7E, 0x20, 0x1E, 0x20,
986
            0x06, 0x02, 0x7E, 0x02, 0x02,
987
            0x99, 0xA5, 0xE7, 0xA5, 0x99,
988
            0x1C, 0x2A, 0x49, 0x2A, 0x1C,
989
            0x4C, 0x72, 0x01, 0x72, 0x4C,
990
            0x30, 0x4A, 0x4D, 0x4D, 0x30,
991
            0x30, 0x48, 0x78, 0x48, 0x30,
992
            0xBC, 0x62, 0x5A, 0x46, 0x3D,
993
            0x3E, 0x49, 0x49, 0x49, 0x00,
994
            0x7E, 0x01, 0x01, 0x01, 0x7E,
995
            0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
996
            0x44, 0x44, 0x5F, 0x44, 0x44,
997
            0x40, 0x51, 0x4A, 0x44, 0x40,
998
            0x40, 0x44, 0x4A, 0x51, 0x40,
999
            0x00, 0x00, 0xFF, 0x01, 0x03,
1000
            0xE0, 0x80, 0xFF, 0x00, 0x00,
1001
            0x08, 0x08, 0x6B, 0x6B, 0x08,
1002
            0x36, 0x12, 0x36, 0x24, 0x36,
1003
            0x06, 0x0F, 0x09, 0x0F, 0x06,
1004
            0x00, 0x00, 0x18, 0x18, 0x00,
1005
            0x00, 0x00, 0x10, 0x10, 0x00,
1006
            0x30, 0x40, 0xFF, 0x01, 0x01,
1007
            0x00, 0x1F, 0x01, 0x01, 0x1E,
1008
            0x00, 0x19, 0x1D, 0x17, 0x12,
1009
            0x00, 0x3C, 0x3C, 0x3C, 0x3C,
1010
            0x00, 0x00, 0x00, 0x00, 0x00  // #255 NBSP
1011
        };
1012
    }
1013
}