Subversion Repositories group.electronics

Rev

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