void CGTextArea::Paint (CG32bitImage &Dest, const RECT &rcRect) // Paint // // Handle paint { RECT rcText = CalcTextRect(rcRect); // Paint the background if (m_iBorderRadius > 0) CGDraw::RoundedRect(Dest, rcRect.left, rcRect.top, RectWidth(rcRect), RectHeight(rcRect), m_iBorderRadius, m_rgbBackColor); else Dest.Fill(rcRect.left, rcRect.top, RectWidth(rcRect), RectHeight(rcRect), m_rgbBackColor); // Paint the editable box if (m_bEditable) { CG32bitPixel rgbBorderColor = CG32bitPixel::Blend(CG32bitPixel(0, 0, 0), m_rgbColor, (BYTE)128); CGDraw::RectOutlineDotted(Dest, rcRect.left, rcRect.top, RectWidth(rcRect), RectHeight(rcRect), rgbBorderColor); } // Paint the content if (!m_sText.IsBlank()) PaintText(Dest, rcText); else PaintRTF(Dest, rcText); }
void CGImageArea::Paint (CG32bitImage &Dest, const RECT &rcRect) // Paint // // Handle paint { if (!m_bTransBackground) Dest.Fill(rcRect.left, rcRect.top, RectWidth(rcRect), RectHeight(rcRect), m_rgbBackColor); if (m_pImage) { int x, y; // Compute position of image in the area rect if (m_dwStyles & alignCenter) x = rcRect.left + (RectWidth(rcRect) - RectWidth(m_rcImage)) / 2; else if (m_dwStyles & alignRight) x = rcRect.left + (RectWidth(rcRect) - RectWidth(m_rcImage)); else x = rcRect.left; if (m_dwStyles & alignMiddle) y = rcRect.top + (RectHeight(rcRect) - RectHeight(m_rcImage)) / 2; else if (m_dwStyles & alignBottom) y = rcRect.top + (RectHeight(rcRect) - RectHeight(m_rcImage)); else y = rcRect.top; // Blt // // For compatibility with previous (Transcendence) releases, we assume // black is transparent if the image has no alpha channel. CGDraw::BltWithBackColor(Dest, x, y, *m_pImage, m_rcImage.left, m_rcImage.top, RectWidth(m_rcImage), RectHeight(m_rcImage), CG32bitPixel(0, 0, 0)); } }
void CTransmuterSession::OnPaint(CG32bitImage &Screen, const RECT &rcInvalid) { // paint the background Screen.Fill(0, 0, Screen.GetWidth(), Screen.GetHeight(), CG32bitPixel(32, 32, 32)); // make sure m_SubSessions is up-to-date with any error sessions UpdateSubSessionsList(); // call paint functions of all subsessions for (int i = 0; i < m_SubSessions.GetCount(); i++) { m_SubSessions[i]->OnPaint(Screen, rcInvalid); } }
CG32bitImage *CSystemMap::CreateBackgroundImage (void) // CreateBackgroundImage // // Creates an image containing the map. // Caller is responsible for freeing the returned image. { int i; CG32bitImage *pImage = g_pUniverse->GetLibraryBitmapCopy(m_dwBackgroundImage); if (pImage == NULL) return NULL; int xCenter = pImage->GetWidth() / 2; int yCenter = pImage->GetHeight() / 2; // Paint all annotations if (m_Annotations.GetCount() > 0) { SViewportPaintCtx Ctx; for (i = 0; i < m_Annotations.GetCount(); i++) { SMapAnnotation *pAnnotation = &m_Annotations[i]; Ctx.iTick = pAnnotation->iTick; Ctx.iRotation = pAnnotation->iRotation; pAnnotation->pPainter->Paint(*pImage, xCenter + pAnnotation->xOffset, yCenter - pAnnotation->yOffset, Ctx); } } #ifdef DEBUG #if 0 // Test noise function CG32bitImage Alpha; Alpha.CreateBlankAlpha(pImage->GetWidth(), pImage->GetHeight()); DrawNebulosity8bit(Alpha, 0, 0, pImage->GetWidth(), pImage->GetHeight(), 256, 0, 255); pImage->Fill(0, 0, pImage->GetWidth(), pImage->GetHeight(), 0); pImage->FillMask(0, 0, pImage->GetWidth(), pImage->GetHeight(), Alpha, CG32bitPixel(255, 255, 255), 0, 0); #endif #endif return pImage; }
void CGSelectorArea::PaintModifier (CG32bitImage &Dest, int x, int y, const CString &sText, CG32bitPixel rgbColor, CG32bitPixel rgbBackColor, int *rety) // PaintModifier // // Paints a modifier block. { int cx = m_VI.GetFont(fontSmall).MeasureText(sText); if (!rgbBackColor.IsNull()) Dest.Fill(x - cx - 8, y, cx + 8, m_VI.GetFont(fontSmall).GetHeight(), rgbBackColor); m_VI.GetFont(fontSmall).DrawText(Dest, x - cx - 4, y, rgbColor, sText); if (rety) *rety = y + m_VI.GetFont(fontSmall).GetHeight() + 1; }
void GenerateImageChart (CUniverse &Universe, CXMLElement *pCmdLine) { int i; enum OrderTypes { orderSmallest = 1, orderLargest = 2, orderName = 3, orderLevel = 4, orderSovereign = 5, orderManufacturer = 6, }; // Item criteria bool bHasItemCriteria; CString sCriteria; CItemCriteria ItemCriteria; if (bHasItemCriteria = pCmdLine->FindAttribute(CONSTLIT("itemCriteria"), &sCriteria)) CItem::ParseCriteria(sCriteria, &ItemCriteria); else CItem::InitCriteriaAll(&ItemCriteria); // Get the criteria from the command line. CDesignTypeCriteria Criteria; if (pCmdLine->FindAttribute(CONSTLIT("criteria"), &sCriteria)) { if (CDesignTypeCriteria::ParseCriteria(sCriteria, &Criteria) != NOERROR) { printf("ERROR: Unable to parse criteria.\n"); return; } } else if (bHasItemCriteria) { if (CDesignTypeCriteria::ParseCriteria(CONSTLIT("i"), &Criteria) != NOERROR) { printf("ERROR: Unable to parse criteria.\n"); return; } } else { printf("ERROR: Expected criteria.\n"); return; } bool bAll = pCmdLine->GetAttributeBool(CONSTLIT("all")); // Options bool bTextBoxesOnly = pCmdLine->GetAttributeBool(CONSTLIT("textBoxesOnly")); bool bFieldUNID = pCmdLine->GetAttributeBool(CONSTLIT("unid")); // Figure out what order we want CString sOrder = pCmdLine->GetAttribute(CONSTLIT("sort")); int iOrder; if (strEquals(sOrder, CONSTLIT("smallest"))) iOrder = orderSmallest; else if (strEquals(sOrder, CONSTLIT("largest"))) iOrder = orderLargest; else if (strEquals(sOrder, CONSTLIT("level"))) iOrder = orderLevel; else if (strEquals(sOrder, CONSTLIT("sovereign"))) iOrder = orderSovereign; else if (strEquals(sOrder, CONSTLIT("manufacturer"))) iOrder = orderManufacturer; else iOrder = orderName; bool b3DGrid = pCmdLine->GetAttributeBool(CONSTLIT("3DGrid")); bool bDockingPorts = pCmdLine->GetAttributeBool(CONSTLIT("portPos")); bool bDevicePos = pCmdLine->GetAttributeBool(CONSTLIT("devicePos")); // Image size int cxDesiredWidth; if (pCmdLine->FindAttributeInteger(CONSTLIT("width"), &cxDesiredWidth)) cxDesiredWidth = Max(512, cxDesiredWidth); else cxDesiredWidth = 1280; // Spacing int cxSpacing = pCmdLine->GetAttributeInteger(CONSTLIT("xSpacing")); int cxExtraMargin = pCmdLine->GetAttributeInteger(CONSTLIT("xMargin")); int cxImageMargin = 2 * pCmdLine->GetAttributeInteger(CONSTLIT("xImageMargin")); // Font for text CString sTypeface; int iSize; bool bBold; bool bItalic; if (!CG16bitFont::ParseFontDesc(pCmdLine->GetAttribute(CONSTLIT("font")), &sTypeface, &iSize, &bBold, &bItalic)) { sTypeface = CONSTLIT("Arial"); iSize = 10; bBold = false; bItalic = false; } CG16bitFont NameFont; NameFont.Create(sTypeface, -PointsToPixels(iSize), bBold, bItalic); CG32bitPixel rgbNameColor = CG32bitPixel(255, 255, 255); // Rotation int iRotation = pCmdLine->GetAttributeInteger(CONSTLIT("rotation")); // Output file CString sFilespec = pCmdLine->GetAttribute(CONSTLIT("output")); if (!sFilespec.IsBlank()) sFilespec = pathAddExtensionIfNecessary(sFilespec, CONSTLIT(".bmp")); // Generate a sorted table of types TSortMap<CString, SEntryDesc> Table; for (i = 0; i < Universe.GetDesignTypeCount(); i++) { CDesignType *pType = Universe.GetDesignType(i); SEntryDesc NewEntry; // Make sure we match the criteria if (!pType->MatchesCriteria(Criteria)) continue; // Figure stuff stuff out based on the specific design type switch (pType->GetType()) { case designItemType: { CItemType *pItemType = CItemType::AsType(pType); CItem Item(pItemType, 1); // Skip if not in item criteria if (!Item.MatchesCriteria(ItemCriteria)) continue; // Skip virtual classes if (pItemType->IsVirtual()) continue; // Initialize the entry NewEntry.pType = pType; NewEntry.sName = pItemType->GetNounPhrase(0); NewEntry.pImage = &pItemType->GetImage(); NewEntry.iSize = RectWidth(NewEntry.pImage->GetImageRect()); break; } case designShipClass: { CShipClass *pClass = CShipClass::AsType(pType); // Skip non-generic classess if (!bAll && !pClass->HasLiteralAttribute(CONSTLIT("genericClass"))) continue; // Initialize the entry NewEntry.pType = pType; NewEntry.sName = pClass->GetNounPhrase(0); NewEntry.iSize = RectWidth(pClass->GetImage().GetImageRect()); NewEntry.pImage = &pClass->GetImage(); NewEntry.iRotation = pClass->Angle2Direction(iRotation); NewEntry.sSovereignName = (pClass->GetDefaultSovereign() ? pClass->GetDefaultSovereign()->GetTypeNounPhrase() : NULL_STR); break; } case designStationType: { CStationType *pStationType = CStationType::AsType(pType); // Skip generic classes if (!bAll && !pStationType->HasLiteralAttribute(CONSTLIT("generic"))) continue; NewEntry.pType = pType; NewEntry.sName = pStationType->GetNounPhrase(0); NewEntry.iSize = pStationType->GetSize(); NewEntry.sSovereignName = (pStationType->GetSovereign() ? pStationType->GetSovereign()->GetTypeNounPhrase() : NULL_STR); InitStationTypeImage(NewEntry, pStationType); break; } default: // Don't know how to handle this type continue; break; } // Adjust name if (bFieldUNID) NewEntry.sName = strPatternSubst(CONSTLIT("%s (%x)"), NewEntry.sName, NewEntry.pType->GetUNID()); // Compute the sort key char szBuffer[1024]; switch (iOrder) { case orderLargest: wsprintf(szBuffer, "%09d%s%x", 1000000 - NewEntry.iSize, NewEntry.sName.GetASCIIZPointer(), pType->GetUNID()); break; case orderLevel: wsprintf(szBuffer, "%09d%s%x", pType->GetLevel(), NewEntry.sName.GetASCIIZPointer(), pType->GetUNID()); break; case orderSmallest: wsprintf(szBuffer, "%09d%s%x", NewEntry.iSize, NewEntry.sName.GetASCIIZPointer(), pType->GetUNID()); break; case orderSovereign: wsprintf(szBuffer, "%s|%s|%x", NewEntry.sSovereignName.GetASCIIZPointer(), NewEntry.sName.GetASCIIZPointer(), pType->GetUNID()); NewEntry.sCategorize = NewEntry.sSovereignName; break; case orderManufacturer: { CString sManufacturer = NewEntry.pType->GetPropertyString(CONSTLIT("manufacturer")); wsprintf(szBuffer, "%s|%s|%x", sManufacturer.GetASCIIZPointer(), NewEntry.sName.GetASCIIZPointer(), pType->GetUNID()); NewEntry.sCategorize = sManufacturer; break; } default: wsprintf(szBuffer, "%s%x", NewEntry.sName.GetASCIIZPointer(), pType->GetUNID()); break; } // Add to list Table.Insert(CString(szBuffer), NewEntry); } // Allocate an arranger that tracks where to paint each world. CImageArranger Arranger; // Settings for the overall arrangement CImageArranger::SArrangeDesc Desc; Desc.cxDesiredWidth = Max(512, cxDesiredWidth - (2 * (cxSpacing + cxExtraMargin))); Desc.cxSpacing = cxSpacing; Desc.cxExtraMargin = cxExtraMargin; Desc.pHeader = &NameFont; // Generate a table of cells for the arranger TArray<CCompositeImageSelector> Selectors; Selectors.InsertEmpty(Table.GetCount()); CString sLastCategory; TArray<CImageArranger::SCellDesc> Cells; for (i = 0; i < Table.GetCount(); i++) { SEntryDesc &Entry = Table[i]; CImageArranger::SCellDesc *pNewCell = Cells.Insert(); pNewCell->cxWidth = (Entry.pImage ? RectWidth(Entry.pImage->GetImageRect()) : 0) + cxImageMargin; pNewCell->cyHeight = (Entry.pImage ? RectHeight(Entry.pImage->GetImageRect()) : 0) + cxImageMargin; pNewCell->sText = Entry.sName; if (!strEquals(sLastCategory, Entry.sCategorize)) { sLastCategory = Entry.sCategorize; pNewCell->bStartNewRow = true; } } // Arrange Arranger.ArrangeByRow(Desc, Cells); // Create a large image CG32bitImage Output; int cxWidth = Max(cxDesiredWidth, Arranger.GetWidth()); int cyHeight = Arranger.GetHeight(); Output.Create(cxWidth, cyHeight); printf("Creating %dx%d image.\n", cxWidth, cyHeight); // Paint the images for (i = 0; i < Table.GetCount(); i++) { SEntryDesc &Entry = Table[i]; int x = Arranger.GetX(i); int y = Arranger.GetY(i); // Paint if (x != -1) { int xCenter = x + (Arranger.GetWidth(i) / 2); int yCenter = y + (Arranger.GetHeight(i) / 2); int xOffset; int yOffset; Entry.pImage->GetImageOffset(0, Entry.iRotation, &xOffset, &yOffset); int cxImage = RectWidth(Entry.pImage->GetImageRect()); int cyImage = RectHeight(Entry.pImage->GetImageRect()); // Paint image if (!bTextBoxesOnly && Entry.pImage) { Entry.pImage->PaintImageUL(Output, x + (Arranger.GetWidth(i) - cxImage) / 2, y + (Arranger.GetHeight(i) - cyImage) / 2, 0, Entry.iRotation); } // Paint type specific stuff switch (Entry.pType->GetType()) { case designStationType: { CStationType *pStationType = CStationType::AsType(Entry.pType); int xStationCenter = xCenter - xOffset; int yStationCenter = yCenter - yOffset; if (bDockingPorts) pStationType->PaintDockPortPositions(Output, xStationCenter, yStationCenter); if (bDevicePos) pStationType->PaintDevicePositions(Output, xStationCenter, yStationCenter); // If we have docking or device positions, mark the center of the station if (bDockingPorts || bDevicePos) { const int LINE_HALF_LENGTH = 24; const CG32bitPixel RGB_CENTER_CROSS(255, 255, 0); Output.DrawLine(xStationCenter - LINE_HALF_LENGTH, yStationCenter, xStationCenter + LINE_HALF_LENGTH, yStationCenter, 1, RGB_CENTER_CROSS); Output.DrawLine(xStationCenter, yStationCenter - LINE_HALF_LENGTH, xStationCenter, yStationCenter + LINE_HALF_LENGTH, 1, RGB_CENTER_CROSS); } break; } } // Paint the 3D grid, if necessary if (b3DGrid) { int iScale = Entry.pImage->GetImageViewportSize(); Metric rMaxRadius = g_KlicksPerPixel * cxImage * 0.5; const Metric rGridSize = LIGHT_SECOND; Metric rRadius; for (rRadius = rGridSize; rRadius <= rMaxRadius; rRadius += rGridSize) { int iRadius = (int)((rRadius / g_KlicksPerPixel) + 0.5); const int iGridAngle = 8; int iPrevAngle = 0; int iAngle; for (iAngle = iGridAngle; iAngle <= 360; iAngle += iGridAngle) { int xFrom, yFrom; C3DConversion::CalcCoord(iScale, iPrevAngle, iRadius, 0, &xFrom, &yFrom); int xTo, yTo; C3DConversion::CalcCoord(iScale, iAngle, iRadius, 0, &xTo, &yTo); Output.DrawLine(xFrom + xCenter, yFrom + yCenter, xTo + xCenter, yTo + yCenter, 1, CG32bitPixel(255, 255, 0)); iPrevAngle = iAngle; } } } // Paint name int xText = Arranger.GetTextX(i); int yText = Arranger.GetTextY(i); if (xText != -1) { if (bTextBoxesOnly) Output.Fill(xText, yText, Arranger.GetTextWidth(i), Arranger.GetTextHeight(i), 0xffff); if (!bTextBoxesOnly) { Output.FillColumn(xCenter, y + Arranger.GetHeight(i), yText - (y + Arranger.GetHeight(i)), rgbNameColor); NameFont.DrawText(Output, xText, yText, rgbNameColor, Entry.sName); } } } } // Write to file or clipboard OutputImage(Output, sFilespec); }
void CGItemListArea::Paint (CG32bitImage &Dest, const RECT &rcRect) // Paint // // Paint the area { // Can't paint if we are not properly initialized if (m_pFonts == NULL) return; bool bPaintCursor = false; RECT rcCursor; // Paint Background CG32bitPixel rgbFadeBackColor = CG32bitPixel(CG32bitPixel::Darken(m_rgbBackColor, 220), 220); CGDraw::RoundedRect(Dest, rcRect.left, rcRect.top, RectWidth(rcRect), RectHeight(rcRect), BORDER_RADIUS + 1, rgbFadeBackColor); // If there are no items here, then say so if (m_pListData == NULL || !m_pListData->IsCursorValid()) { int x = rcRect.left + (RectWidth(rcRect) - m_pFonts->LargeBold.MeasureText(STR_NO_ITEMS)) / 2; int y = rcRect.top + (RectHeight(rcRect) - m_pFonts->LargeBold.GetHeight()) / 2; Dest.DrawText(x, y, m_pFonts->LargeBold, RGB_DISABLED_TEXT, STR_NO_ITEMS); m_iOldCursor = -1; } // Otherwise, paint the list of items else { int iCursor = m_pListData->GetCursor(); int iCount = m_pListData->GetCount(); ASSERT(iCursor >= 0 && iCursor < m_Rows.GetCount()); // If the cursor has changed, update the offset so that we // have a smooth scroll. if (m_iOldCursor != -1 && m_iOldCursor != iCursor && m_iOldCursor < m_Rows.GetCount()) { int cyDiff = (m_Rows[iCursor].cyHeight - m_Rows[m_iOldCursor].cyHeight) / 2; if (m_iOldCursor < iCursor) m_yOffset = m_Rows[m_iOldCursor].cyHeight + cyDiff; else m_yOffset = -(m_Rows[iCursor].cyHeight - cyDiff); } m_iOldCursor = iCursor; // Figure out the ideal position of the cursor (relative to the // rect). int yIdeal = m_yOffset + ((RectHeight(rcRect) - m_Rows[iCursor].cyHeight) / 2); // Figure out the actual position of the cursor row (relative to the // rect). int yCursor; // If the cursor is in the top part of the list if (m_Rows[iCursor].yPos < yIdeal) yCursor = m_Rows[iCursor].yPos; // If the total number of lines is less than the whole rect else if (m_cyTotalHeight < RectHeight(rcRect)) yCursor = m_Rows[iCursor].yPos; // If the cursor is in the bottom part of the list else if ((m_cyTotalHeight - m_Rows[iCursor].yPos) < (RectHeight(rcRect) - yIdeal)) yCursor = (RectHeight(rcRect) - (m_cyTotalHeight - m_Rows[iCursor].yPos)); // The cursor is in the middle of the list else yCursor = yIdeal; // Figure out the item position at which we start painting int iStart = FindRow(m_Rows[iCursor].yPos - yCursor); ASSERT(iStart != -1); if (iStart == -1) iStart = 0; int yStart = yCursor - (m_Rows[iCursor].yPos - m_Rows[iStart].yPos); // Compute y offset of first row (so that we can handle clicks later) m_yFirst = yStart - m_Rows[iStart].yPos; // Paint int y = rcRect.top + yStart; int iPos = iStart; bool bPaintSeparator = false; RECT rcItem; while (y < rcRect.bottom && iPos < m_Rows.GetCount()) { // Paint previous separator if (bPaintSeparator) { Dest.Fill(rcItem.left + BORDER_RADIUS, rcItem.bottom - 1, RectWidth(rcItem) - (BORDER_RADIUS * 2), 1, CG32bitPixel(50,50,50)); } else bPaintSeparator = true; // Paint only if we have a valid entry. Sometimes we can // start at an invalid entry because we're scrolling. if (iPos >= 0) { m_pListData->SetCursor(iPos); rcItem.top = y; rcItem.left = rcRect.left; rcItem.bottom = y + m_Rows[iPos].cyHeight; rcItem.right = rcRect.right; // See if we need to paint the cursor bool bIsCursor = (iPos == iCursor); // Paint selection background (if selected) if (bIsCursor) { bPaintCursor = true; bPaintSeparator = false; rcCursor = rcItem; CGDraw::RoundedRect(Dest, rcCursor.left, rcCursor.top, RectWidth(rcCursor), RectHeight(rcCursor), BORDER_RADIUS, m_rgbBackColor); } // Paint item switch (m_iType) { case listCustom: PaintCustom(Dest, rcItem, bIsCursor); break; case listItem: PaintItem(Dest, m_pListData->GetItemAtCursor(), rcItem, bIsCursor); break; } } // Next y += m_Rows[iPos].cyHeight; iPos++; } // Done m_pListData->SetCursor(iCursor); } // Paint a frame CGDraw::RoundedRectOutline(Dest, rcRect.left, rcRect.top, RectWidth(rcRect), RectHeight(rcRect), BORDER_RADIUS, 1, CG32bitPixel(80,80,80)); if (bPaintCursor) { CGDraw::RoundedRectOutline(Dest, rcCursor.left + 1, rcCursor.top + 1, RectWidth(rcCursor) - 2, RectHeight(rcCursor) - 2, BORDER_RADIUS, SELECTION_WIDTH, m_VI.GetColor(colorAreaDialogHighlight)); } }
void CGTextArea::PaintText (CG32bitImage &Dest, const RECT &rcRect) // PaintText // // Paint plain text { // Paint the text if (m_pFont) { // If we haven't justified the text for this size, do it now if (m_cxJustifyWidth != RectWidth(rcRect)) { m_cxJustifyWidth = RectWidth(rcRect); m_Lines.DeleteAll(); m_pFont->BreakText(m_sText, m_cxJustifyWidth, &m_Lines, CG16bitFont::SmartQuotes); } // Compute the rect within which we draw the text RECT rcText = rcRect; if (m_bEditable) { int iVSpacing = (RectHeight(rcRect) - m_pFont->GetHeight()) / 2; rcText.left += iVSpacing; rcText.right -= iVSpacing; rcText.top += iVSpacing; rcText.bottom -= iVSpacing; } // Clip to text rect RECT rcOldClip = Dest.GetClipRect(); Dest.SetClipRect(rcText); // Figure out how many lines fit in the rect int iMaxLineCount = RectHeight(rcText) / m_pFont->GetHeight(); // If there are too many lines, and we're editable, start at the end int iStart = 0; if (m_bEditable && iMaxLineCount < m_Lines.GetCount()) iStart = m_Lines.GetCount() - iMaxLineCount; // Paint each line int x = rcText.left; int y = rcText.top; for (int i = iStart; i < m_Lines.GetCount(); i++) { CString sLine = m_Lines[i]; // Trim the last space in the line, if necessary char *pPos = sLine.GetASCIIZPointer(); if (sLine.GetLength() > 0 && pPos[sLine.GetLength() - 1] == ' ') sLine = strTrimWhitespace(sLine); // Alignment int xLine; if (m_dwStyles & alignCenter) { int cxWidth = m_pFont->MeasureText(sLine); xLine = x + (RectWidth(rcText) - cxWidth) / 2; } else if (m_dwStyles & alignRight) { int cxWidth = m_pFont->MeasureText(sLine); xLine = x + (RectWidth(rcRect) - cxWidth); } else xLine = x; // Paint if (HasEffects()) m_pFont->DrawTextEffect(Dest, xLine, y, m_rgbColor, sLine, GetEffectCount(), GetEffects()); else Dest.DrawText(xLine, y, *m_pFont, m_rgbColor, sLine); // Next y += m_pFont->GetHeight() + m_cyLineSpacing; if (y >= rcText.bottom) break; } // Paint the cursor if (m_bEditable && m_iCursorLine >= iStart) { int cxPos = (m_iCursorLine < m_Lines.GetCount() ? m_pFont->MeasureText(CString(m_Lines[m_iCursorLine].GetASCIIZPointer(), m_iCursorPos, true)) : 0); int y = rcText.top + (m_iCursorLine - iStart) * (m_pFont->GetHeight() + m_cyLineSpacing); int x = rcText.left; if (m_dwStyles & alignCenter) { int cxWidth = (m_iCursorLine < m_Lines.GetCount() ? m_pFont->MeasureText(m_Lines[m_iCursorLine]) : 0); x += ((RectWidth(rcText) - cxWidth) / 2) + cxPos; } else if (m_dwStyles & alignRight) { int cxWidth = (m_iCursorLine < m_Lines.GetCount() ? m_pFont->MeasureText(m_Lines[m_iCursorLine]) : 0); x += (RectWidth(rcText) - cxWidth) + cxPos; } else x += cxPos; if (((m_iTick / 30) % 2) > 0) { Dest.Fill(x, y, 2, m_pFont->GetHeight(), RGB_CURSOR); } } // Restore clip Dest.SetClipRect(rcOldClip); } }
void TestPolygons (CUniverse &Universe, CXMLElement *pCmdLine) { int i; const int FRAME_WIDTH = 256; const int FRAME_HEIGHT = 256; const int OUTPUT_WIDTH = FRAME_WIDTH * 2; const int OUTPUT_HEIGHT = FRAME_HEIGHT; // Options int iCount = pCmdLine->GetAttributeInteger(CONSTLIT("count")); if (iCount == 0) iCount = 1000; int iBltCount = Max(1, iCount / 10); // Create the output image CG32bitImage Output; Output.Create(OUTPUT_WIDTH, OUTPUT_HEIGHT, CG32bitImage::alpha8); // Create a regular polygon const int iSides = 17; const Metric rRadius = 100.0; const Metric rAngleStep = (TAU / iSides); TArray<CVector> Shape1; Shape1.InsertEmpty(iSides); for (i = 0; i < iSides; i++) Shape1[i] = CVector::FromPolar(i * rAngleStep, rRadius); // Create a point array, which we'll use for the binary region SPoint Shape1Points[iSides]; for (i = 0; i < iSides; i++) { Shape1Points[i].x = (int)Shape1[i].GetX(); Shape1Points[i].y = (int)Shape1[i].GetY(); } // Create a path CGPath Shape1Path; Shape1Path.Init(Shape1); // We do timing tests first TNumberSeries<Metric> Timing; // Time rasterization of a binary region const int CALLS_PER_SAMPLE = 1000; const int BLTS_PER_SAMPLE = 100; DWORD dwStart = ::GetTickCount(); for (i = 0; i < iCount; i++) { CG16bitBinaryRegion Region; Region.CreateFromPolygon(iSides, Shape1Points); if (((i + 1) % CALLS_PER_SAMPLE) == 0) Timing.Insert((Metric)::sysGetTicksElapsed(dwStart, &dwStart)); } printf("CG16bitBinaryRegion::CreateFromPolygon: %s ms per %d\n", (LPSTR)strFromDouble(Timing.GetMean()), CALLS_PER_SAMPLE); // Time rasterization of path Timing.DeleteAll(); dwStart = ::GetTickCount(); for (i = 0; i < iCount; i++) { CGRegion Region; Shape1Path.Rasterize(&Region, 1); if (((i + 1) % CALLS_PER_SAMPLE) == 0) Timing.Insert((Metric)::sysGetTicksElapsed(dwStart, &dwStart)); } printf("CGPath::Rasterize: %s ms per %d\n", (LPSTR)strFromDouble(Timing.GetMean()), CALLS_PER_SAMPLE); // Create the regions CG16bitBinaryRegion Shape1BinaryRegion; Shape1BinaryRegion.CreateFromPolygon(iSides, Shape1Points); CGRegion Shape1Region; Shape1Path.Rasterize(&Shape1Region, 4); // Time to blt Timing.DeleteAll(); dwStart = ::GetTickCount(); for (i = 0; i < iBltCount; i++) { CGDraw::Region(Output, (FRAME_WIDTH / 2), (FRAME_HEIGHT / 2), Shape1BinaryRegion, CG32bitPixel(255, 255, 255)); if (((i + 1) % BLTS_PER_SAMPLE) == 0) Timing.Insert((Metric)::sysGetTicksElapsed(dwStart, &dwStart)); } printf("CGDraw::Region (CG16bitBinaryRegion): %s ms per %d\n", (LPSTR)strFromDouble(Timing.GetMean()), BLTS_PER_SAMPLE); Timing.DeleteAll(); dwStart = ::GetTickCount(); for (i = 0; i < iBltCount; i++) { CGDraw::Region(Output, (FRAME_WIDTH / 2), (FRAME_HEIGHT / 2), Shape1Region, CG32bitPixel(255, 255, 255)); if (((i + 1) % BLTS_PER_SAMPLE) == 0) Timing.Insert((Metric)::sysGetTicksElapsed(dwStart, &dwStart)); } printf("CGDraw::Region (CGRegion): %s ms per %d\n", (LPSTR)strFromDouble(Timing.GetMean()), BLTS_PER_SAMPLE); // Clear Output.Fill(CG32bitPixel(0, 0, 0)); // Blt result int x = 0; int y = 0; CGDraw::Region(Output, x + (FRAME_WIDTH / 2), y + (FRAME_HEIGHT / 2), Shape1BinaryRegion, CG32bitPixel(255, 255, 255)); x = FRAME_WIDTH; CGDraw::Region(Output, x + (FRAME_WIDTH / 2), y + (FRAME_HEIGHT / 2), Shape1Region, CG32bitPixel(255, 255, 255)); // Copy to clipboard OutputImage(Output, NULL_STR); }
void CGButtonArea::Paint (CG32bitImage &Dest, const RECT &rcRect) // Paint // // Handle paint { int i; // Paint the background CG32bitPixel rgbBackColor = ((m_bMouseOver && !m_bDisabled) ? m_rgbBackColorHover : (m_bDisabled ? CG32bitPixel(m_rgbBackColor, 0xC0) : m_rgbBackColor)); if (!rgbBackColor.IsNull()) { if (m_iBorderRadius > 0) { CGDraw::RoundedRect(Dest, rcRect.left, rcRect.top, RectWidth(rcRect), RectHeight(rcRect), m_iBorderRadius, rgbBackColor); CGDraw::RoundedRectOutline(Dest, rcRect.left, rcRect.top, RectWidth(rcRect), RectHeight(rcRect), m_iBorderRadius, 1, m_rgbBorderColor); } else Dest.Fill(rcRect.left, rcRect.top, RectWidth(rcRect), RectHeight(rcRect), rgbBackColor); } // Paint the label int xPaint = rcRect.left + m_rcPadding.left; int yPaint = rcRect.top + m_rcPadding.top; if (m_pLabelFont) { // If we're disabled, paint gray if (m_bDisabled) Dest.DrawText(xPaint, yPaint, *m_pLabelFont, RGB_DISABLED_TEXT, m_sLabel); // If we have a prefix accelerator, draw that else if (!m_sAccelerator.IsBlank()) { // Measure the size of the accelerator int cyAccel; int cxAccel = m_pLabelFont->MeasureText(m_sAccelerator, &cyAccel); // We draw a rounded-rect box int cxBox = cxAccel + (2 * ACCEL_INNER_PADDING); int cyBox = cyAccel + 1; CGDraw::RoundedRect(Dest, xPaint, yPaint, cxBox, cyBox, ACCEL_BORDER_RADIUS, m_rgbAccelColor); // Draw the text Dest.DrawText(xPaint + ACCEL_INNER_PADDING, yPaint, *m_pLabelFont, CG32bitPixel(0, 0, 0), m_sAccelerator); // Now draw the rest of the label Dest.DrawText(xPaint + cxBox + (2 * ACCEL_INNER_PADDING), yPaint, *m_pLabelFont, m_rgbLabelColor, m_sLabel); } // If we have an accelerator, paint in pieces else if (m_iAccelerator != -1) { char *pPos = m_sLabel.GetASCIIZPointer(); int x = xPaint; if (m_iAccelerator > 0) Dest.DrawText(x, yPaint, *m_pLabelFont, m_rgbLabelColor, CString(pPos, m_iAccelerator, true), 0, &x); Dest.DrawText(x, yPaint, *m_pLabelFont, m_rgbAccelColor, CString(pPos + m_iAccelerator, 1, true), 0, &x); Dest.DrawText(x, yPaint, *m_pLabelFont, m_rgbLabelColor, CString(pPos + m_iAccelerator + 1, m_sLabel.GetLength() - m_iAccelerator - 1, true)); } else Dest.DrawText(xPaint, yPaint, *m_pLabelFont, m_rgbLabelColor, m_sLabel); yPaint += m_pLabelFont->GetHeight(); } // Paint the description if (m_pDescFont) { for (i = 0; i < m_Lines.GetCount(); i++) { Dest.DrawText(xPaint, yPaint, *m_pDescFont, m_rgbDescColor, m_Lines[i]); yPaint += m_pDescFont->GetHeight(); } } }
void CG8bitSparseImage::MaskFill (CG32bitImage &Dest, int xDest, int yDest, int cxDest, int cyDest, int xSrc, int ySrc, CG32bitPixel rgbColor) const // MaskFill // // Fills the destination image with the given color through our mask. { // Make sure we're in bounds if (!Dest.AdjustCoords(&xSrc, &ySrc, GetWidth(), GetHeight(), &xDest, &yDest, &cxDest, &cyDest)) return; // Short-circuit if (rgbColor.GetAlpha() == 0x00) return; // Compute a pre-multiplied color BYTE *pAlpha = CG32bitPixel::AlphaTable(rgbColor.GetAlpha()); CG32bitPixel rgbPreMultColor = CG32bitPixel(pAlpha[rgbColor.GetRed()], pAlpha[rgbColor.GetGreen()], pAlpha[rgbColor.GetBlue()], rgbColor.GetAlpha()); // Loop int yPos = ySrc; int yPosEnd = ySrc + cyDest; int yTile = yPos / m_cyTile; int yOffset = ClockMod(yPos, m_cyTile); int xTileStart = xSrc / m_cxTile; int xOffsetStart = ClockMod(xSrc, m_cxTile); int yDestPos = yDest; while (yPos < yPosEnd) { int cyTileLeft = Min(m_cyTile - yOffset, yPosEnd - yPos); // Is this a valid tile row, then continue if (yTile >= 0 && yTile < m_yTileCount) { int xPos = xSrc; int xPosEnd = xSrc + cxDest; int xTile = xTileStart; int xOffset = xOffsetStart; int xDestPos = xDest; while (xPos < xPosEnd) { int cxTileLeft = Min(m_cxTile - xOffset, xPosEnd - xPos); // If this is a valid tile, then we can continue if (xTile >= 0 && xTile < m_xTileCount) { const CNode &Tile = GetTile(xTile, yTile); switch (Tile.GetType()) { case typeByte: { BYTE byAlpha = Tile.GetByte(); if (byAlpha == 0x00) {} else if (byAlpha == 0xff) Dest.Fill(xDestPos, yDestPos, cxTileLeft, cyTileLeft, rgbColor); else // We just modify the alpha on the original color (Fill will take care of the rest) Dest.Fill(xDestPos, yDestPos, cxTileLeft, cyTileLeft, CG32bitPixel(rgbColor, CG32bitPixel::BlendAlpha(rgbColor.GetAlpha(), byAlpha))); break; } case typeNodeArray: { CNode *Rows = Tile.GetNodeArray(); CNode *pSrcRow = Rows + yOffset; CNode *pSrcRowEnd = pSrcRow + cyTileLeft; CG32bitPixel *pDestRow = Dest.GetPixelPos(xDestPos, yDestPos); while (pSrcRow < pSrcRowEnd) { CG32bitPixel *pDest = pDestRow; CG32bitPixel *pDestEnd = pDestRow + cxTileLeft; switch (pSrcRow->GetType()) { case typeByte: { BYTE byAlpha = pSrcRow->GetByte(); if (byAlpha == 0x00) {} else if (byAlpha == 0xff) { BYTE byFillAlpha = rgbColor.GetAlpha(); if (byFillAlpha == 0xff) { while (pDest < pDestEnd) *pDest++ = rgbColor; } else { BYTE *pAlphaInv = CG32bitPixel::AlphaTable(byFillAlpha ^ 0xff); BYTE byRed = rgbPreMultColor.GetRed(); BYTE byGreen = rgbPreMultColor.GetGreen(); BYTE byBlue = rgbPreMultColor.GetBlue(); while (pDest < pDestEnd) { BYTE byRedResult = pAlphaInv[pDest->GetRed()] + byRed; BYTE byGreenResult = pAlphaInv[pDest->GetGreen()] + byGreen; BYTE byBlueResult = pAlphaInv[pDest->GetBlue()] + byBlue; *pDest++ = CG32bitPixel(byRedResult, byGreenResult, byBlueResult); } } } else { // Blend the alphas together BYTE byFillAlpha = CG32bitPixel::BlendAlpha(byAlpha, rgbColor.GetAlpha()); BYTE *pAlpha = CG32bitPixel::AlphaTable(byFillAlpha); BYTE *pAlphaInv = CG32bitPixel::AlphaTable(byFillAlpha ^ 0xff); BYTE byRed = pAlpha[rgbColor.GetRed()]; BYTE byGreen = pAlpha[rgbColor.GetBlue()]; BYTE byBlue = pAlpha[rgbColor.GetGreen()]; while (pDest < pDestEnd) { BYTE byRedResult = pAlphaInv[pDest->GetRed()] + byRed; BYTE byGreenResult = pAlphaInv[pDest->GetGreen()] + byGreen; BYTE byBlueResult = pAlphaInv[pDest->GetBlue()] + byBlue; *pDest++ = CG32bitPixel(byRedResult, byGreenResult, byBlueResult); } } break; } case typeByteArray: { BYTE *pSrcAlpha = pSrcRow->GetByteArray() + xOffset; BYTE *pSrcAlphaEnd = pSrcAlpha + cxTileLeft; BYTE byColorAlpha = rgbColor.GetAlpha(); if (byColorAlpha == 0xff) { while (pSrcAlpha < pSrcAlphaEnd) { if (*pSrcAlpha == 0x00) {} else if (*pSrcAlpha == 0xff) *pDest = rgbColor; else { BYTE *pAlpha = CG32bitPixel::AlphaTable(*pSrcAlpha); BYTE *pAlphaInv = CG32bitPixel::AlphaTable(*pSrcAlpha ^ 0xff); BYTE byRedResult = pAlphaInv[pDest->GetRed()] + pAlpha[rgbColor.GetRed()]; BYTE byGreenResult = pAlphaInv[pDest->GetGreen()] + pAlpha[rgbColor.GetGreen()]; BYTE byBlueResult = pAlphaInv[pDest->GetBlue()] + pAlpha[rgbColor.GetBlue()]; *pDest = CG32bitPixel(byRedResult, byGreenResult, byBlueResult); } pSrcAlpha++; pDest++; } } else { BYTE *pAlphaFFInv = CG32bitPixel::AlphaTable(byColorAlpha ^ 0xff); while (pSrcAlpha < pSrcAlphaEnd) { if (*pSrcAlpha == 0x00) {} else if (*pSrcAlpha == 0xff) { BYTE byRedResult = pAlphaFFInv[pDest->GetRed()] + rgbPreMultColor.GetRed(); BYTE byGreenResult = pAlphaFFInv[pDest->GetGreen()] + rgbPreMultColor.GetGreen(); BYTE byBlueResult = pAlphaFFInv[pDest->GetBlue()] + rgbPreMultColor.GetBlue(); *pDest = CG32bitPixel(byRedResult, byGreenResult, byBlueResult); } else { BYTE byFillAlpha = CG32bitPixel::BlendAlpha(*pSrcAlpha, byColorAlpha); BYTE *pAlpha = CG32bitPixel::AlphaTable(byFillAlpha); BYTE *pAlphaInv = CG32bitPixel::AlphaTable(byFillAlpha ^ 0xff); BYTE byRedResult = pAlphaInv[pDest->GetRed()] + pAlpha[rgbColor.GetRed()]; BYTE byGreenResult = pAlphaInv[pDest->GetGreen()] + pAlpha[rgbColor.GetGreen()]; BYTE byBlueResult = pAlphaInv[pDest->GetBlue()] + pAlpha[rgbColor.GetBlue()]; *pDest = CG32bitPixel(byRedResult, byGreenResult, byBlueResult); } pSrcAlpha++; pDest++; } } break; } } pSrcRow++; pDestRow = Dest.NextRow(pDestRow); } break; } } } // Move to the next tile xTile++; xOffset = 0; xPos += cxTileLeft; xDestPos += cxTileLeft; } } // Next tile row yTile++; yOffset = 0; yPos += cyTileLeft; yDestPos += cyTileLeft; } }
void CButtonBarDisplay::Paint (CG32bitImage &Dest) // Paint // // Paint the bar { int i; // Fill background Dest.Fill(m_rcRect.left, m_rcRect.top, RectWidth(m_rcRect), RectHeight(m_rcRect), BAR_COLOR); // Get the images const CG32bitImage &Images = m_pButtons->GetImage(); // Paint each button for (i = 0; i < m_pButtons->GetCount(); i++) { RECT rcRect = m_pButtons->GetButtonRect(i); // Skip invisible buttons if (!m_pButtons->GetVisible(i)) continue; // Paint the image RECT rcSrc; GetImageRect(i, (i == m_iSelected), &rcSrc); Dest.Blt(rcSrc.left, rcSrc.top, RectWidth(rcSrc), RectHeight(rcSrc), Images, rcRect.left, rcRect.top); // Paint the button label int cxWidth = m_pFonts->SubTitle.MeasureText(m_pButtons->GetLabel(i), NULL); m_pFonts->SubTitle.DrawText(Dest, rcRect.left + (RectWidth(rcRect) - cxWidth) / 2, rcRect.top + BUTTON_LABEL_Y, CG32bitPixel(128,128,128), m_pButtons->GetLabel(i)); // Paint the description cxWidth = m_pFonts->Medium.MeasureText(m_pButtons->GetDescription(i), NULL); m_pFonts->Medium.DrawText(Dest, rcRect.left + (RectWidth(rcRect) - cxWidth) / 2, rcRect.top + BUTTON_DESCRIPTION_Y, CG32bitPixel(255,255,255), m_pButtons->GetDescription(i)); } }