-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathStdFont.cpp
1441 lines (1046 loc) · 43 KB
/
StdFont.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#include "StdFuncs.h"
#include "StdCharConverter.h"
#include "StdFont.h"
#include "StdWindow.h"
#ifdef __amigaos__
#include <proto/diskfont.h>
#include <proto/graphics.h>
#include <graphics/gfxmacros.h>
#include <string.h>
#define NUM_VERTICES 6
#elif defined(QT_GUI_LIB)
#include "Qt/QtWindow.h"
#endif /* QT_GUI_LIB */
/* Colours that can be printed by RFont::DrawColouredText(). This must match */
/* STDFONT_NUM_COLOURS in StdFont.h */
static const COLORREF g_acoColours[] = { RGB(0, 0, 0), RGB(163, 21, 21), RGB(0, 128, 0), RGB(0, 0, 255) };
#if defined(WIN32) && !defined(QT_GUI_LIB)
/**
* Callback function for the EnumFontFamiliesEx() function.
* This function is called for each font in the list of available fonts when the user has
* called the EnumFontFamiliesEx() function. It will check to see if the font specified is
* a bitmap based font and, if so, will add its size to a list of available font sizes.
* This allows the RFont class to determine whether a requested font size is valid.
*
* @date Friday 07-Aug-2015 9:03 am, Henry's Coffee World (Hirschstrasse)
* @param a_poEnumLogFont Pointer to a structure containing information about the font
* @param a_poNewTextMetric Pointer to information regarding the sizes of the font
* @param a_iFontType The type of the font (bitmap or vector)
* @param a_oLParam Pointer to the RFont instance that initiated the enumeration
* @return 1 to continue enumerating fonts, else 0
*/
TInt CALLBACK RFont::FontNameProc(ENUMLOGFONTEX *a_poEnumLogFont, NEWTEXTMETRICEX *a_poNewTextMetric, TInt a_iFontType, LPARAM a_oLParam)
{
TInt Index, Height, LogHeight, RetVal;
RFont *Font;
(void) a_poEnumLogFont;
/* By default we want to know about the next available font */
RetVal = 1;
/* We are only interested in bitmap fonts */
if (a_iFontType != TRUETYPE_FONTTYPE)
{
Font = (RFont *) a_oLParam;
/* First, check to see if the list is full and if so, end the scan */
if (Font->m_iNumSizes == (sizeof(Font->m_aiFontSizes) / sizeof(Font->m_aiFontSizes[0])))
{
RetVal = 0;
}
else
{
/* Determine the logical and physical size of the font */
LogHeight = a_poNewTextMetric->ntmTm.tmHeight;
Height = MulDiv(LogHeight, 72, GetDeviceCaps(Font->m_poWindow->m_poDC, LOGPIXELSY));
/* Search through the list of font sizes to see if it is already in there */
for (Index = 0; Index < Font->m_iNumSizes; ++Index)
{
if (Font->m_aiFontSizes[Index] == Height)
{
break;
}
}
/* If the font is not already in the list then add it */
if (Index == Font->m_iNumSizes)
{
Font->m_aiFontSizes[Font->m_iNumSizes++] = Height;
}
}
}
return(RetVal);
}
#endif /* defined(WIN32) && !defined(QT_GUI_LIB) */
/* Written: Sunday 31-May-2010 1:41 pm */
RFont::RFont(CWindow *a_poWindow)
{
ASSERTM(a_poWindow, "RFont::RFont() => Window handle must not be NULL");
m_pccName = NULL;
m_bHighlight = EFalse;
// TODO: CAW - These are not used by all routines and -1 is probably not a good default
m_iClipWidth = m_iClipHeight = -1;
m_iNumSizes = m_iSize = m_iWidth = m_iHeight = m_iXOffset = m_iYOffset = 0;
m_poWindow = a_poWindow;
#ifdef __amigaos__
unsigned long Red, Green, Blue;
TInt Index;
m_iBaseline = 0;
/* Unit Test support: The Framework must be able to run without a real GUI */
if (m_poWindow->m_poWindow)
{
/* Iterate through the colours and determine the best pen to use for each one. */
/* This is better done here rather than in RFont::DrawColouredText() every */
/* time it is called */
for (Index = 0; Index < STDFONT_NUM_COLOURS; ++Index)
{
Red = Utils::Red32(g_acoColours[Index] & 0xff);
Green = Utils::Green32(g_acoColours[Index] & 0xff00);
Blue = Utils::Blue32(g_acoColours[Index] & 0xff0000);
m_alPens[Index] = ObtainBestPen(m_poWindow->m_poWindow->WScreen->ViewPort.ColorMap, Red, Green, Blue, TAG_DONE);
ASSERTM((m_alPens[Index] != -1), "RFont::RFont() => Unable to allocate pen");
}
}
/* We are using the default font by default */
m_poFont = m_poOldFont = NULL;
#elif defined(QT_GUI_LIB)
m_iBaseline = 0;
m_poFont = NULL;
#else /* ! QT_GUI_LIB */
m_pcRealName = NULL;
m_iWideBufferLength = 0;
m_pwcWideBuffer = NULL;
m_poDC = NULL;
m_poFont = m_poOldFont = NULL;
#endif /* ! QT_GUI_LIB */
}
/**
* Opens the default or a user specified font for use.
* Opens the font for use. This function can be called at any time but before rendering, you
* must first also call RFont::Begin() to setup the rendering context. Begin() can unfortunately
* only be called in response to a system paint event (in other words, from your overridden
* CWindow::draw() function) due to needing to fit in with Qt's architecture. For cross platform
* compatibility, this requirement therefore applies to all platforms, not just Qt.
*
* After this function has been called, the RFont::Width() and RFont::Height() functions are able
* to be called, but no other functions.
*
* @pre Size of the font passed in must be larger than zero
*
* @date Sunday 31-May-2010 3:38 pm
* @param a_iSize Size of the font to be opened, in points. If -1 then the platform's default size
* will be selected
* @param a_pccName Ptr to the name of the font to be opened, which is platform specific. If NULL
* then the platform's default font will be selected
* @return KErrNone if the font was opened successfully, else KErrGeneral
*/
TInt RFont::open(TInt a_iSize, const char *a_pccName)
{
TInt RetVal;
ASSERTM((a_iSize >= -1), "RFont::open() => a_iSize must be >= -1");
#ifdef __amigaos__
struct TextAttr TextAttr;
ASSERTM(m_poWindow, "RFont::open() => Window handle not set");
/* RFont::open() cannot fail on the Amiga */
RetVal = KErrNone;
/* Unit Test support: The Framework must be able to run without a real GUI */
if (m_poWindow->m_poWindow)
{
/* If no font has been specified then use the one used by the current window */
if (!a_pccName)
{
a_pccName = m_poWindow->m_poWindow->RPort->Font->tf_Message.mn_Node.ln_Name;
}
m_pccName = a_pccName;
/* If no size has been specified then use the one used by the current window */
if (a_iSize == -1)
{
a_iSize = m_poWindow->m_poWindow->RPort->Font->tf_YSize;
}
/* If the requested font is different to the current one, or if it has a different size then try */
/* to load it from disc and make it the rastport's default font */
if ((strcmp(a_pccName, m_poWindow->m_poWindow->RPort->Font->tf_Message.mn_Node.ln_Name) != 0) ||
(a_iSize != m_poWindow->m_poWindow->RPort->Font->tf_YSize))
{
TextAttr.ta_Name = a_pccName;
TextAttr.ta_YSize = a_iSize;
TextAttr.ta_Style = 0;
TextAttr.ta_Flags = 0;
/* And try to open the font */
if ((m_poFont = OpenDiskFont(&TextAttr)) != NULL)
{
m_poOldFont = m_poWindow->m_poWindow->RPort->Font;
SetFont(m_poWindow->m_poWindow->RPort, m_poFont);
}
else
{
Utils::info("RFont::open() => Unable to open font \"%s\", using system default", a_pccName);
}
}
/* If the requested font could not be found then fall back to the system font */
if (!m_poFont)
{
m_poFont = m_poWindow->m_poWindow->RPort->Font;
}
/* Determine the baseline, width & height of the font from the window */
m_iBaseline = m_poWindow->m_poWindow->RPort->Font->tf_Baseline;
m_iWidth = m_poWindow->m_poWindow->RPort->Font->tf_XSize;
m_iHeight = m_poWindow->m_poWindow->RPort->Font->tf_YSize;
m_iSize = a_iSize;
}
#elif defined(QT_GUI_LIB)
/* If no font has been specified then use "Monaco" or "Monospace", depending on the platform */
if (!a_pccName)
{
#ifdef __APPLE__
a_pccName = "Monaco";
#else /* ! __APPLE__ */
a_pccName = "Courier New";
#endif /* ! __APPLE__ */
}
m_pccName = a_pccName;
/* Create a monospace font in the desired point size */
if ((m_poFont = new QFont(a_pccName, a_iSize)) != NULL)
{
RetVal = KErrNone;
/* As this is a programmer's editor, we want a fixed width font */
m_poFont->setFixedPitch(true);
/* And enable full hinting for Qt. Although in theory hinting only changes the way that */
/* characters are displayed, leaving the hinting setting on its default on Qt 5 seems to */
/* also change the positioning and width of the characters as well, thus making them no */
/* longer monospaced */
m_poFont->setHintingPreference(QFont::PreferFullHinting);
/* Determine the width & height of the font */
QFontMetrics Metrics(*m_poFont);
m_iBaseline = Metrics.ascent();
m_iHeight = Metrics.height();
m_iWidth = Metrics.averageCharWidth();
m_iSize = a_iSize;
/* If the font we requested was not found, the Qt will try to choose a different but similar font */
/* to what we requested. So query the name of the selected font and save this, rather than just */
/* saving the name of the requested font */
QFontInfo FontInfo(*m_poFont);
m_oRealName = FontInfo.family().toStdString();
m_pccName = m_oRealName.c_str();
/* And assign the font to the window */
m_poWindow->m_poCentralWidget->setFont(*m_poFont);
}
else
{
RetVal = KErrGeneral;
}
#else /* ! QT_GUI_LIB */
TInt Height, Length;
TEXTMETRIC TextMetric;
/* Assume failure */
RetVal = KErrGeneral;
/* If no DC is specified for the window, create a temporary one for use by the class */
if (!m_poWindow->m_poDC)
{
m_poDC = m_poWindow->m_poDC = GetDC(m_poWindow->m_poWindow);
}
if (m_poWindow->m_poDC)
{
/* If no font has been specified then use "Courier New" */
if (!a_pccName)
{
a_pccName = "Courier New";
}
m_pccName = a_pccName;
/* Convert the font size from the desired point size to pixels per inch and attempt to open a font */
/* that uses that size */
Height = -MulDiv(a_iSize, GetDeviceCaps(m_poWindow->m_poDC, LOGPIXELSY), 72);
if ((m_poFont = CreateFont(Height, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, (FF_MODERN | FIXED_PITCH), a_pccName)) != NULL)
{
DEBUGCHECK(SelectObject(m_poWindow->m_poDC, m_poFont), "RFont::open() => Unable to select font into device context");
}
else
{
Utils::info("RFont::open() => Unable to open requested font, using default");
}
/* Determine the width & height of the font from the device context */
if (GetTextMetrics(m_poWindow->m_poDC, &TextMetric))
{
RetVal = KErrNone;
m_iWidth = TextMetric.tmAveCharWidth;
m_iHeight = TextMetric.tmHeight;
m_iSize = a_iSize;
}
/* If the font we requested ws not found, the Windows font mapper will try to choose a different but similar */
/* font to what we requested. So query the name of the selected font and save this, rather than just saving */
/* the name of the requested font */
if ((Length = GetTextFace(m_poWindow->m_poDC, 0, NULL)) > 0)
{
/* Delete the old real name instance, if it was already allocated */
if (m_pcRealName)
{
delete [] m_pcRealName;
}
m_pcRealName = new char[Length + 1];
if (GetTextFace(m_poWindow->m_poDC, Length, m_pcRealName) > 0)
{
m_pccName = m_pcRealName;
}
}
/* Save the background and text colours for l8r use */
m_oBackground = GetBkColor(m_poWindow->m_poDC);
m_oText = GetTextColor(m_poWindow->m_poDC);
}
else
{
Utils::info("RFont::open() => Unable to create temporary DC");
}
#endif /* ! QT_GUI_LIB */
return(RetVal);
}
/* Written: Monday 05-Jul-2010 7:13 am */
/* Closes the font after use and frees any associated resouces */
void RFont::close()
{
m_pccName = NULL;
#ifdef __amigaos__
int Index;
/* If a user defined font was loaded and assigned to the rastport, set the rastport's font back */
/* to the default and free the font */
if (m_poOldFont)
{
SetFont(m_poWindow->m_poWindow->RPort, m_poOldFont);
m_poOldFont = NULL;
CloseFont(m_poFont);
m_poFont = NULL;
}
/* Free any pens that were successfully allocated */
for (Index = 0; Index < STDFONT_NUM_COLOURS; ++Index)
{
ReleasePen(m_poWindow->m_poWindow->WScreen->ViewPort.ColorMap, m_alPens[Index]);
}
#elif defined(WIN32) && !defined(QT_GUI_LIB)
delete [] m_pcRealName;
m_pcRealName = NULL;
Utils::FreeTempBuffer(m_pwcWideBuffer);
m_iWideBufferLength = 0;
m_pwcWideBuffer = NULL;
if (m_poOldFont)
{
DEBUGCHECK(SelectObject(m_poWindow->m_poDC, m_poOldFont), "RFont::close() => Unable to unselect font from device context");
m_poOldFont = NULL;
}
if (m_poFont)
{
DEBUGCHECK(DeleteObject(m_poFont), "RFont::close() => Unable to delete font object");
m_poFont = NULL;
}
if (m_poDC)
{
ReleaseDC(m_poWindow->m_poWindow, m_poDC);
m_poDC = m_poWindow->m_poDC = NULL;
}
#else /* ! defined(WIN32) && !defined(QT_GUI_LIB) */
m_iBaseline = 0;
#endif /* ! defined(WIN32) && !defined(QT_GUI_LIB) */
}
/* Written: Saturday 25-Aug-2012 11:30 am */
/* @return KErrNone if successful, else KErrGeneral if painting could not be started */
/* Prepares the RFont class for writing text using the Draw*() functions. This should be called */
/* when you are about to render text in response to the overridden CWindow::draw() function. */
/* This function exists mainly for compatibility with Qt, which introduces some restrictions on */
/* precisely when rendering can occur. On other operating systems, you can write text using */
/* RFont at any time. However on Qt you can only write text in response to widget paint events. */
/* So we have to follow Qt's way of working, even though it adds extra complexity to our framework */
/* At the end of rendering, call RFont::End() to release the rendering context */
TInt RFont::Begin()
{
TInt RetVal;
/* Assume success */
RetVal = KErrNone;
#ifdef QT_GUI_LIB
QWidget *CentralWidget;
/* Begin the Qt paint process on the window's central widget */
CentralWidget = m_poWindow->m_poWindow->centralWidget();
ASSERTM((CentralWidget != NULL), "RFont::Begin() => Central widget has not been assigned to window");
if (m_oPainter.begin(CentralWidget))
{
/* Save the background and text colours for l8r use */
m_oBackground = m_oPainter.background().color();
m_oText = m_oPainter.pen().color();
}
else
{
RetVal = KErrGeneral;
Utils::info("RFont::Begin() => Unable to begin painting to device");
}
#endif /* QT_GUI_LIB */
#ifdef _DEBUG
if (RetVal == KErrNone)
{
m_bBeginCalled = ETrue;
}
#endif /* _DEBUG */
return(RetVal);
}
/* Written: Saturday 25-Aug-2012 11:32 am */
/* Ends the rendering process started by RFont::Begin(). All calls to RFont::Begin() must */
/* have a matching call to RFont::End() */
void RFont::End()
{
ASSERTM(m_bBeginCalled, "RFont::End() => RFont::Begin() must be called before RFont::End()");
#ifdef _DEBUG
m_bBeginCalled = EFalse;
#endif /* _DEBUG */
/* Set the text and background colours back to their default as these are held by the */
/* operating system and will persist across instances of the RFont class */
SetHighlight(EFalse);
#ifdef QT_GUI_LIB
/* Finish the Qt paint process */
m_oPainter.end();
#endif /* QT_GUI_LIB */
}
/**
* Draws a cursor at the position passed in.
* This method will either draw a cursor or set the position of the system cursor to the position
* passed in, depending on the workings of the underlying OS.
*
* @date Tuesday 08-Jun-2010 6:22 am
* @param a_uiCharacter The character to be drawn, encoded in little endian format
* @param a_iX X position in the window at which to draw, specified as a pixel offset
* @param a_iY Y position in the window at which to draw, specified as a character offset
*/
void RFont::DrawCursor(TUint a_uiCharacter, TInt a_iX, TInt a_iY)
{
int X, Y;
ASSERTM(m_poWindow, "RFont::DrawCursor() => Window handle not set");
ASSERTM(m_bBeginCalled, "RFont::DrawCursor() => RFont::Begin() must be called before RFont::DrawCursor()");
#if defined(__amigaos__) || defined(QT_GUI_LIB)
std::string Buffer = CStdCharConverter::makeString(a_uiCharacter);
#else /* ! defined(__amigaos__) || defined(QT_GUI_LIB) */
(void) a_uiCharacter;
#endif /* defined(__amigaos__) || defined(QT_GUI_LIB) */
/* Invert the current highlight state before drawing the cursor and draw the letter under */
/* the cursor. This will cause it to be highlighted. We toggle the highlight rather than */
/* use ETrue and EFalse so that the cursor works within highlighted blocks of text as well */
SetHighlight(!(m_bHighlight));
#ifdef __amigaos__
PLANEPTR PlanePtr;
ULONG OldDrawMode;
WORD AreaBuffer[(NUM_VERTICES * 5) / 2];
struct AreaInfo AreaInfo;
struct TmpRas TmpRas;
uint16_t DitherData[] = { 0x5555, 0xaaaa };
/* Unit Test support: The Framework must be able to run without a real GUI */
if (m_poWindow->m_poWindow)
{
/* Calculate the position at which to draw the cursor */
X = (m_poWindow->m_poWindow->BorderLeft + m_iXOffset + a_iX);
Y = (m_poWindow->m_poWindow->BorderTop + m_iYOffset + (a_iY * m_iHeight));
/* Now ensure that the cursor is within the bounds of the clipping area before drawing it */
if ((X + m_iWidth) <= (m_poWindow->m_poWindow->BorderLeft + m_iXOffset + m_iClipWidth))
{
/* Move to the position at which to print, taking into account the left and top border sizes, */
/* the height of the current font and the baseline of the font, given that the Text() routine */
/* prints at the baseline position, not the top of the font */
Move(m_poWindow->m_poWindow->RPort, X, (Y + m_iBaseline));
/* If the window is active then draw the cursor over the text as normal */
if (m_poWindow->IsActive())
{
Text(m_poWindow->m_poWindow->RPort, Buffer.data(), Buffer.size());
}
else
{
/* Otherwise draw the cursor in a greyed out state. Start by allocating a raster */
/* that can be used for the dithered flood fill and initialise it */
if ((PlanePtr = AllocRaster(16, 16)) != NULL)
{
InitArea(&AreaInfo, AreaBuffer, NUM_VERTICES);
InitTmpRas(&TmpRas, PlanePtr, ((16 * 16) / 8));
/* Set a dithered drawing mode and initialise the drawing information into the RastPort */
SetAfPt(m_poWindow->m_poWindow->RPort, DitherData, 1);
m_poWindow->m_poWindow->RPort->AreaInfo = &AreaInfo;
m_poWindow->m_poWindow->RPort->TmpRas = &TmpRas;
/* Draw a dithered cursor where the solid one would normally be */
AreaMove(m_poWindow->m_poWindow->RPort, X, Y);
AreaDraw(m_poWindow->m_poWindow->RPort, X, Y);
AreaDraw(m_poWindow->m_poWindow->RPort, (X + m_iWidth - 1), Y);
AreaDraw(m_poWindow->m_poWindow->RPort, (X + m_iWidth - 1), (Y + m_iHeight - 1));
AreaDraw(m_poWindow->m_poWindow->RPort, X, (Y + m_iHeight - 1));
AreaDraw(m_poWindow->m_poWindow->RPort, X, Y);
AreaEnd(m_poWindow->m_poWindow->RPort);
/* Remove the dithered drawing mode */
m_poWindow->m_poWindow->RPort->TmpRas = NULL;
m_poWindow->m_poWindow->RPort->AreaInfo = NULL;
SetAfPt(m_poWindow->m_poWindow->RPort, NULL, 0);
/* And draw the text over the top of the dithered cursor, ensuring that the dithering */
/* is not overwritten */
OldDrawMode = GetDrMd(m_poWindow->m_poWindow->RPort);
SetDrMd(m_poWindow->m_poWindow->RPort, JAM1);
Text(m_poWindow->m_poWindow->RPort, Buffer.data(), Buffer.size());
SetDrMd(m_poWindow->m_poWindow->RPort, OldDrawMode);
FreeRaster(PlanePtr, 16, 16);
}
}
}
}
#elif defined(QT_GUI_LIB)
if (m_poWindow->IsActive())
{
/* Calculate the position at which to draw the cursor */
X = (m_iXOffset + a_iX);
Y = (m_iYOffset + (a_iY * m_iHeight));
/* Set the background mode to opaque, as we want to forcibly draw the cursor over the top of the background */
m_oPainter.setBackgroundMode(Qt::OpaqueMode);
/* And render the inverted character in the cursor, taking into account that QPainter::drawText() */
/* uses the Y position as the baseline of the font, not as the top */
QByteArray String = QByteArray::fromRawData(Buffer.data(), (int) Buffer.size());
m_oPainter.drawText(X, (Y + m_iBaseline), String);
/* Set the background mode back to transparent so that if there is a pretty transparent background or a */
/* gradient in the background it is displayed correctly */
m_oPainter.setBackgroundMode(Qt::TransparentMode);
}
#else /* ! QT_GUI_LIB */
/* Calculate the position at which to draw the cursor */
X = (m_iXOffset + a_iX);
Y = (m_iYOffset + (a_iY * m_iHeight));
/* And move the cursor to the calculated position */
m_poWindow->SetCursorInfo(X, Y, m_iHeight);
#endif /* ! QT_GUI_LIB */
/* Toggle the highlight state back to normal, remembering that calling SetHighlight() */
/* above will have set the state of the highlight flag */
SetHighlight(!(m_bHighlight));
}
/**
* Draws a string of text to a window.
* Draws a string to the window the font is assigned to at the specified X and Y
* positions.
*
* @date Sunday 09-May-2010 6:57 pm
* @param a_pccText Pointer to string to be drawn to the screen
* @param a_iSize Size of the string pointed to by a_pccText
* @param a_iX X position in the window at which to draw, specified as a pixel offset
* @param a_iY Y position in the window at which to draw, specified as a character offset
* @param a_eEncoding Text encoding in which the string is encoded
*/
void RFont::DrawText(const char *a_pccText, TInt a_iSize, TInt a_iX, TInt a_iY, enum TEncoding a_eEncoding)
{
ASSERTM(a_pccText, "RFont::DrawText() => Text ptr must not be NULL");
ASSERTM(m_poWindow, "RFont::DrawText() => Window handle not set");
ASSERTM(m_bBeginCalled, "RFont::DrawText() => RFont::Begin() must be called before RFont::DrawText()");
#ifdef __amigaos__
TInt NumChars, Width;
struct TextExtent TextExtent;
(void) a_eEncoding;
/* Unit Test support: The Framework must be able to run without a real GUI */
if (m_poWindow->m_poWindow)
{
/* Move to the position at which to print, taking into account the left and top border sizes, */
/* the height of the current font and the baseline of the font, given that the Text() routine */
/* prints at the baseline position, not the top of the font */
Move(m_poWindow->m_poWindow->RPort, (m_poWindow->m_poWindow->BorderLeft + m_iXOffset + a_iX),
(m_poWindow->m_poWindow->BorderTop + m_iYOffset + (a_iY * m_iHeight) + m_iBaseline));
/* Calculate the maximum number of characters that can fit in the client area of the window, */
/* as text is not automatically clipped by the Amiga OS text drawing routine. The text may */
/* not start at the very left of the screen so take this into account */
Width = (m_iClipWidth - m_iWidth);
Width = MAX(0, Width);
NumChars = TextFit(m_poWindow->m_poWindow->RPort, a_pccText, a_iSize, &TextExtent, NULL, 1,
Width, m_poWindow->InnerHeight());
/* And draw as much of the text passed in as will fit in the client area */
Text(m_poWindow->m_poWindow->RPort, a_pccText, NumChars);
}
#elif defined(QT_GUI_LIB)
(void) a_eEncoding;
/* Render the string passed in, taking into account that QPainter::drawText() uses the Y position as */
/* the baseline of the font, not as the top */
QByteArray String(a_pccText, a_iSize);
m_oPainter.drawText((m_iXOffset + a_iX), (m_iYOffset + (a_iY * m_iHeight) + m_iBaseline), String);
#else /* ! QT_GUI_LIB */
TInt WideLength;
UINT CodePage;
/* The text must be converted to UTF-16 format before it can be displayed, or some characters will not be displayed */
/* correctly, such as the Euro sign */
CodePage = (a_eEncoding == EEncodingUTF8) ? CP_UTF8 : 28605;
/* Determine how many characters will be in the converted text. If this is larger than the number of */
/* characters in the currently allocated temporary buffer then reallocate it */
if ((WideLength = MultiByteToWideChar(CodePage, 0, a_pccText, a_iSize, NULL, 0)) > m_iWideBufferLength)
{
if ((m_pwcWideBuffer = (WCHAR *) Utils::GetTempBuffer((char *) m_pwcWideBuffer, (WideLength * sizeof(WCHAR)), 0)) != NULL)
{
m_iWideBufferLength = WideLength;
}
}
/* If the temporary buffer was successfully allocated then convert the text to UTF-16 and draw it. In the */
/* unlikely event that something went wrong then this method will just fail silently */
if (m_pwcWideBuffer)
{
if ((WideLength = MultiByteToWideChar(CodePage, 0, a_pccText, a_iSize, m_pwcWideBuffer, m_iWideBufferLength)) > 0)
{
TextOutW(m_poWindow->m_poDC, (m_iXOffset + a_iX), (m_iYOffset + (a_iY * m_iHeight)), m_pwcWideBuffer, WideLength);
}
}
#endif /* ! QT_GUI_LIB */
}
/**
* Draws a coloured string of text to a window.
* Draws a string to the window the font is assigned to at the specified X and Y
* positions. Unline RFont::DrawText(), this text contains embedded codes that
* specify the colour to use for each run of characters. The encoded text is of the
* following format:
*
* Size Colour Text[Size] 0
*
* The Size byte specifies the size of the upcoming run of text in bytes. It is 0 to terminate
* the string. The Colour byte specifies the colour in which to draw and following this are
* Size bytes of the text itself. After this, the sequence repeats or is terminated with 0.
*
* This method can also handle Unicode strings being encoded into the data. The decoding of such
* strings is handled by the underlying OS. If an error occurs during translation, this method
* will silently fail. This means that the Size count mentioned above is the number of bytes to
* be drawn, not the number of characters.
*
* It is also possible to skip a number of characters at the start of the string by specifying
* the number of characters to skip in a_iStartOffset.
*
* @date Thursday 01-Dec-2011 8:43 pm, Munich Airport, awaiting flight EK 052 to Dubai
* @param a_pccText Pointer to string to be drawn to the screen
* @param a_iStartOffset Index into the text at which to start drawing
* @param a_iX X position in the window at which to draw, specified as a character offset
* @param a_iY Y position in the window at which to draw, specified as a character offset
* @param a_eEncoding Text encoding in which the string is encoded
*/
void RFont::DrawColouredText(const char *a_pccText, TInt a_iStartOffset, TInt a_iX, TInt a_iY, enum TEncoding a_eEncoding)
{
TInt Colour, Size, Skip, XPixels, XPosition;
ASSERTM(a_pccText, "RFont::DrawColouredText() => Text ptr must not be NULL");
ASSERTM(m_poWindow, "RFont::DrawColouredText() => Window handle not set");
ASSERTM(m_bBeginCalled, "RFont::DrawColouredText() => RFont::Begin() must be called before RFont::DrawColouredText()");
ASSERTM((a_iX == 0), "RFont::DrawColouredText() => Non zero X positions are not currently supported");
#ifdef __amigaos__
TInt NumChars, Width;
struct TextExtent TextExtent;
(void) a_eEncoding;
/* Determine how much space we have in which to print. The text may not start at the very left */
/* of the screen so take this into account */
Width = (m_iClipWidth - (a_iX * m_iWidth));
Width = MAX(0, Width);
/* Unit Test support: The Framework must be able to run without a real GUI */
if (m_poWindow->m_poWindow)
{
/* Iterate through the source text and display the runs of characters in the required colour */
std::string LineText;
while (*a_pccText)
{
/* Get the size of the run and the colour in which to to display the run in */
Size = *a_pccText++;
Colour = *a_pccText++;
ASSERTM((Colour < STDFONT_NUM_COLOURS), "RFont::DrawColouredText() => Colour index out of range");
/* Display the text in the required colour. If the highlight is set then */
/* the colours will already have been inversed so leave them as they are */
if (!(m_bHighlight))
{
SetAPen(m_poWindow->m_poWindow->RPort, m_alPens[Colour]);
}
/* If it has been requested to start drawing from an index into the string then update the pointer */
/* to the text to point to the character at that index */
if (a_iStartOffset > 0)
{
if (a_iX < a_iStartOffset)
{
Skip = (a_iStartOffset - a_iX);
if (Skip > Size)
{
Skip = Size;
}
a_iX += Skip;
a_pccText += Skip;
Size -= Skip;
}
}
/* Move to the position at which to print, taking into account the left and top border sizes, */
/* the height of the current font and the baseline of the font, given that the Text() routine */
/* prints at the baseline position, not the top of the font */
XPixels = TextWidthInPixels(LineText.c_str(), LineText.size(), LineText.size());
XPosition = (m_iXOffset + XPixels);
/* If it is outside of the clipping rectangle, break out. Unlike the other versions, on Amiga OS, */
/* continuing to print outside the clipping rectangle would actually print text outside the clipping */
/* rectangle so we have to clip manually */
if (XPosition > m_iClipWidth)
{
break;
}
Move(m_poWindow->m_poWindow->RPort, (m_poWindow->m_poWindow->BorderLeft + XPosition),
(m_poWindow->m_poWindow->BorderTop + m_iYOffset + (a_iY * m_iHeight) + m_iBaseline));
/* Calculate the maximum number of characters that can fit in the client area of the window, */
/* as text is not automatically clipped by the Amiga OS text drawing routine. Note that the */
/* clip width reduces as we print the parts of the string */
NumChars = TextFit(m_poWindow->m_poWindow->RPort, a_pccText, Size, &TextExtent, NULL, 1,
Width, m_poWindow->InnerHeight());
/* Only display the text if some of it is on the screen. As well as being clipped, it could be */
/* that the text is scrolled to the left of the screen and thus is not visible */
if (NumChars > 0)
{
Text(m_poWindow->m_poWindow->RPort, a_pccText, NumChars);
}
/* And prepare for the next run to be displayed */
a_iX += Size;
LineText.append(a_pccText, Size);
a_pccText += Size;
Width -= TextExtent.te_Width;
ASSERTM((Width >= 0), "RFont::DrawColouredText() => Out of space");
}
}
#elif defined(QT_GUI_LIB)
(void) a_eEncoding;
/* Iterate through the source text and display the runs of characters in the required colour */
QByteArray LineText;
while (*a_pccText)
{
/* Get the size of the run and the colour in which to to display the run in */
Size = *a_pccText++;
Colour = *a_pccText++;
ASSERTM((Colour < STDFONT_NUM_COLOURS), "RFont::DrawColouredText() => Colour index out of range");
/* If the highlight is set then the colours will already have been inversed so don't change them */
if (!(m_bHighlight))
{
QPen Pen(QColor((g_acoColours[Colour] & 0xff), ((g_acoColours[Colour] & 0xff00) >> 8), (g_acoColours[Colour] >> 16)));
m_oPainter.setPen(Pen);
}
/* If it has been requested to start drawing from an index into the string then update the pointer */
/* to the text to point to the character at that index */
if (a_iStartOffset > 0)
{
if (a_iX < a_iStartOffset)
{
Skip = (a_iStartOffset - a_iX);
if (Skip > Size)
{
Skip = Size;
}
a_iX += Skip;
a_pccText += Skip;
Size -= Skip;
}
}
/* Determine the starting X position at which to print. If it is outside of the clipping rectangle, */
/* break out as there is no point continuing to print the text runs, which would be clipped by the */
/* system print routine */