LKColor LKSurface::SetBkColor(const LKColor& Color) { #ifdef USE_GDI return LKColor(::SetBkColor(*this, Color)); #else if(_pCanvas) { _pCanvas->SetBackgroundColor(Color); } return LKColor(); #endif }
LKColor LKSurface::SetTextColor(const LKColor& Color) { #ifdef WIN32 return LKColor(::SetTextColor(*this, Color)); #else if(_pCanvas) { _pCanvas->SetTextColor(Color); } return LKColor(); #endif }
static void OnAirspacePatternsPaintListItem(WindowControl * Sender, LKSurface& Surface) { (void) Sender; if ((DrawListIndex < NUMAIRSPACEBRUSHES) &&(DrawListIndex >= 0)) { int i = DrawListIndex; Surface.SelectObject(LKBrush_White); Surface.SelectObject(LK_BLACK_PEN); Surface.SetBkColor(LKColor(0xFF, 0xFF, 0xFF)); Surface.SelectObject(MapWindow::GetAirspaceBrush(i)); Surface.SetTextColor(LKColor(0x00, 0x00, 0x00)); Surface.Rectangle(100 * ScreenScale, 2 * ScreenScale, 180 * ScreenScale, 22 * ScreenScale); } }
// inititalise shapes for markers, not the text file surviving restarts void TopologyInitialiseMarks() { StartupStore(TEXT(". Initialise marks%s"),NEWLINE); LockTerrainDataGraphics(); // TODO code: - This convert to non-unicode will not support all languages // (some may use more complicated PATH names, containing Unicode) // char buffer[MAX_PATH]; // ConvertTToC(buffer, LocalPath(TEXT("xcsoar-marks"))); // DISABLED LocalPath // JMW localpath does NOT work for the shapefile renderer! if (topo_marks) { topo_marks->DeleteFiles(); delete topo_marks; } TCHAR buf[MAX_PATH]; LocalPath(buf, _T(LKD_CONF)); _tcscat(buf, _T(DIRSEP)); _tcscat(buf, _T(LKF_SMARKS)); topo_marks = new TopologyWriter(buf, LKColor(0xD0,0xD0,0xD0)); if (topo_marks) { topo_marks->scaleThreshold = 30.0; //topo_marks->scaleDefaultThreshold = 30.0; // 101212 topo_marks->scaleCategory = 0; // 101212 marked locations topo_marks->loadBitmap(IDB_MARK); } UnlockTerrainDataGraphics(); }
LKColor LKColor::MixColors(const LKColor& Color2, double fFact1) const { double fFact2 = 1.0f - fFact1; #ifdef GREYSCALE int Luminosity1 = GetLuminosity(); int Luminosity2 = Color2.GetLuminosity(); int Luminosity = (int) (fFact1 * (double) Luminosity1 + fFact2 * (double) Luminosity2); if (Luminosity > 255) Luminosity = 255; return Color(Luminosity, Alpha()); #else uint8_t red1 = Red(); uint8_t green1 = Green(); uint8_t blue1 = Blue(); uint8_t red2 = Color2.Red(); uint8_t green2 = Color2.Green(); uint8_t blue2 = Color2.Blue(); int red = (int) (fFact1 * (double) red1 + fFact2 * (double) red2); if (red > 255) red = 255; int green = (int) (fFact1 * (double) green1 + fFact2 * (double) green2); if (green > 255) green = 255; int blue = (int) (fFact1 * (double) blue1 + fFact2 * (double) blue2); if (blue > 255) blue = 255; return LKColor((uint8_t) red, (uint8_t) green, (uint8_t) blue); #endif }
void Message::Initialize(RECT rc) { startTime.Update(); block_ref = 0; hidden = true; nvisible = 0; rcmsg = rc; // default; message window can be full size of screen WndMsg.Create(&MainWindow, rc); // change message font for different resolutions // Caution, remember to set font also in Resize.. WndMsg.SetFont(ScreenLandscape ? LK8InfoBigFont : MapWindowBoldFont); WndMsg.SetTextColor(LKColor(0x00,0x00,0x00)); WndMsg.SetBkColor(LKColor(0xFF,0xFF,0xFF)); }
static void OnAirspacePaintListItem(WindowControl * Sender, LKSurface& Surface){ TCHAR label[40]; (void)Sender; if (DrawListIndex < AIRSPACECLASSCOUNT){ int i = DrawListIndex; LK_tcsncpy(label, CAirspaceManager::Instance().GetAirspaceTypeText(i), 39); int w0, w1, w2, x0; if (ScreenLandscape) { w0 = 202*ScreenScale; } else { w0 = 225*ScreenScale; } // LKTOKEN _@M789_ = "Warn" w1 = Surface.GetTextWidth(MsgToken(789))+ScreenScale*10; // LKTOKEN _@M241_ = "Display" w2 = Surface.GetTextWidth(MsgToken(241))+ScreenScale*10; x0 = w0-w1-w2; Surface.SetTextColor(RGB_BLACK); Surface.DrawTextClip(2*ScreenScale, 2*ScreenScale, label, x0-ScreenScale*10); if (colormode) { Surface.SelectObject(LK_WHITE_PEN); Surface.SelectObject(LKBrush_White); Surface.Rectangle(x0, 2*ScreenScale,w0, 22*ScreenScale); Surface.SetTextColor(MapWindow::GetAirspaceColourByClass(i)); Surface.SetBkColor(LKColor(0xFF, 0xFF, 0xFF)); Surface.SelectObject(MapWindow::GetAirspaceBrushByClass(i)); Surface.Rectangle(x0, 2*ScreenScale,w0, 22*ScreenScale); } else { bool iswarn; bool isdisplay; iswarn = (MapWindow::iAirspaceMode[i]>=2); isdisplay = ((MapWindow::iAirspaceMode[i]%2)>0); if (iswarn) { // LKTOKEN _@M789_ = "Warn" _tcscpy(label, MsgToken(789)); Surface.DrawText(w0-w1-w2, 2*ScreenScale, label); } if (isdisplay) { // LKTOKEN _@M241_ = "Display" _tcscpy(label, MsgToken(241)); Surface.DrawText(w0-w2, 2*ScreenScale, label); } } } }
static void OnMultiSelectListPaintListItem(WindowControl * Sender, LKSurface& Surface) { #define PICTO_WIDTH 50 Surface.SetTextColor(RGB_BLACK); if (TaskDrawListIndex < iNO_Tasks) { TCHAR *pToken = NULL; TCHAR *pWClast = NULL; TCHAR *pWClast2 = NULL; TCHAR text[180] = {TEXT("empty")}; TCHAR text1[180] = {TEXT("empty")}; TCHAR text2[180] = {TEXT("empty")}; _tcscpy(text, szTaskStrings [TaskDrawListIndex] ); unsigned int i=0; while (i < _tcslen(text) ) // remove all quotations " { if(text[i]== '"') // quotations found ? { for (unsigned int j= i ; j < _tcslen(text); j++) text[j] = text[j+1]; } i++; } pToken = strsep_r(text, TEXT(","), &pWClast) ; _tcscpy(text1, pToken ); if(*text1 == '\0') _tcscpy(text1, _T("???") ); pToken = strsep_r(pWClast, TEXT(","), &pWClast2) ; // remove takeof point _tcscpy(text2, pWClast2); Surface.SetBkColor(LKColor(0xFF, 0xFF, 0xFF)); PixelRect rc = { 0, 0, 0, // DLGSCALE(PICTO_WIDTH), static_cast<PixelScalar>(Sender->GetHeight()) }; /******************** * show text ********************/ Surface.SetBackgroundTransparent(); Surface.SetTextColor(RGB_BLACK); Surface.DrawText(rc.right + DLGSCALE(2), DLGSCALE(2), text1); int ytext2 = Surface.GetTextHeight(text1); Surface.SetTextColor(RGB_DARKBLUE); Surface.DrawText(rc.right + DLGSCALE(2), ytext2, text2); } }
void MapWindow::DrawStartEndSector(LKSurface& Surface, const RECT& rc, const POINT &Start, const POINT &End, int Index, int Type, double Radius) { double tmp; LKSurface::OldPen oldpen; LKSurface::OldBrush oldbrush; switch (Type) { case 0: // CIRCLE tmp = Radius * zoom.ResScaleOverDistanceModify(); oldpen = Surface.SelectObject(hpStartFinishThick); oldbrush = Surface.SelectObject(LKBrush_Hollow); Surface.Circle(WayPointList[Index].Screen.x, WayPointList[Index].Screen.y, (int) tmp, rc, false, false); Surface.SelectObject(LKPen_Red_N1); Surface.Circle(WayPointList[Index].Screen.x, WayPointList[Index].Screen.y, (int) tmp, rc, false, false); Surface.SelectObject(oldpen); Surface.SelectObject(oldbrush); break; case 1: // LINE Surface.DrawLine(PEN_SOLID, NIBLSCALE(5), End, Start, taskcolor, rc); Surface.DrawLine(PEN_SOLID, NIBLSCALE(1), End, Start, LKColor(255, 0, 0), rc); break; case 2: // SECTOR Surface.DrawLine(PEN_SOLID, NIBLSCALE(5), WayPointList[Index].Screen, Start, taskcolor, rc); Surface.DrawLine(PEN_SOLID, NIBLSCALE(5), WayPointList[Index].Screen, End, taskcolor, rc); Surface.DrawLine(PEN_SOLID, NIBLSCALE(1), WayPointList[Index].Screen, Start, LKColor(255, 0, 0), rc); Surface.DrawLine(PEN_SOLID, NIBLSCALE(1), WayPointList[Index].Screen, End, LKColor(255, 0, 0), rc); break; } }
static void OnAirspaceColoursPaintListItem(WindowControl * Sender, LKSurface& Surface){ (void)Sender; if ((DrawListIndex < NUMAIRSPACECOLORS) &&(DrawListIndex>=0)) { int i = DrawListIndex; Surface.SelectObject(LKBrush_White); Surface.SelectObject(LK_BLACK_PEN); Surface.SetBkColor(LKColor(0xFF, 0xFF, 0xFF)); Surface.SelectObject(MapWindow::GetAirspaceSldBrush(i)); // this is the solid brush Surface.SetTextColor(MapWindow::GetAirspaceColour(i)); Surface.Rectangle( 100*ScreenScale, 2*ScreenScale, 180*ScreenScale, 22*ScreenScale); } }
LKColor LKColor::ChangeBrightness(double fBrightFact) const { #ifdef GREYSCALE int Luminosity = GetLuminosity()*fBrightFact; if (Luminosity > 255) Luminosity = 255; return Color(Luminosity, Alpha()); #else int red = (int) (fBrightFact * (double) Red()); if (red > 255) red = 255; int blue = (int) (fBrightFact * (double) Blue()); if (blue > 255) blue = 255; int green = (int) (fBrightFact * (double) Green()); if (green > 255) green = 255; return LKColor((uint8_t) red, (uint8_t) green, (uint8_t) blue); #endif }
void MapWindow::DrawVisualGlide(LKSurface& Surface, const DiagrammStruct& sDia) { const RECT& rci = sDia.rc; unsigned short numboxrows = 1; #if BUGSTOP LKASSERT(Current_Multimap_SizeY < SIZE4); #endif switch (Current_Multimap_SizeY) { case SIZE0: case SIZE1: numboxrows = 3; break; case SIZE2: numboxrows = 2; break; case SIZE3: numboxrows = 1; break; case SIZE4: return; default: LKASSERT(0); break; } if (!ScreenLandscape) { numboxrows++; if (numboxrows > 3) numboxrows = 3; } TCHAR tmpT[30]; line1Font = LK8VisualTopFont; line2Font = LK8VisualBotFont; SIZE textSizeTop, textSizeBot; Surface.SelectObject(line1Font); _stprintf(tmpT, _T("MMMM")); Surface.GetTextSize(tmpT, &textSizeTop); Surface.SelectObject(line2Font); _stprintf(tmpT, _T("55.5%s 79%s%s "), Units::GetDistanceName(), MsgToken(2179), MsgToken(2183)); Surface.GetTextSize(tmpT, &textSizeBot); // we can cut the waypoint name, but not the value data, so we use the second row of data // to size the box for everything. maxtSizeX = textSizeBot.cx; int a = (rci.right-rci.left) / (textSizeBot.cx+BOXINTERVAL); int b = (rci.right-rci.left) - a * (textSizeBot.cx)-(BOXINTERVAL * (a + 1)); boxSizeX = textSizeBot.cx + (b / (a + 1)); boxSizeY = textSizeTop.cy + 1; // single line (wp name) + distance from bottombar if (numboxrows > 1) { boxSizeY += (textSizeBot.cy * (numboxrows - 1)) - NIBLSCALE(2); if (numboxrows > 2) boxSizeY -= NIBLSCALE(1); } #if DEBUG_SCR StartupStore(_T("boxX=%d boxY=%d \n"), boxSizeX, boxSizeY); #endif #if DEBUG_SCR StartupStore(_T("VG AREA LTRB: %d,%d %d,%d\n"), rci.left, rci.top, rci.right, rci.bottom); #endif const auto oldBrush = Surface.SelectObject(LKBrush_White); const auto oldPen = Surface.SelectObject(LK_BLACK_PEN); BrushReference brush_back; if (!INVERTCOLORS) { brush_back = LKBrush_Black; } else { brush_back = LKBrush_Nlight; } Surface.FillRect(&rci, brush_back); POINT center, p1, p2; center.y = rci.top + (rci.bottom - rci.top) / 2; center.x = rci.left + (rci.right - rci.left) / 2; // numSlotX is the number items we can print horizontally. unsigned short numSlotX = (rci.right - rci.left) / (boxSizeX + BOXINTERVAL); if (numSlotX > MAXBSLOT) numSlotX = MAXBSLOT; #if BUGSTOP LKASSERT(numSlotX > 0); #endif if (numSlotX == 0) return; unsigned short boxInterval = ((rci.right - rci.left)-(boxSizeX * numSlotX)) / (numSlotX + 1); unsigned short oddoffset = ( (rci.right-rci.left) - (boxSizeX * numSlotX) - boxInterval * (numSlotX + 1)) / 2; /* #if BUGSTOP // not really harmful LKASSERT(oddoffset<=boxInterval); #endif */ #if DEBUG_SCR StartupStore(_T("numSlotX=%d ScreenSizeX=%d boxSizeX=%d interval=%d offset=%d\n"), numSlotX, ScreenSizeX, boxSizeX, boxInterval, oddoffset); #endif unsigned int t; // The horizontal grid unsigned int slotCenterX[MAXBSLOT + 1]; for (t = 0; t < numSlotX; t++) { slotCenterX[t] = (t * boxSizeX) + boxInterval * (t + 1)+(boxSizeX / 2) + oddoffset+rci.left; #if DEBUG_SCR StartupStore(_T("slotCenterX[%d]=%d\n"), t, slotCenterX[t]); #endif } // Vertical coordinates of each up/down subwindow, excluding center line int upYtop = rci.top; #if MIDCENTER int upYbottom = center.y + (boxSizeY / 2); int downYtop = center.y - (boxSizeY / 2); #else int upYbottom = center.y - CENTERYSPACE; int downYtop = center.y + CENTERYSPACE; #endif int upSizeY = upYbottom - upYtop - (boxSizeY); ; int downYbottom = rci.bottom; int downSizeY = downYbottom - downYtop - (boxSizeY); ; #if 0 // Reassign dynamically the vertical scale for each subwindow size double vscale = 1000 * (100 - Current_Multimap_SizeY) / 100; #else // Set the vertical range double vscale; if (Units::GetUserAltitudeUnit() == unFeet) vscale = (1000 / TOFEET); else vscale = 300.0; #endif Surface.SetBackgroundTransparent(); RECT trc = rci; // Top part of visual rect, target is over us=unreachable=red trc.top = rci.top; trc.bottom = center.y - 1; #ifndef DITHER RenderSky(Surface, trc, RGB_WHITE, LKColor(150, 255, 150), GC_NO_COLOR_STEPS / 2); #else RenderSky(Surface, trc, RGB_WHITE, RGB_WHITE, GC_NO_COLOR_STEPS / 2); #endif // Bottom part, target is below us=reachable=green trc.top = center.y + 1; trc.bottom = rci.bottom; #ifndef DITHER RenderSky(Surface, trc, LKColor(255, 150, 150), RGB_WHITE, GC_NO_COLOR_STEPS / 2); #else RenderSky(Surface, trc, RGB_WHITE, RGB_WHITE,GC_NO_COLOR_STEPS / 2); #endif // Draw center line p1.x = rci.left + 1; p1.y = center.y; p2.x = rci.right - 1; p2.y = center.y; Surface.SelectObject(LKPen_Black_N1); Surface.DrawSolidLine(p1, p2, rci); #if DEBUG_SCR StartupStore(_T("... Center line: Y=%d\n"), center.y); #endif Surface.SelectObject(line1Font); Surface.SelectObject(LKPen_Black_N0); ResetVisualGlideGlobals(); short res = GetVisualGlidePoints(numSlotX); if (res == INVALID_VALUE) { #if DEBUG_DVG StartupStore(_T("...... GVGP says not ready, wait..\n")); #endif return; } if (res == 0) { #if DEBUG_DVG StartupStore(_T("...... GVGP says no data available!\n")); #endif return; } // Print them all! int offset = (boxSizeY / 2) + CENTERYSPACE; LKBrush bcolor; LKColor rgbcolor, textcolor; int wp; unsigned short zeroslot = 0; double minbrgdiff = 999.0; double minabrgdiff = 999.0; // absolute never negative for (unsigned short n = 0; n < numSlotX; n++) { wp = slotWpIndex[n]; if (!ValidWayPoint(wp)) { // empty slot nothing to print continue; } double brgdiff = WayPointCalc[wp].Bearing - DrawInfo.TrackBearing; // this check is worthless if (brgdiff < -180.0) { brgdiff += 360.0; } else { if (brgdiff > 180.0) brgdiff -= 360.0; } double abrgdiff = brgdiff; if (abrgdiff < 0) abrgdiff *= -1; if (abrgdiff < minabrgdiff) { zeroslot = n; minabrgdiff = abrgdiff; minbrgdiff = brgdiff; } } // Draw vertical line #define DEGRANGE 10 // degrees left and right to perfect target if (minabrgdiff < 1) { p1.x = slotCenterX[zeroslot]; } else { // set fullscale range if (minabrgdiff > DEGRANGE) { minabrgdiff = DEGRANGE; if (minbrgdiff < 0) minbrgdiff = -1 * DEGRANGE; else minbrgdiff = DEGRANGE; } // we shift of course in the opposite direction p1.x = slotCenterX[zeroslot]-(int) ((boxSizeX / (DEGRANGE * 2)) * minbrgdiff); } p2.x = p1.x; p1.y = rci.top + 1; p2.y = rci.bottom - 1; Surface.SelectObject(LKPen_Black_N1); Surface.DrawSolidLine(p1, p2, rci); for (unsigned short n = 0; n < numSlotX; n++) { wp = slotWpIndex[n]; if (!ValidWayPoint(wp)) { // empty slot nothing to print continue; } #if DEBUG_DVG StartupStore(_T("... DVG PRINT [%d]=%d <%s>\n"), n, wp, WayPointList[wp].Name); #endif Sideview_VGWpt[n] = wp; double altdiff = WayPointCalc[wp].AltArriv[AltArrivMode]; int ty; #if DEBUG_SCR StartupStore(_T("... wp=<%s>\n"), WayPointList[wp].Name); #endif // Since terrain can be approximated due to low precision maps, or waypoint position or altitude error, // we have a common problem: we get an obstacle to get to the waypoint because it is // positioned "BELOW" the terrain itself. We try to reduce this problem here. #define SAFETERRAIN 50 // Positive arrival altitude for the waypoint, upper window if (altdiff >= 0) { if (altdiff == 0)altdiff = 1; double d = vscale / altdiff; if (d == 0) d = 1; ty = upYbottom - (int) ((double) upSizeY / d)-(boxSizeY / 2); #if DEBUG_SCR StartupStore(_T("... upYbottom=%d upSizeY=%d / (vscale=%f/altdiff=%f = %f) =- %d ty=%d offset=%d\n"), upYbottom, upSizeY, vscale, altdiff, d, (int) ((double) upSizeY / d), ty, offset); #endif if ((ty - offset) < upYtop) ty = upYtop + offset; if ((ty + offset) > upYbottom) ty = upYbottom - offset; #if DEBUG_SCR StartupStore(_T("... upYtop=%d upYbottom=%d final ty=%d\n"), upYtop, upYbottom, ty); #endif // // This is too confusing. We want simple colors, not shaded // rgbcolor = MixColors( LKColor(50,255,50), LKColor(230,255,230), altdiff/(vscale-50)); // if (altdiff <= SAFETERRAIN) { rgbcolor = RGB_LIGHTYELLOW; } else { if (!CheckLandableReachableTerrainNew(&DrawInfo, &DerivedDrawInfo, WayPointCalc[wp].Distance, WayPointCalc[wp].Bearing)) { rgbcolor = RGB_LIGHTRED; } else { #ifdef DITHER rgbcolor = RGB_WHITE; #else rgbcolor = RGB_LIGHTGREEN; #endif } } bcolor.Create(rgbcolor); } else { double d = vscale / altdiff; if (d == 0) d = -1; ty = downYtop - (int) ((double) downSizeY / d)+(boxSizeY / 2); // - because the left part is negative, we are really adding. if ((ty - offset) < downYtop) ty = downYtop + offset; if ((ty + offset) > downYbottom) ty = downYbottom - offset; #ifdef DITHER rgbcolor = RGB_WHITE; // negative part, no need to render dark #else rgbcolor = RGB_LIGHTRED; #endif bcolor.Create(rgbcolor); } TCHAR line2[40], line3[40]; TCHAR value[40], unit[30]; TCHAR name[NAME_SIZE + 1]; double ar = (WayPointCalc[wp].AltArriv[AltArrivMode] * ALTITUDEMODIFY); _tcscpy(name, WayPointList[wp].Name); CharUpper(name); if (IsSafetyAltitudeInUse(wp)) textcolor = RGB_DARKBLUE; else textcolor = RGB_BLACK; switch (numboxrows) { case 0: #if BUGSTOP LKASSERT(0); #endif return; case 1: // 1 line: waypoint name VGTextInBox(Surface, n, 1, name, NULL, NULL, slotCenterX[n], ty, textcolor, bcolor); break; case 2: // 2 lines: waypoint name + altdiff LKFormatAltDiff(wp, false, value, unit); // Should we print also the GR? if ((ar >= -9999 && ar <= 9999) && (WayPointCalc[wp].GR < MAXEFFICIENCYSHOW)) { if (ar >= -999 && ar <= 999) _stprintf(line2, _T("%s "), value); else _stprintf(line2, _T("%s "), value); LKFormatGR(wp, false, value, unit); _tcscat(line2, value); } else { _stprintf(line2, _T("%s ---"), value); } VGTextInBox(Surface, n, 2, name, line2, NULL, slotCenterX[n], ty, textcolor, bcolor); break; case 3: // 3 lines: waypoint name + dist + altdiff LKFormatDist(wp, false, value, unit); _stprintf(line2, _T("%s%s"), value, unit); LKFormatBrgDiff(wp, false, value, unit); _stprintf(tmpT, _T(" %s%s"), value, unit); _tcscat(line2, tmpT); LKFormatAltDiff(wp, false, value, unit); // Should we print also the GR? if ((ar >= -9999 && ar <= 9999) && (WayPointCalc[wp].GR < MAXEFFICIENCYSHOW)) { if (ar >= -999 && ar <= 999) _stprintf(line3, _T("%s "), value); else _stprintf(line3, _T("%s "), value); LKFormatGR(wp, false, value, unit); _tcscat(line3, value); } else { _stprintf(line3, _T("%s ---"), value); } VGTextInBox(Surface, n, 3, name, line2, line3, slotCenterX[n], ty, textcolor, bcolor); break; default: #if BUGSTOP LKASSERT(0); #endif return; } } // for numSlotX // Cleanup and return Surface.SelectObject(oldBrush); Surface.SelectObject(oldPen); return; }
// // Draw the reachable SHADED terrain glide amoeba // This is not the outlined perimeter // void MapWindow::DrawTerrainAbove(LKSurface& Surface, const RECT& rc) { // Lets try to make it better understandable with a goto. // If CAR or GA users dont want amoeba, they should disable it in config. // Otherwise we should paint it, not hide it automatically! // Here are the conditions we print this amoeba, otherwise we return; // First is we are in SIM mode and we changed the altitude; if (SIMMODE && DerivedDrawInfo.AltitudeAGL>100) goto _doit; // Second, if we are flying if (DerivedDrawInfo.Flying) goto _doit; if (DerivedDrawInfo.GlideFootPrint_valid) goto _doit; return; _doit: #ifndef ENABLE_OPENGL LKColor whitecolor = LKColor(0xff,0xff,0xff); LKColor graycolor = LKColor(0xf0,0xf0,0xf0); LKColor origcolor = TempSurface.SetTextColor(whitecolor); TempSurface.SetBackgroundTransparent(); TempSurface.SetBkColor(whitecolor); TempSurface.SelectObject(LK_WHITE_PEN); TempSurface.SetTextColor(graycolor); TempSurface.SelectObject(hAboveTerrainBrush); TempSurface.Rectangle(rc.left,rc.top,rc.right,rc.bottom); TempSurface.SelectObject(LK_WHITE_PEN); TempSurface.SelectObject(LKBrush_White); TempSurface.Polygon(Groundline.data(),Groundline.size()); // need to do this to prevent drawing of colored outline TempSurface.SelectObject(LK_WHITE_PEN); #ifdef HAVE_HATCHED_BRUSH Surface.TransparentCopy( rc.left,rc.top, rc.right-rc.left,rc.bottom-rc.top, TempSurface, rc.left,rc.top); #else Surface.AlphaBlendNotWhite(rc, TempSurface, rc, 255/2); #endif // restore original color TempSurface.SetTextColor(origcolor); TempSurface.SetBackgroundOpaque(); #else Canvas& canvas = Surface; const GLEnable<GL_STENCIL_TEST> stencil; glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDepthMask(GL_FALSE); glStencilFunc(GL_NEVER, 1, 0xFF); glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP); // draw 1s on test fail (always) // draw stencil pattern glStencilMask(0xFF); glClear(GL_STENCIL_BUFFER_BIT); // needs mask=0xFF ScopeVertexPointer vp(Groundline.data()); glDrawArrays(GL_TRIANGLE_FAN, 0, Groundline.size()); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); glStencilMask(0x00); // draw where stencil's value is 0 glStencilFunc(GL_EQUAL, 0, 0xFF); canvas.DrawFilledRectangle(rc.left,rc.top,rc.right,rc.bottom, AboveTerrainColor); #endif }
void MapWindow::DrawTaskAAT(LKSurface& Surface, const RECT& rc) { int i; double tmp1 = 0.0; if (WayPointList.empty()) return; if (!AATEnabled) return; LockTaskData(); // protect from external task changes /**********************************************/ /* Check if not Validated Waypoint is visible */ bool bDraw = false; int maxTp = 1; rectObj rcrect = (rectObj){(double) rc.left, (double) rc.top, (double) rc.right, (double) rc.bottom}; RECT rcDraw = (RECT){rc.right, rc.bottom, rc.left, rc.top}; for (maxTp = std::max(1, ActiveTaskPoint); ValidTaskPoint(maxTp + 1); ++maxTp) { if (ValidTaskPoint(maxTp)) { int Type = 0; double Radius = 0.; GetTaskSectorParameter(maxTp, &Type, &Radius); switch (Type) { case CONE: case CIRCLE: tmp1 = Task[maxTp].AATCircleRadius * zoom.ResScaleOverDistanceModify(); break; case SECTOR: tmp1 = Task[maxTp].AATSectorRadius * zoom.ResScaleOverDistanceModify(); break; default: tmp1 = 0.0; break; } } PixelScalar x = WayPointList[Task[maxTp].Index].Screen.x; PixelScalar y = WayPointList[Task[maxTp].Index].Screen.y; rectObj rect = (rectObj){x - tmp1, y - tmp1, x + tmp1, y + tmp1}; if (msRectOverlap(&rect, &rcrect) == MS_TRUE) { rcDraw.top = std::min((PixelScalar)rect.miny, rcDraw.top); rcDraw.bottom = std::max((PixelScalar) rect.maxy, rcDraw.bottom); rcDraw.left = std::min((PixelScalar) rect.minx, rcDraw.left); rcDraw.right = std::max((PixelScalar) rect.maxx, rcDraw.right); bDraw = true; } } /**********************************************/ if (bDraw) { // Draw Only if one is Visible #ifdef USE_GDI rcDraw.top = std::max(rc.top, rcDraw.top); rcDraw.bottom = std::min(rc.bottom, rcDraw.bottom); rcDraw.left = std::max(rc.left, rcDraw.left); rcDraw.right = std::min(rc.right, rcDraw.right); LKColor whitecolor = RGB_WHITE; LKColor origcolor = TempSurface.SetTextColor(whitecolor); const auto oldpen = TempSurface.SelectObject(LK_WHITE_PEN); const auto oldbrush = TempSurface.SelectObject(LKBrush_White); if(LKSurface::AlphaBlendSupported()) { // copy original bitmap into temp (for saving fully transparent areas) TempSurface.Copy(rcDraw.left, rcDraw.top, rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top, Surface, rcDraw.left, rcDraw.top); } else { TempSurface.Rectangle(rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom); } TempSurface.SelectObject(LK_NULL_PEN); #ifdef HAVE_HATCHED_BRUSH TempSurface.SelectObject(hAirspaceBrushes[iAirspaceBrush[AATASK]]); #else TempSurface.SelectObject(LKBrush_Yellow); #endif // this color is used as the black bit TempSurface.SetTextColor(Colours[iAirspaceColour[AATASK]]); // this color is the transparent bit TempSurface.SetBkColor(whitecolor); LKSurface & AliasSurface = TempSurface; #else LKSurface & AliasSurface = Surface; Surface.SelectObject(LKBrush(LKColor(255U,255U,0U).WithAlpha(AlphaLevel))); #endif for (i = maxTp - 1; i > std::max(0, ActiveTaskPoint - 1); i--) { if (ValidTaskPoint(i)) { int Type = 0; double Radius = 0.; GetTaskSectorParameter(i, &Type, &Radius); switch (Type) { case CONE: case CIRCLE: tmp1 = Radius * zoom.ResScaleOverDistanceModify(); AliasSurface.DrawCircle( WayPointList[Task[i].Index].Screen.x, WayPointList[Task[i].Index].Screen.y, (int) tmp1, rc, true); break; case SECTOR: tmp1 = Radius * zoom.ResScaleOverDistanceModify(); AliasSurface.Segment( WayPointList[Task[i].Index].Screen.x, WayPointList[Task[i].Index].Screen.y, (int) tmp1, rc, Task[i].AATStartRadial - DisplayAngle, Task[i].AATFinishRadial - DisplayAngle); break; } } } #ifdef USE_GDI // restore original color TempSurface.SetTextColor(origcolor); TempSurface.SelectObject(oldpen); TempSurface.SelectObject(oldbrush); if(!Surface.AlphaBlend(rcDraw, TempSurface,rcDraw, AlphaLevel)) { // if AlphaBlend is not supported, use TransparentBld Surface.TransparentCopy( rcDraw.left, rcDraw.top, rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top, TempSurface, rcDraw.left, rcDraw.top); } #endif } { UnlockTaskData(); } }
static void OnMultiSelectListPaintListItem(WindowControl * Sender, LKSurface& Surface) { #define PICTO_WIDTH 50 Surface.SetTextColor(RGB_BLACK); if ((DrawListIndex < iNO_ELEMENTS) &&(DrawListIndex >= 0)) { int j; static CAirspaceBase airspace_copy; int i = DrawListIndex; LKASSERT(i < MAX_LIST_ITEMS); PixelRect rc = { 0, 0, DLGSCALE(PICTO_WIDTH), static_cast<PixelScalar>(Sender->GetHeight()) }; const CAirspace* pAS = NULL; int HorDist, Bearing, VertDist; double Distance; unsigned int idx = 0; TCHAR text1[180] = {TEXT("empty")}; TCHAR text2[180] = {TEXT("empty")}; TCHAR Comment[80] = {TEXT("")}; TCHAR Comment1[80] = {TEXT("")}; Surface.SetBkColor(LKColor(0xFF, 0xFF, 0xFF)); LKASSERT(i < MAX_LIST_ITEMS); switch (Elements[i].type) { case IM_AIRSPACE: pAS = (CAirspace*) Elements[i].ptr; if (pAS) { /*********************************************************************** * here we use a local copy of the airspace, only common property exists ***********************************************************************/ airspace_copy = CAirspaceManager::Instance().GetAirspaceCopy(pAS); // airspace type already in name? if (_tcsnicmp(airspace_copy.Name(), airspace_copy.TypeName(), _tcslen(airspace_copy.TypeName())) == 0) { _stprintf(text1, TEXT("%s"), airspace_copy.Name()); // yes, take name only } else { // fixed strings max. 20 NAME_SIZE 30 => max. 30 char _stprintf(text1, TEXT("%s %s"), airspace_copy.TypeName(), airspace_copy.Name()); } CAirspaceManager::Instance().GetSimpleAirspaceAltText(Comment, sizeof (Comment) / sizeof (Comment[0]), airspace_copy.Top()); CAirspaceManager::Instance().GetSimpleAirspaceAltText(Comment1, sizeof (Comment1) / sizeof (Comment1[0]), airspace_copy.Base()); CAirspaceManager::Instance().AirspaceCalculateDistance((CAirspace*) pAS, &HorDist, &Bearing, &VertDist); _stprintf(text2, TEXT("%3.1f%s (%s - %s)"), (double) HorDist*DISTANCEMODIFY, Units::GetDistanceName(), Comment1, Comment); //8 + 8+3 21 /**************************************************************** * for drawing the airspace pictorial, we need the original data. * copy contain only base class property, not geo data, * original data are shared ressources ! * for that we need to grant all called methods are thread safe ****************************************************************/ pAS->DrawPicto(Surface, rc); } break; case IM_TASK_PT: case IM_WAYPOINT: idx = -1; LockTaskData(); // protect from external task changes if (Elements[i].type == IM_TASK_PT) { if(ValidTaskPointFast(Elements[i].iIdx)) { idx = Task[Elements[i].iIdx].Index; } } else { if(ValidWayPointFast(Elements[i].iIdx)) { idx = Elements[i].iIdx; } } // This is not a solution. It will avoid a crash but the solution is to understand // why we are getting a wrong idx, eventually. If ever we got a wrong idx! // And then this "fix" should be changed to something more useful, instead of // adopting a totally wrong waypoint for task. assert(idx < WayPointList.size()); if(idx < WayPointList.size()) { if (WayPointList[idx].Comment != NULL) { LK_tcsncpy(Comment, WayPointList[idx].Comment, 30); } else { _tcscpy(Comment, TEXT("")); } DistanceBearing(GPS_INFO.Latitude, GPS_INFO.Longitude, WayPointList[idx].Latitude, WayPointList[idx].Longitude, &Distance, NULL); if (Elements[i].type != IM_TASK_PT) { if (WayPointCalc[idx].IsLandable) { MapWindow::DrawRunway(Surface, &WayPointList[idx], rc, nullptr, 1.5, true); if (WayPointCalc[idx].IsAirport) { // remove spaces from frequency for (j = 1; j < (CUPSIZE_FREQ); j++) if (WayPointList[idx].Freq[CUPSIZE_FREQ - j] == ' ') WayPointList[idx].Freq[CUPSIZE_FREQ - j] = '\0'; if (_tcslen(WayPointList[idx].Freq) > 2) _stprintf(text1, TEXT("%s %s MHz"), WayPointList[idx].Name, WayPointList[idx].Freq); else _stprintf(text1, TEXT("%s"), WayPointList[idx].Name); } else { if (WayPointList[idx].Comment != NULL) _stprintf(text1, TEXT("%s %s"), WayPointList[idx].Name, Comment); else _stprintf(text1, TEXT("%s"), WayPointList[idx].Name); } if ((WayPointList[idx].RunwayLen >= 10) || (WayPointList[idx].RunwayDir > 0)) { _stprintf(text2, TEXT("%3.1f%s (%i%s %02i/%02i %i%s)"), Distance * DISTANCEMODIFY, Units::GetDistanceName(), (int) (WayPointList[idx].Altitude * ALTITUDEMODIFY), Units::GetAltitudeName(), (int) (WayPointList[idx].RunwayDir / 10.0 + 0.5), (int) (AngleLimit360(WayPointList[idx].RunwayDir + 180.0) / 10.0 + 0.5), (int) ((double) WayPointList[idx].RunwayLen * ALTITUDEMODIFY), Units::GetAltitudeName()); } else { _stprintf(text2, TEXT("%3.1f%s (%i%s) "), Distance * DISTANCEMODIFY, Units::GetDistanceName(), (int) (WayPointList[idx].Altitude * ALTITUDEMODIFY), Units::GetAltitudeName()); } }// waypoint isLandable else { MapWindow::DrawWaypointPicto(Surface, rc, &WayPointList[idx]); _stprintf(text1, TEXT("%s %s"), WayPointList[idx].Name, Comment); _stprintf(text2, TEXT("%3.1f%s (%i%s)"), Distance * DISTANCEMODIFY, Units::GetDistanceName(), (int) (WayPointList[idx].Altitude * ALTITUDEMODIFY), Units::GetAltitudeName()); } }// Elements IM_TASK else { int iTaskIdx = Elements[i].iIdx; MapWindow::DrawTaskPicto(Surface, iTaskIdx, rc, 3000); int iLastTaskPoint = 0; while (ValidTaskPoint(iLastTaskPoint)) iLastTaskPoint++; iLastTaskPoint--; if (iTaskIdx == 0) { // _@M2301_ "S" # S = Start Task point _stprintf(text1, TEXT("%s: (%s)"), MsgToken(2301), WayPointList[idx].Name); _stprintf(text2, TEXT("Radius %3.1f%s (%i%s)"), StartRadius * DISTANCEMODIFY, Units::GetDistanceName(), (int) (WayPointList[idx].Altitude * ALTITUDEMODIFY), Units::GetAltitudeName()); } else { if (iTaskIdx == iLastTaskPoint) { // _@M2303_ "F" // max 30 30 => max 60 char _stprintf(text1, TEXT("%s: (%s) "), MsgToken(2303), WayPointList[idx].Name); _stprintf(text2, TEXT("Radius %3.1f%s (%i%s)"), FinishRadius * DISTANCEMODIFY, Units::GetDistanceName(), (int) (WayPointList[idx].Altitude * ALTITUDEMODIFY), Units::GetAltitudeName()); } else { // _@M2302_ "T" # F = Finish point // max 30 30 => max 60 char _stprintf(text1, TEXT("%s%i: (%s) "), MsgToken(2302), iTaskIdx, WayPointList[idx].Name); double SecRadius = 0; SecRadius = SectorRadius; if (AATEnabled) { if (Task[iTaskIdx].AATType == SECTOR) SecRadius = Task[iTaskIdx].AATSectorRadius; else SecRadius = Task[iTaskIdx].AATCircleRadius; } _stprintf(text2, TEXT("Radius %3.1f%s (%i%s)"), SecRadius * DISTANCEMODIFY, Units::GetDistanceName(), (int) (WayPointList[idx].Altitude * ALTITUDEMODIFY), Units::GetAltitudeName()); } } } } UnlockTaskData(); // protect from external task changes break; } /******************** * show text ********************/ Surface.SetBackgroundTransparent(); Surface.SetTextColor(RGB_BLACK); Surface.DrawText(rc.right + DLGSCALE(2), DLGSCALE(2), text1); int ytext2 = Surface.GetTextHeight(text1); Surface.SetTextColor(RGB_DARKBLUE); Surface.DrawText(rc.right + DLGSCALE(2), ytext2, text2); } }
void MapWindow::DrawWindAtAircraft2(LKSurface& Surface, const POINT& Orig, const RECT& rc) { int i; POINT Start; TCHAR sTmp[12]; static SIZE tsize = {0,0}; if (DerivedDrawInfo.WindSpeed<1) { return; // JMW don't bother drawing it if not significant } if (tsize.cx == 0){ const auto oldFont = Surface.SelectObject(MapWindowBoldFont); Surface.GetTextSize(TEXT("99"), 2, &tsize); Surface.SelectObject(oldFont); tsize.cx = tsize.cx/2; } int wmag = iround(4.0*DerivedDrawInfo.WindSpeed); Start.y = Orig.y; Start.x = Orig.x; int kx = tsize.cx/ScreenScale/2; POINT Arrow[7] = { {0,-20}, {-6,-26}, {0,-20}, {6,-26}, {0,-20}, {8+kx, -24}, {-8-kx, -24}}; for (i=1;i<4;i++) Arrow[i].y -= wmag; PolygonRotateShift(Arrow, 7, Start.x, Start.y, DerivedDrawInfo.WindBearing-DisplayAngle); // // Draw Wind Arrow // POINT Tail[2] = {{0,-20}, {0,-26-min(20,wmag)*3}}; double angle = AngleLimit360(DerivedDrawInfo.WindBearing-DisplayAngle); for(i=0; i<2; i++) { if (ScreenScale>1) { Tail[i].x *= ScreenScale; Tail[i].y *= ScreenScale; } protateshift(Tail[i], angle, Start.x, Start.y); } // optionally draw dashed line for wind arrow Surface.DrawLine(PEN_DASH, 1, Tail[0], Tail[1], LKColor(0,0,0), rc); // Paint wind value only while circling if ( (mode.Is(Mode::MODE_CIRCLING)) ) { _stprintf(sTmp, _T("%d"), iround(DerivedDrawInfo.WindSpeed * SPEEDMODIFY)); TextInBoxMode_t TextInBoxMode = {0}; TextInBoxMode.AlligneCenter = true; // { 16 | 32 }; // JMW test {2 | 16}; TextInBoxMode.WhiteBorder = true; if (Arrow[5].y>=Arrow[6].y) { TextInBox(Surface, &rc, sTmp, Arrow[5].x-kx, Arrow[5].y, 0, &TextInBoxMode); } else { TextInBox(Surface, &rc, sTmp, Arrow[6].x-kx, Arrow[6].y, 0, &TextInBoxMode); } } const auto hpOld = Surface.SelectObject(LKPen_Black_N2); const auto hbOld = Surface.SelectObject(LKBrush_Grey); Surface.Polygon(Arrow,5); Surface.SelectObject(hbOld); Surface.SelectObject(hpOld); }