Color Color::Modulate(const Color& c) const { uint8 R = static_cast<uint8>(GetRed() * c.GetRed() / 255); uint8 G = static_cast<uint8>(GetGreen() * c.GetGreen() / 255); uint8 B = static_cast<uint8>(GetBlue() * c.GetBlue() / 255); uint8 A = static_cast<uint8>(GetAlpha() * c.GetAlpha() / 255); return Color(R, G, B, A); }
Color Color::operator +(const Color& c) const { int R = GetRed() + c.GetRed(); int G = GetGreen() + c.GetGreen(); int B = GetBlue() + c.GetBlue(); int A = GetAlpha() + c.GetAlpha(); Color Ret; Ret.SetInt(R, G, B, A); return Ret; }
xui_method_explain(xui_family_create_win, get_bits, void* )( const xui_family& family, u16 wc ) { add_font(family); gdiinfo* info = m_gdiinfo_map[family.to_string()]; //draw char SolidBrush brush(Color::White); info->gdig->SetTextRenderingHint(TextRenderingHintAntiAliasGridFit); info->gdig->Clear(Color(0)); info->gdig->DrawString( (LPWSTR)(&wc), 1, info->gdif, PointF(0.0f,0.0f), StringFormat::GenericTypographic(), &brush); //char size RectF rect; info->gdig->MeasureString( (LPWSTR)(&wc), 1, info->gdif, PointF(0.0f, 0.0f), StringFormat::GenericTypographic(), &rect); info->size.w = (s32)ceilf(rect.Width ); info->size.h = (s32)ceilf(rect.Height); if (info->size.w == 0) info->size.w = family.size / 2; //copy buffer s32 w = info->size.w; s32 h = info->size.h; Color color; for (s32 y = 0; y < h; ++y) { for (s32 x = 0; x < w; ++x) { info->gdib->GetPixel(x, y, &color); info->bits[y*w+x] = color.GetAlpha(); } } return info->bits; }
//================================================= // Helper Functions //================================================= Color OffsetColor(Color clr, short sOffset) { BYTE bRed = 0; BYTE bGreen = 0; BYTE bBlue = 0; short sOffsetR = sOffset; short sOffsetG = sOffset; short sOffsetB = sOffset; if((sOffset < -255) || (sOffset > 255)) return clr; // Get RGB components of specified color bRed = clr.GetR(); bGreen = clr.GetG(); bBlue = clr.GetB(); // Calculate max. allowed real offset if(sOffset > 0) { if((bRed + sOffset) > 255) sOffsetR = (255 - bRed); if((bGreen + sOffset) > 255) sOffsetG = (255 - bGreen); if((bBlue + sOffset) > 255) sOffsetB = (255 - bBlue); sOffset = min(min(sOffsetR, sOffsetG), sOffsetB); } else { if((bRed + sOffset) < 0) sOffsetR = -bRed; if((bGreen + sOffset) < 0) sOffsetG = -bGreen; if((bBlue + sOffset) < 0) sOffsetB = -bBlue; sOffset = max(max(sOffsetR, sOffsetG), sOffsetB); } return Color(clr.GetAlpha(), (BYTE)(bRed + sOffset), (BYTE)(bGreen + sOffset), (BYTE)(bBlue + sOffset)); }
int FontSheet::GetCharMaxX(Bitmap& charBitmap) { int width = charBitmap.GetWidth(); int height = charBitmap.GetHeight(); for(int x = width-1; x >= 0; --x) { for(int y = 0; y < height; ++y) { Color color; charBitmap.GetPixel(x, y, &color); if(color.GetAlpha() > 0) { return x; } } } return width-1; }
/** * \brief Test to see if we clicked on the image. * \param pos Position to test * \returns True if clicked on */ bool CImageDrawable::HitTest(Gdiplus::Point pos) { Matrix mat; mat.Translate((float)mCenter.X, (float)mCenter.Y); mat.Rotate((float)(mPlacedR * RtoD)); mat.Translate((float)-mPlacedPosition.X, (float)-mPlacedPosition.Y); Point points[] = { pos }; mat.TransformPoints(points, 1); double wid = mImage->GetWidth(); double hit = mImage->GetHeight(); double testX = points[0].X; double testY = points[0].Y; // Test to see if x, y are in the image if (testX < 0 || testY < 0 || testX >= wid || testY >= hit) { // We are outside the image return false; } // Test to see if x, y are in the drawn part of the image auto format = mImage->GetPixelFormat(); if (format == PixelFormat32bppARGB || format == PixelFormat32bppPARGB) { // This image has an alpha map, which implements the // transparency. If so, we should check to see if we // clicked on a pixel where alpha is not zero, meaning // the pixel shows on the screen. Color color; mImage->GetPixel((int)testX, (int)testY, &color); return color.GetAlpha() != 0; } else { return true; } }
//--------------------------------------------------------------------------- int GetCharMaxX(Gdiplus::Bitmap& charBitmap) { using namespace Gdiplus; int width = charBitmap.GetWidth(); int height = charBitmap.GetHeight(); for(int x = width-1; x >= 0; --x) { for(int y = 0; y < height; ++y) { Color color; charBitmap.GetPixel(x, y, &color); if(color.GetAlpha() > 0) { return x; } } } return width-1; }
IrisColor* IrisBitmap::GetPixel(int x, int y){ Color color; this->bitmap->GetPixel(x, y, &color); return new IrisColor(color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha()); }
bool D3D11::FGdiFont::Reload() { assert(FRenderContext::Get()->InRenderThread()); const char* head = "FGdiFont::Reload"; bool dirtChars = false; bool dirtConfig = false; std::set<WCHAR> inputChars; { lock_guard<mutex> lck(Mutex); inputChars.insert(PendingCharacters.begin(), PendingCharacters.end()); if (PendingConfig != nullptr) { Property.Config = *PendingConfig; SAFE_DELETE(PendingConfig); dirtConfig = true; } } inputChars.insert(Property.Characters.begin(), Property.Characters.end()); dirtChars = Property.Characters != inputChars; if (!dirtConfig && !dirtChars) { return true; } auto& config = Property.Config; auto& td = Property.TextureDescription; td.TextureWidth = STexWidth; Property.CharacterDescriptions.clear(); Property.Characters.clear(); std::vector<WCHAR> vecChars(inputChars.begin(), inputChars.end()); Property.FontTexture = (new FTexture2D); auto hint = config.bAntiAliased ? TextRenderingHintAntiAliasGridFit : TextRenderingHintSingleBitPerPixelGridFit; hint = TextRenderingHintClearTypeGridFit; LOGFONTW lf; wcscpy_s(lf.lfFaceName, config.FontName.c_str()); lf.lfHeight = (int32)-config.Height; lf.lfWidth = 0; lf.lfWeight = config.Weight; lf.lfItalic = config.bItalic; lf.lfUnderline = config.bUnderline; lf.lfStrikeOut = 0; lf.lfCharSet = config.CharSet; lf.lfOutPrecision = config.OutPrecision; lf.lfClipPrecision = config.ClipPrecision; lf.lfQuality = config.Quality; lf.lfPitchAndFamily = config.PitchAndFamily; ULONG_PTR token = NULL; GdiplusStartupInput startupInput(NULL, TRUE, TRUE); GdiplusStartupOutput startupOutput; Gdiplus::Status ret; if (Gdiplus::Ok != (ret = GdiplusStartup(&token, &startupInput, &startupOutput))) { LVERR(head, "GdiplusStartup failed: %d", ret); return false; } HDC hFont = ::GetDC(NULL); Gdiplus::Font font(hFont, &lf); if (Gdiplus::Ok != (ret = font.GetLastStatus())) { LVERR(head, "Gdiplus::Font::GetLastStatus failed: %d", ret); RETURN_FALSE; } int32 size = (int32)(config.Height) * vecChars.size(); Bitmap bmp(size, size, PixelFormat32bppARGB); if (Gdiplus::Ok != (ret = bmp.GetLastStatus())) { LVERR(head, "Bitmap::GetLastStatus failed: %d", ret); RETURN_FALSE; } Graphics graphics(&bmp); if (Gdiplus::Ok != (ret = graphics.GetLastStatus())) { LVERR(head, "Graphics::GetLastStatus failed: %d", ret); RETURN_FALSE; } if (Gdiplus::Ok != (ret = graphics.SetTextRenderingHint(hint))) { LVERR(head, "Graphics::SetTextRenderingHint failed: %d", ret); RETURN_FALSE; } Property.CharHeight = font.GetHeight(&graphics); RectF rect; if (Gdiplus::Ok != (ret = graphics.MeasureString(vecChars.data(), vecChars.size(), &font, PointF(0, 0), &rect))) { LVERR(head, "Graphics::MeasureString failed: %d", ret); RETURN_FALSE; } int32 numRows = (int32)(rect.Width / td.TextureWidth) + 1; td.TextureHeight = (int32)(numRows * Property.CharHeight) + 1; int32 tsz = (int32)config.Height * 2; Bitmap bmp2(tsz, tsz, PixelFormat32bppARGB); if (Gdiplus::Ok != (ret = bmp2.GetLastStatus())) { LVERR(head, "Bitmap::GetLastStatus failed: %d", ret); RETURN_FALSE; } Graphics graphics2(&bmp2); if (Gdiplus::Ok != (ret = graphics2.GetLastStatus())) { LVERR(head, "Graphics::GetLastStatus failed: %d", ret); RETURN_FALSE; } if (Gdiplus::Ok != (ret = graphics2.SetTextRenderingHint(hint))) { LVERR(head, "Graphics::SetTextRenderingHint failed: %d", ret); RETURN_FALSE; } Bitmap bmp3(td.TextureWidth, td.TextureHeight, PixelFormat32bppARGB); if (Gdiplus::Ok != (ret = bmp3.GetLastStatus())) { LVERR(head, "Bitmap::GetLastStatus failed: %d", ret); RETURN_FALSE; } Graphics graphics3(&bmp3); if (Gdiplus::Ok != (ret = graphics3.GetLastStatus())) { LVERR(head, "Graphics::GetLastStatus failed: %d", ret); RETURN_FALSE; } if (Gdiplus::Ok != (ret = graphics3.Clear(Color(0, 255, 255, 255)))) { LVERR(head, "Graphics::Clear failed: %d", ret); RETURN_FALSE; } if (Gdiplus::Ok != (ret = graphics3.SetCompositingMode(CompositingModeSourceCopy))) { LVERR(head, "Graphics::SetCompositingMode failed: %d", ret); RETURN_FALSE; } SolidBrush brush(Color(255, 255, 255, 255)); if (Gdiplus::Ok != (ret = brush.GetLastStatus())) { LVERR(head, "SolidBrush::GetLastStatus failed: %d", ret); RETURN_FALSE; } int32 currX = 0; int32 currY = 0; for (auto it = inputChars.begin(); it != inputChars.end(); ++it) { WCHAR wc = *it; // 跳过不绘制的字符 if (wc == ' ') { Property.Characters.insert(wc); Property.CharacterDescriptions.insert(FCharacterDescription(wc)); continue; } if (Gdiplus::Ok != (ret = graphics2.Clear(Color(0, 255, 255, 255)))) { LVERR(head, "graphics2::Clear failed: %d", ret); RETURN_FALSE; } if (Gdiplus::Ok != (ret = graphics2.DrawString(&wc, 1, &font, PointF(0, 0), &brush))) { LVERR(head, "graphics2::DrawString failed: %d", ret); RETURN_FALSE; } int32 minX = 0; for (int32 x = 0; x < tsz; ++x) { for (int32 y = 0; y < tsz; ++y) { Color col; if (Gdiplus::Ok != (ret = bmp2.GetPixel(x, y, &col))) { LVERR(head, "Bitmap::GetPixel failed: %d", ret); RETURN_FALSE; } if (col.GetAlpha() > 0) { minX = x; x = tsz; break; } } } int32 maxX = tsz - 1; for (int32 x = tsz - 1; x >= 0; --x) { for (int32 y = 0; y < tsz; ++y) { Color col; if (Gdiplus::Ok != (ret = bmp2.GetPixel(x, y, &col))) { LVERR(head, "Bitmap::GetPixel failed: %d", ret); RETURN_FALSE; } if (col.GetAlpha() > 0) { maxX = x; x = -1; break; } } } int32 charWidth = maxX - minX + 1; if (currX + charWidth >= td.TextureWidth) { currX = 0; currY += (int32)(Property.CharHeight) + 1; } Property.Characters.insert(wc); Property.CharacterDescriptions.insert(FCharacterDescription(wc, currX, currY, charWidth, (int32)Property.CharHeight)); int32 height = (int32)(Property.CharHeight) + 1; if (Gdiplus::Ok != (ret = graphics3.DrawImage(&bmp2, currX, currY, minX, 0, charWidth, height, UnitPixel))) { LVERR(head, "Graphics::DrawImage failed: %d", ret); RETURN_FALSE; } currX += charWidth + 1; } const WCHAR space = ' '; if (Gdiplus::Ok != (ret = graphics2.MeasureString(&space, 1, &font, PointF(0, 0), &rect))) { LVERR(head, "Graphics::MeasureString failed: %d", ret); RETURN_FALSE; } // 如果字符串里有空格 td.SpaceWidth = rect.Width; Property.CharacterDescriptions.insert(FCharacterDescription(space, 0, 0, rect.Width, (int32)Property.CharHeight)); BitmapData bmpData; if (Gdiplus::Ok != (ret = bmp3.LockBits(&Rect(0, 0, td.TextureWidth, td.TextureHeight), ImageLockModeRead, PixelFormat32bppARGB, &bmpData))) { LVERR(head, "Bitmap::LockBits failed: %d", ret); RETURN_FALSE; } Property.FontTexture->Construct(td.TextureWidth, td.TextureHeight, DXGI_FORMAT_B8G8R8A8_UNORM, false, false, true, false, bmpData.Scan0, td.TextureWidth * 4); bmp3.UnlockBits(&bmpData); ::ReleaseDC(NULL, hFont); return true; }
/* ** Read the meter-specific options from the ini-file. ** */ void TintedImage::ReadOptions(ConfigParser& parser, const WCHAR* section, const WCHAR* imagePath) { // Store the current values so we know if the image needs to be tinted or transformed Rect oldCrop = m_Crop; CROPMODE oldCropMode = m_CropMode; bool oldGreyScale = m_GreyScale; ColorMatrix oldColorMatrix = *m_ColorMatrix; RotateFlipType oldFlip = m_Flip; REAL oldRotate = m_Rotate; std::wstring oldPath = m_Path; m_Path = parser.ReadString(section, m_OptionArray[OptionIndexImagePath], imagePath); PathUtil::AppendBacklashIfMissing(m_Path); m_HasPathChanged = (oldPath != m_Path); if (!m_DisableTransform) { m_Crop.X = m_Crop.Y = m_Crop.Width = m_Crop.Height = -1; m_CropMode = CROPMODE_TL; const std::wstring& crop = parser.ReadString(section, m_OptionArray[OptionIndexImageCrop], L""); if (!crop.empty()) { if (wcschr(crop.c_str(), L',')) { WCHAR* parseSz = _wcsdup(crop.c_str()); WCHAR* token; token = wcstok(parseSz, L","); if (token) { m_Crop.X = parser.ParseInt(token, 0); token = wcstok(nullptr, L","); if (token) { m_Crop.Y = parser.ParseInt(token, 0); token = wcstok(nullptr, L","); if (token) { m_Crop.Width = parser.ParseInt(token, 0); token = wcstok(nullptr, L","); if (token) { m_Crop.Height = parser.ParseInt(token, 0); token = wcstok(nullptr, L","); if (token) { m_CropMode = (CROPMODE)parser.ParseInt(token, 0); } } } } } free(parseSz); } if (m_CropMode < CROPMODE_TL || m_CropMode > CROPMODE_C) { m_CropMode = CROPMODE_TL; LogErrorF(m_Skin, L"%s=%s (origin) is not valid in [%s]", m_OptionArray[OptionIndexImageCrop], crop, section); } } } m_NeedsCrop = (oldCrop.X != m_Crop.X || oldCrop.Y != m_Crop.Y || oldCrop.Width != m_Crop.Width || oldCrop.Height != m_Crop.Height || oldCropMode != m_CropMode); m_GreyScale = parser.ReadBool(section, m_OptionArray[OptionIndexGreyscale], false); Color tint = parser.ReadColor(section, m_OptionArray[OptionIndexImageTint], Color::White); int alpha = parser.ReadInt(section, m_OptionArray[OptionIndexImageAlpha], tint.GetAlpha()); // for backwards compatibility alpha = min(255, alpha); alpha = max(0, alpha); *m_ColorMatrix = c_IdentityMatrix; // Read in the Color Matrix // It has to be read in like this because it crashes when reading over 17 floats // at one time. The parser does it fine, but after putting the returned values // into the Color Matrix the next time the parser is used it crashes. std::vector<Gdiplus::REAL> matrix1 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix1]); if (matrix1.size() == 5) { for (int i = 0; i < 4; ++i) // The fifth column must be 0. { m_ColorMatrix->m[0][i] = matrix1[i]; } } else { m_ColorMatrix->m[0][0] = (REAL)tint.GetRed() / 255.0f; } std::vector<Gdiplus::REAL> matrix2 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix2]); if (matrix2.size() == 5) { for (int i = 0; i < 4; ++i) // The fifth column must be 0. { m_ColorMatrix->m[1][i] = matrix2[i]; } } else { m_ColorMatrix->m[1][1] = (REAL)tint.GetGreen() / 255.0f; } std::vector<Gdiplus::REAL> matrix3 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix3]); if (matrix3.size() == 5) { for (int i = 0; i < 4; ++i) // The fifth column must be 0. { m_ColorMatrix->m[2][i] = matrix3[i]; } } else { m_ColorMatrix->m[2][2] = (REAL)tint.GetBlue() / 255.0f; } std::vector<Gdiplus::REAL> matrix4 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix4]); if (matrix4.size() == 5) { for (int i = 0; i < 4; ++i) // The fifth column must be 0. { m_ColorMatrix->m[3][i] = matrix4[i]; } } else { m_ColorMatrix->m[3][3] = (REAL)alpha / 255.0f; } std::vector<Gdiplus::REAL> matrix5 = parser.ReadFloats(section, m_OptionArray[OptionIndexColorMatrix5]); if (matrix5.size() == 5) { for (int i = 0; i < 4; ++i) // The fifth column must be 1. { m_ColorMatrix->m[4][i] = matrix5[i]; } } m_NeedsTinting = (oldGreyScale != m_GreyScale || !CompareColorMatrix(&oldColorMatrix, m_ColorMatrix)); m_UseExifOrientation = parser.ReadBool(section, m_OptionArray[OptionIndexUseExifOrientation], false); const WCHAR* flip = parser.ReadString(section, m_OptionArray[OptionIndexImageFlip], L"NONE").c_str(); if (_wcsicmp(flip, L"NONE") == 0) { m_Flip = RotateNoneFlipNone; } else if (_wcsicmp(flip, L"HORIZONTAL") == 0) { m_Flip = RotateNoneFlipX; } else if (_wcsicmp(flip, L"VERTICAL") == 0) { m_Flip = RotateNoneFlipY; } else if (_wcsicmp(flip, L"BOTH") == 0) { m_Flip = RotateNoneFlipXY; } else { LogErrorF(m_Skin, L"%s=%s (origin) is not valid in [%s]", m_OptionArray[OptionIndexImageFlip], flip, section); } if (!m_DisableTransform) { m_Rotate = (REAL)parser.ReadFloat(section, m_OptionArray[OptionIndexImageRotate], 0.0); } m_NeedsTransform = (oldFlip != m_Flip || oldRotate != m_Rotate); }
inline void ToGDIColor(const Color& source, Gdiplus::Color& target) { target = Gdiplus::Color(source.GetAlpha(), source.GetRed(), source.GetGreen(), source.GetBlue()); }