bool C4Surface::ReadBMP(CStdStream &hGroup, int iFlags) { int lcnt; C4BMP256Info BitmapInfo; // read bmpinfo-header if (!hGroup.Read(&BitmapInfo,sizeof(C4BMPInfo))) return false; // is it 8bpp? if (BitmapInfo.Info.biBitCount == 8) { if (!hGroup.Read(((BYTE *) &BitmapInfo)+sizeof(C4BMPInfo), std::min(sizeof(BitmapInfo)-sizeof(C4BMPInfo),sizeof(BitmapInfo)-sizeof(C4BMPInfo)+BitmapInfo.FileBitsOffset()))) return false; if (!hGroup.Advance(BitmapInfo.FileBitsOffset())) return false; } else { // read 24bpp if (BitmapInfo.Info.biBitCount != 24) return false; if (!hGroup.Advance(((C4BMPInfo) BitmapInfo).FileBitsOffset())) return false; } // Create and lock surface if (!Create(BitmapInfo.Info.biWidth,BitmapInfo.Info.biHeight, iFlags)) return false; if (!Lock()) { Clear(); return false; } // create line buffer int iBufSize=DWordAligned(BitmapInfo.Info.biWidth*BitmapInfo.Info.biBitCount/8); BYTE *pBuf = new BYTE[iBufSize]; // Read lines for (lcnt=Hgt-1; lcnt>=0; lcnt--) { if (!hGroup.Read(pBuf, iBufSize)) { Clear(); delete [] pBuf; return false; } BYTE *pPix=pBuf; for (int x=0; x<BitmapInfo.Info.biWidth; ++x) switch (BitmapInfo.Info.biBitCount) { case 8: SetPixDw(x, lcnt, C4RGB( BitmapInfo.Colors[*pPix].rgbRed, BitmapInfo.Colors[*pPix].rgbGreen, BitmapInfo.Colors[*pPix].rgbBlue)); ++pPix; break; case 24: SetPixDw(x, lcnt, C4RGB(pPix[0], pPix[1], pPix[2])); pPix+=3; break; } } // free buffer again delete [] pBuf; Unlock(); return true; }
void C4Sky::SetFadePalette(int32_t *ipColors) { // If colors all zero, use game palette default blue if (ipColors[0]+ipColors[1]+ipColors[2]+ipColors[3]+ipColors[4]+ipColors[5]==0) { FadeClr1=C4RGB(0x1c, 0x40, 0x99); FadeClr2=C4RGB(0xc2, 0xc6, 0xff); } else { // set colors FadeClr1=C4RGB(ipColors[0], ipColors[1], ipColors[2]); FadeClr2=C4RGB(ipColors[3], ipColors[4], ipColors[5]); } }
bool CSurface8::Read(CStdStream &hGroup) { int cnt,lcnt; C4BMP256Info BitmapInfo; // read bmpinfo-header if (!hGroup.Read(&BitmapInfo,sizeof(C4BMPInfo))) return false; // is it 8bpp? if (BitmapInfo.Info.biBitCount == 8) { if (!hGroup.Read(((BYTE *) &BitmapInfo)+sizeof(C4BMPInfo),sizeof(BitmapInfo)-sizeof(C4BMPInfo))) return false; if (!hGroup.Advance(BitmapInfo.FileBitsOffset())) return false; } else { // read 24bpp if (BitmapInfo.Info.biBitCount != 24) return false; if (!hGroup.Advance(((C4BMPInfo) BitmapInfo).FileBitsOffset())) return false; } // Create and lock surface if (!Create(BitmapInfo.Info.biWidth,BitmapInfo.Info.biHeight)) return false; if (BitmapInfo.Info.biBitCount == 8) { // Copy palette for (cnt=0; cnt<256; cnt++) { pPal->Colors[cnt] = C4RGB(BitmapInfo.Colors[cnt].rgbRed, BitmapInfo.Colors[cnt].rgbGreen, BitmapInfo.Colors[cnt].rgbBlue); } } // create line buffer int iBufSize=DWordAligned(BitmapInfo.Info.biWidth*BitmapInfo.Info.biBitCount/8); BYTE *pBuf = new BYTE[iBufSize]; // Read lines for (lcnt=Hgt-1; lcnt>=0; lcnt--) { if (!hGroup.Read(pBuf, iBufSize)) { Clear(); delete [] pBuf; return false; } BYTE *pPix=pBuf; for (int x=0; x<BitmapInfo.Info.biWidth; ++x) switch (BitmapInfo.Info.biBitCount) { case 8: SetPix(x, lcnt, *pPix++); break; case 24: return false; break; } } // free buffer again delete [] pBuf; return true; }
DWORD CPNGFile::GetPix(int iX, int iY) { // image loaded? if (!pImageData) return 0; // return pixel value unsigned char *pPix=pImageData+iY*iRowSize+iX*iPixSize; switch (iClrType) { case PNG_COLOR_TYPE_RGB: return C4RGB(pPix[2], pPix[1], pPix[0]); case PNG_COLOR_TYPE_RGB_ALPHA: return RGBA(pPix[2], pPix[1], pPix[0], pPix[3]); } return 0; }
void C4GraphicsSystem::ApplyGamma() { // No gamma effects if (Config.Graphics.DisableGamma) return; // calculate color channels by adding the difference between the gamma ramps to their normals int32_t ChanOff[3]; DWORD Gamma[3]; const int32_t DefChanVal[3] = { 0x00, 0x80, 0xff }; // calc offset for curve points for (int32_t iCurve=0; iCurve<3; ++iCurve) { ZeroMemory(ChanOff, sizeof(int32_t)*3); // ...channels... for (int32_t iChan=0; iChan<3; ++iChan) // ...ramps... for (int32_t iRamp=0; iRamp<C4MaxGammaRamps; ++iRamp) // add offset ChanOff[iChan]+=(int32_t) BYTE(dwGamma[iRamp*3+iCurve]>>(16-iChan*8)) - DefChanVal[iCurve]; // calc curve point Gamma[iCurve]=C4RGB(BoundBy<int32_t>(DefChanVal[iCurve]+ChanOff[0], 0, 255), BoundBy<int32_t>(DefChanVal[iCurve]+ChanOff[1], 0, 255), BoundBy<int32_t>(DefChanVal[iCurve]+ChanOff[2], 0, 255)); } // set gamma Application.DDraw->SetGamma(Gamma[0], Gamma[1], Gamma[2]); }
void C4Menu::DrawFrame(C4Surface * sfcSurface, int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt) { pDraw->DrawFrameDw(sfcSurface, iX+1, iY+1, iX+iWdt-1,iY+iHgt-1, C4RGB(0x44, 0, 0)); }
void C4MenuItem::DrawElement(C4TargetFacet &cgo) { // get target pos C4Facet cgoOut(cgo.Surface, cgo.TargetX + rcBounds.x, cgo.TargetY + rcBounds.y, rcBounds.Wdt, rcBounds.Hgt); // Select mark if (iStyle!=C4MN_Style_Info) if (fSelected && TextDisplayProgress) pDraw->DrawBoxDw(cgo.Surface, cgoOut.X, cgoOut.Y, cgoOut.X + cgoOut.Wdt - 1, cgoOut.Y + cgoOut.Hgt - 1, C4RGB(0xca, 0, 0)); // Symbol/text areas C4Facet cgoItemSymbol,cgoItemText; cgoItemSymbol=cgoItemText=cgoOut; int32_t iSymWidth; if ((iSymWidth = GetSymbolWidth(cgoItemText.Hgt))) { // get symbol area cgoItemSymbol=cgoItemText.Truncate(C4FCT_Left, iSymWidth); } // cgoItemSymbol.Hgt is 0. This means rcBounds.Hgt is 0. That // makes no sense at this point, so let's just draw in a // square area at item y. C4Facet cgoSymbolOut(cgoItemSymbol.Surface, cgoItemSymbol.X, cgoItemSymbol.Y, cgoItemSymbol.Wdt, cgoItemSymbol.Wdt); // Draw item symbol: // Draw if there is no text progression at all (TextDisplayProgress==-1, or if it's progressed far enough already (TextDisplayProgress>0) if(pSymbolObj && TextDisplayProgress) { pSymbolObj->DrawPicture(cgoSymbolOut, false, NULL); } else if (pSymbolGraphics && TextDisplayProgress) { pSymbolGraphics->Draw(cgoSymbolOut, dwSymbolClr ? dwSymbolClr : 0xffffffff, NULL, 0, 0, NULL); } else if (Symbol.Surface && TextDisplayProgress) Symbol.DrawClr(cgoItemSymbol, true, dwSymbolClr); // Draw item text pDraw->StorePrimaryClipper(); pDraw->SubPrimaryClipper(cgoItemText.X, cgoItemText.Y, cgoItemText.X+cgoItemText.Wdt-1, cgoItemText.Y+cgoItemText.Hgt-1); switch (iStyle) { case C4MN_Style_Context: pDraw->TextOut(Caption,::GraphicsResource.FontRegular, 1.0, cgoItemText.Surface,cgoItemText.X,cgoItemText.Y,C4Draw::DEFAULT_MESSAGE_COLOR,ALeft); break; case C4MN_Style_Info: { StdStrBuf sText; ::GraphicsResource.FontRegular.BreakMessage(InfoCaption, cgoItemText.Wdt, &sText, true); pDraw->TextOut(sText.getData(), ::GraphicsResource.FontRegular, 1.0, cgoItemText.Surface,cgoItemText.X,cgoItemText.Y); break; } case C4MN_Style_Dialog: { // cut buffer at text display pos char cXChg='\0'; int iStopPos = 0; if (TextDisplayProgress>-1) { iStopPos = std::min<int>(TextDisplayProgress, strlen(Caption)); cXChg = Caption[iStopPos]; Caption[iStopPos] = '\0'; } // display broken text StdStrBuf sText; ::GraphicsResource.FontRegular.BreakMessage(Caption, cgoItemText.Wdt, &sText, true); pDraw->TextOut(sText.getData(),::GraphicsResource.FontRegular, 1.0, cgoItemText.Surface,cgoItemText.X,cgoItemText.Y); // restore complete text if (cXChg) Caption[iStopPos] = cXChg; break; } } pDraw->RestorePrimaryClipper(); // Draw count if (Count!=C4MN_Item_NoCount) { char szCount[10+1]; sprintf(szCount,"%ix",Count); pDraw->TextOut(szCount, ::GraphicsResource.FontRegular, 1.0, cgoItemText.Surface, cgoItemText.X+cgoItemText.Wdt-1, cgoItemText.Y+cgoItemText.Hgt-1-::GraphicsResource.FontRegular.GetLineHeight(), C4Draw::DEFAULT_MESSAGE_COLOR, ARight); } }
DWORD GenerateRandomPlayerColor(int32_t iTry) // generate a random player color for the iTry'th try { // generate a random one biased towards max channel luminance // (for greater color difference and less gray-ish colors) return C4RGB(std::min<int>(UnsyncedRandom(302), 256), std::min<int>(UnsyncedRandom(302), 256), std::min<int>(UnsyncedRandom(302), 256)); }
void C4Def::Draw(C4Facet &cgo, bool fSelected, DWORD iColor, C4Object *pObj, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform* trans, const char *graphicsName) { if(fSelected) pDraw->DrawBoxDw(cgo.Surface, cgo.X, cgo.Y, cgo.X + cgo.Wdt - 1, cgo.Y + cgo.Hgt - 1, C4RGB(0xca, 0, 0)); C4DefGraphics* graphics = pObj ? pObj->GetGraphics() : &Graphics; if (graphicsName) { C4DefGraphics *other = graphics->Get(graphicsName); if (other) graphics = other; } graphics->Draw(cgo, iColor, pObj, iPhaseX, iPhaseY, trans); }
void C4Chart::DrawElement(C4TargetFacet &cgo) { typedef C4Graph::ValueType ValueType; typedef C4Graph::TimeType TimeType; // transparent w/o graph if (!pDisplayGraph) return; int iSeriesCount = pDisplayGraph->GetSeriesCount(); if (!iSeriesCount) return; assert(iSeriesCount>0); StdStrBuf sbuf; pDisplayGraph->Update(); // update averages, etc. // calc metrics CStdFont &rFont = ::GraphicsResource.MiniFont; int YAxisWdt = 5, XAxisHgt = 15; const int AxisArrowLen = 6, AxisMarkerLen = 5, AxisArrowThickness = 3, AxisArrowIndent= 2; // margin between axis arrow and last value int32_t YAxisMinStepHgt, XAxisMinStepWdt; // get value range int iMinTime = pDisplayGraph->GetStartTime(); int iMaxTime = pDisplayGraph->GetEndTime() - 1; if (iMinTime >= iMaxTime) return; ValueType iMinVal = pDisplayGraph->GetMinValue(); ValueType iMaxVal = pDisplayGraph->GetMaxValue(); if (iMinVal == iMaxVal) ++iMaxVal; if (iMinVal > 0 && iMaxVal/iMinVal >= 2) iMinVal = 0; // go zero-based if this creates less than 50% unused space else if (iMaxVal < 0 && iMinVal/iMaxVal >= 2) iMaxVal = 0; int ddv; if (iMaxVal>0 && (ddv=GetValueDecade(int(iMaxVal))/50)) iMaxVal = ((iMaxVal-(iMaxVal>0))/ddv+(iMaxVal>0))*ddv; if (iMinVal && (ddv=GetValueDecade(int(iMinVal))/50)) iMinVal = ((iMinVal-(iMinVal<0))/ddv+(iMinVal<0))*ddv; ValueType dv=iMaxVal-iMinVal; TimeType dt=iMaxTime-iMinTime; // axis calculations sbuf.Format("-%d", (int) std::max(Abs(iMaxVal), Abs(iMinVal))); rFont.GetTextExtent(sbuf.getData(), XAxisMinStepWdt, YAxisMinStepHgt, false); YAxisWdt += XAxisMinStepWdt; XAxisHgt += YAxisMinStepHgt; XAxisMinStepWdt += 2; YAxisMinStepHgt += 2; int tw = rcBounds.Wdt - YAxisWdt; int th = rcBounds.Hgt - XAxisHgt; int tx = rcBounds.x + int(cgo.TargetX) + YAxisWdt; int ty = rcBounds.y + int(cgo.TargetY); // show a legend, if more than one graph is shown if (iSeriesCount > 1) { int iSeries = 0; const C4Graph *pSeries; int32_t iLegendWdt = 0, Q,W; while ((pSeries = pDisplayGraph->GetSeries(iSeries++))) { rFont.GetTextExtent(pSeries->GetTitle(), W, Q, true); iLegendWdt = std::max(iLegendWdt, W); } tw -= iLegendWdt+1; iSeries = 0; int iYLegendDraw = (th - iSeriesCount*Q)/2 + ty; while ((pSeries = pDisplayGraph->GetSeries(iSeries++))) { pDraw->TextOut(pSeries->GetTitle(), rFont, 1.0f, cgo.Surface, tx+tw, iYLegendDraw, pSeries->GetColorDw() | 0xff000000, ALeft, true); iYLegendDraw += Q; } } // safety: too small? if (tw < 10 || th < 10) return; // draw axis pDraw->DrawLineDw(cgo.Surface, tx, ty+th, tx+tw-1, ty+th, C4RGB(0x91, 0x91, 0x91)); pDraw->DrawLineDw(cgo.Surface, tx+tw-1, ty+th, tx+tw-1-AxisArrowLen, ty+th-AxisArrowThickness, C4RGB(0x91, 0x91, 0x91)); pDraw->DrawLineDw(cgo.Surface, tx+tw-1, ty+th, tx+tw-1-AxisArrowLen, ty+th+AxisArrowThickness, C4RGB(0x91, 0x91, 0x91)); pDraw->DrawLineDw(cgo.Surface, tx, ty, tx, ty+th, C4RGB(0x91, 0x91, 0x91)); pDraw->DrawLineDw(cgo.Surface, tx, ty, tx-AxisArrowThickness, ty+AxisArrowLen, C4RGB(0x91, 0x91, 0x91)); pDraw->DrawLineDw(cgo.Surface, tx, ty, tx+AxisArrowThickness, ty+AxisArrowLen, C4RGB(0x91, 0x91, 0x91)); tw -= AxisArrowLen + AxisArrowIndent; th -= AxisArrowLen + AxisArrowIndent; ty += AxisArrowLen + AxisArrowIndent; // do axis numbering int iXAxisSteps = GetAxisStepRange(dt, tw / XAxisMinStepWdt), iYAxisSteps = GetAxisStepRange(int(dv), th / YAxisMinStepHgt); int iX, iY, iTime, iVal; iY = 0; iTime = ((iMinTime-(iMinTime>0))/iXAxisSteps+(iMinTime>0))*iXAxisSteps; for (; iTime <= iMaxTime; iTime += iXAxisSteps) { iX = tx + tw * (iTime-iMinTime) / dt; pDraw->DrawLineDw(cgo.Surface, iX, ty+th+1, iX, ty+th+AxisMarkerLen, C4RGB(0x91, 0x91, 0x91)); sbuf.Format("%d", (int) iTime); pDraw->TextOut(sbuf.getData(), rFont, 1.0f, cgo.Surface, iX, ty+th+AxisMarkerLen, 0xff7f7f7f, ACenter, false); } iVal = int( ((iMinVal-(iMinVal>0))/iYAxisSteps+(iMinVal>0))*iYAxisSteps ); for (; iVal <= iMaxVal; iVal += iYAxisSteps) { iY = ty+th - int((iVal-iMinVal) / dv * th); pDraw->DrawLineDw(cgo.Surface, tx-AxisMarkerLen, iY, tx-1, iY, C4RGB(0x91, 0x91, 0x91)); sbuf.Format("%d", (int) iVal); pDraw->TextOut(sbuf.getData(), rFont, 1.0f, cgo.Surface, tx-AxisMarkerLen, iY-rFont.GetLineHeight()/2, 0xff7f7f7f, ARight, false); } // draw graph series(es) int iSeries = 0; while (const C4Graph *pSeries = pDisplayGraph->GetSeries(iSeries++)) { int iThisMinTime = std::max(iMinTime, pSeries->GetStartTime()); int iThisMaxTime = std::min(iMaxTime, pSeries->GetEndTime()); bool fAnyVal = false; for (iX = 0; iX<tw; ++iX) { iTime = iMinTime + dt*iX/tw; if (!Inside(iTime, iThisMinTime, iThisMaxTime)) continue; int iY2 = int((-pSeries->GetValue(iTime) + iMinVal) * th / dv) + ty+th; if (fAnyVal) pDraw->DrawLineDw(cgo.Surface, (float) (tx+iX-1), (float) iY, (float) (tx+iX), (float) iY2, pSeries->GetColorDw() | 0xff000000); iY = iY2; fAnyVal = true; } } }
void C4Network2ClientListBox::ClientListItem::Update() { // update wait label if (pPing) { int iWait = ::Control.Network.ClientPerfStat(iClientID); pPing->SetText(FormatString("%d ms", iWait).getData()); pPing->SetColor(C4RGB( Clamp(255-Abs(iWait)*5, 0, 255), Clamp(255-iWait*5, 0, 255), Clamp(255+iWait*5, 0, 255))); } // update activation status const C4Client *pClient = GetClient(); if (!pClient) return; bool fIsActive = pClient->isActivated(); if (fIsActive != fShownActive) { fShownActive = fIsActive; if (!pClient->isHost()) pStatusIcon->SetIcon(fIsActive ? C4GUI::Ico_Client : C4GUI::Ico_ObserverClient); if (pActivateBtn) { pActivateBtn->SetIcon(fIsActive ? C4GUI::Ico_Active : C4GUI::Ico_Inactive); pActivateBtn->SetToolTip(LoadResStrNoAmp(fIsActive ? "IDS_NET_DEACTIVATECLIENT" : "IDS_NET_ACTIVATECLIENT")); } } // update players in tooltip StdStrBuf sCltPlrs(Game.PlayerInfos.GetActivePlayerNames(false, iClientID)); pName->SetToolTip(sCltPlrs.getData()); // update icon: Network status C4GUI::Icons icoStatus = C4GUI::Ico_UnknownClient; C4Network2Client *pClt = pClient->getNetClient(); if (pClt) { switch (pClt->getStatus()) { case NCS_Joining: // waiting for join data case NCS_Chasing: // client is behind (status not acknowledged, isn't waited for) case NCS_NotReady: // client is behind (status not acknowledged) icoStatus = C4GUI::Ico_Loading; break; case NCS_Ready: // client acknowledged network status icoStatus = C4GUI::Ico_Ready; break; case NCS_Remove: // client is to be removed icoStatus = C4GUI::Ico_Kick; break; default: // whatever assert(false); icoStatus = C4GUI::Ico_Loading; break; } } // sound icon? if (last_sound_time) { time_t dt = time(nullptr) - last_sound_time; if (dt >= SoundIconShowTime) { // stop showing sound icon last_sound_time = 0; } else { // time not up yet: show sound icon icoStatus = C4GUI::Ico_Sound; } } // network OK - control ready? if (!pForDlg->IsStartup() && (icoStatus == C4GUI::Ico_Ready)) { if (!::Control.Network.ClientReady(iClientID, ::Control.ControlTick)) { // control not ready icoStatus = C4GUI::Ico_NetWait; } } // set new icon pStatusIcon->SetIcon(icoStatus); }