Пример #1
0
// TODO code: optimise airspace drawing (same as DrawAirSpace())
// draw airspace using alpha blending
//static 
void MapWindow::DrawTptAirSpace(HDC hdc, const RECT rc) {
  // since standard GDI functions (brushes, pens...) ignore alpha octet in ARGB 
  // color value and don't set it in the resulting bitmap, we cannot use
  // perpixel alpha blending, instead we use global opacity for alpha blend 
  // (same opacity for all pixels); for fully "transparent" areas (without 
  // airspace) we must copy destination bitmap into source bitmap first so that 
  // alpha blending of such areas results in the same pixels as origin pixels 
  // in destination 
  CAirspaceList::const_iterator it;
  CAirspaceList::const_reverse_iterator itr;
  const CAirspaceList& airspaces_to_draw = CAirspaceManager::Instance().GetNearAirspacesRef();
  int airspace_type;
  bool found = false;
  bool borders_only = (GetAirSpaceFillType() == asp_fill_ablend_borders);
  HDC hdcbuffer = NULL;
  HBITMAP hbbufferold = NULL, hbbuffer = NULL;
  static bool asp_selected_flash = false;
  asp_selected_flash = !asp_selected_flash;
  
  if (borders_only) {
    // Prepare layers
    hdcbuffer = CreateCompatibleDC(hdc);
    hbbuffer = CreateCompatibleBitmap(hdc, rc.right - rc.left, rc.bottom - rc.top);
    hbbufferold = (HBITMAP)SelectObject(hdcbuffer, hbbuffer);
    BitBlt(hdcbuffer, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, NULL, rc.left, rc.top, BLACKNESS );
    SelectObject(hdcbuffer, GetStockObject(NULL_PEN));
  
    BitBlt(hDCMask, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, NULL, rc.left, rc.top, BLACKNESS );
    SelectObject(hDCMask, hAirspaceBorderPen);
    SelectObject(hDCMask, GetStockObject(HOLLOW_BRUSH));
  }

  // Draw airspace area
    if (1) {
    CCriticalSection::CGuard guard(CAirspaceManager::Instance().MutexRef());
    if (borders_only) {
       // Draw in reverse order!
       // The idea behind this, is lower top level airspaces are smaller. (statistically)
       // They have to be draw later, because inside border area have to be in correct color,
       // not the color of the bigger airspace above this small one.
      for (itr=airspaces_to_draw.rbegin(); itr != airspaces_to_draw.rend(); ++itr) {
            if ((*itr)->DrawStyle() == adsFilled) {
              airspace_type = (*itr)->Type();
              if (!found) {
                found = true;
                ClearTptAirSpace(hdc, rc);
              }
              // set filling brush
              SelectObject(hdcbuffer, GetAirSpaceSldBrushByClass(airspace_type));
              (*itr)->Draw(hdcbuffer, rc, true);
              (*itr)->Draw(hDCMask, rc, false);
            }
      }//for
    } else {
       // Draw in direct order!
      for (it=airspaces_to_draw.begin(); it != airspaces_to_draw.end(); ++it) {
            if ((*it)->DrawStyle() == adsFilled) {
              airspace_type = (*it)->Type();
              if (!found) {
                found = true;
                ClearTptAirSpace(hdc, rc);
              }
              // set filling brush
              SelectObject(hDCTemp, GetAirSpaceSldBrushByClass(airspace_type));
              (*it)->Draw(hDCTemp, rc, true);
            }
      }//for
    }//else borders_only
    }//mutex release

  // alpha blending
  if (found) {
    if (borders_only) {
      #if (WINDOWSPC<1)
        TransparentImage(hdcbuffer,
                rc.left,rc.top,
                rc.right-rc.left,rc.bottom-rc.top,
                hDCMask,
                rc.left,rc.top,
                rc.right-rc.left,rc.bottom-rc.top,
                RGB_WHITE
                );
        TransparentImage(hDCTemp,
                rc.left,rc.top,
                rc.right-rc.left,rc.bottom-rc.top,
                hdcbuffer,
                rc.left,rc.top,
                rc.right-rc.left,rc.bottom-rc.top,
                RGB_BLACK
                );
        #else
        TransparentBlt(hdcbuffer,
                      rc.left,rc.top,
                      rc.right-rc.left,rc.bottom-rc.top,
                      hDCMask,
                      rc.left,rc.top,
                      rc.right-rc.left,rc.bottom-rc.top,
                      RGB_WHITE
                      );
        TransparentBlt(hDCTemp,
                      rc.left,rc.top,
                      rc.right-rc.left,rc.bottom-rc.top,
                      hdcbuffer,
                      rc.left,rc.top,
                      rc.right-rc.left,rc.bottom-rc.top,
                      RGB_BLACK
                      );
        #endif
    }
    DoAlphaBlend(hdc, rc, hDCTemp, rc, (255 * GetAirSpaceOpacity()) / 100);
  }
  
  // draw it again, just the outlines
  
  // we will be drawing directly into given hdc, so store original PEN object
  HPEN hOrigPen = (HPEN) SelectObject(hdc, GetStockObject(WHITE_PEN));

    if (1) {
    CCriticalSection::CGuard guard(CAirspaceManager::Instance().MutexRef());
	for (it=airspaces_to_draw.begin(); it != airspaces_to_draw.end(); ++it) {
        if ((*it)->DrawStyle()) {
		  airspace_type = (*it)->Type();
		  if (bAirspaceBlackOutline ^ (asp_selected_flash && (*it)->Selected()) ) {
			SelectObject(hdc, GetStockObject(BLACK_PEN));
		  } else {
			SelectObject(hdc, hAirspacePens[airspace_type]);
		  }
		  (*it)->Draw(hdc, rc, false);
        }
	}//for
    }

  if (borders_only) {
    // Free up GDI resources
    SelectObject(hdcbuffer, hbbufferold);
    DeleteObject(hbbuffer);
    DeleteDC(hdcbuffer);
  }
  
  // restore original PEN
  SelectObject(hdc, hOrigPen);
} // DrawTptAirSpace()
Пример #2
0
// TODO code: optimise airspace drawing (same as DrawAirSpace())
// draw airspace using alpha blending
//static 
void MapWindow::DrawTptAirSpace(HDC hdc, const RECT rc) {
  // since standard GDI functions (brushes, pens...) ignore alpha octet in ARGB 
  // color value and don't set it in the resulting bitmap, we cannot use
  // perpixel alpha blending, instead we use global opacity for alpha blend 
  // (same opacity for all pixels); for fully "transparent" areas (without 
  // airspace) we must copy destination bitmap into source bitmap first so that 
  // alpha blending of such areas results in the same pixels as origin pixels 
  // in destination 
  CAirspaceList::const_iterator it;
  CAirspaceList::const_reverse_iterator itr;
  const CAirspaceList& airspaces_to_draw = CAirspaceManager::Instance().GetNearAirspacesRef();
  int airspace_type;
  bool found = false;
  bool borders_only = (GetAirSpaceFillType() == asp_fill_ablend_borders);
  bool outlined_only=(GetAirSpaceFillType()==asp_fill_border_only);

  static bool asp_selected_flash = false;
  asp_selected_flash = !asp_selected_flash;
   
  int nDC1 = SaveDC(mhdcbuffer);
  int nDC2 = SaveDC(hDCMask);
  int nDC3 = SaveDC(hDCTemp);
  
  // Draw airspace area
    if (1) {
    CCriticalSection::CGuard guard(CAirspaceManager::Instance().MutexRef());
    if (borders_only) {
       // Draw in reverse order!
       // The idea behind this, is lower top level airspaces are smaller. (statistically)
       // They have to be draw later, because inside border area have to be in correct color,
       // not the color of the bigger airspace above this small one.
      for (itr=airspaces_to_draw.rbegin(); itr != airspaces_to_draw.rend(); ++itr) {
            if ((*itr)->DrawStyle() == adsFilled) {
              airspace_type = (*itr)->Type();
              if (!found) {
                found = true;
                ClearTptAirSpace(hdc, rc);
              }
              // set filling brush
              SelectObject(mhdcbuffer, GetAirSpaceSldBrushByClass(airspace_type));
              (*itr)->Draw(mhdcbuffer, rc, true);
              (*itr)->Draw(hDCMask, rc, false);
            }
      }//for
    } else {
       // Draw in direct order!
      for (it=airspaces_to_draw.begin(); it != airspaces_to_draw.end(); ++it) {
            if ((*it)->DrawStyle() == adsFilled) {
              airspace_type = (*it)->Type();
              if (!found) {
                found = true;
                ClearTptAirSpace(hdc, rc);
              }
              // set filling brush
              SelectObject(hDCTemp, GetAirSpaceSldBrushByClass(airspace_type));
              (*it)->Draw(hDCTemp, rc, true);
            }
      }//for
    }//else borders_only
    }//mutex release

  // alpha blending
  if (found) {
    if (borders_only) {
        MaskBlt(hDCTemp,
                rc.left,rc.top,
                rc.right-rc.left,rc.bottom-rc.top,
                mhdcbuffer,rc.left,rc.top,
                hMaskBitMap,rc.left,rc.top, MAKEROP4(SRCAND,  0x00AA0029));
    }
    DoAlphaBlend(hdc, rc, hDCTemp, rc, (255 * GetAirSpaceOpacity()) / 100);
  }
  
  // draw it again, just the outlines
  
  // we will be drawing directly into given hdc, so store original PEN object
  HPEN hOrigPen = (HPEN) SelectObject(hdc, GetStockObject(WHITE_PEN));

    if (1) {
    CCriticalSection::CGuard guard(CAirspaceManager::Instance().MutexRef());
	for (it=airspaces_to_draw.begin(); it != airspaces_to_draw.end(); ++it) {
        if ((*it)->DrawStyle()) {
		  airspace_type = (*it)->Type();
		  if ( (((*it)->DrawStyle()==adsFilled)&&!outlined_only&&!borders_only)  ^ (asp_selected_flash && (*it)->Selected()) ) {
			SelectObject(hdc, GetStockObject(BLACK_PEN));
		  } else {
			SelectObject(hdc, hAirspacePens[airspace_type]);
		  }
		  (*it)->Draw(hdc, rc, false);
        }
	}//for
    }
  
  // restore original PEN
  SelectObject(hdc, hOrigPen);
  
  RestoreDC(mhdcbuffer, nDC1);
  RestoreDC(hDCMask, nDC2);    
  RestoreDC(hDCTemp, nDC3);    
} // DrawTptAirSpace()