bool Window::CheckAlignment() const { // Only top left-alignment is supported for move and resize if (GetHorizontalAlignment() == HA_LEFT && GetVerticalAlignment() == VA_TOP) return true; else return false; }
void TextFormatD2D::SetProperties(const WCHAR* fontFamily, int size, bool bold, bool italic, Gdiplus::PrivateFontCollection* fontCollection) { Dispose(); HRESULT hr = E_FAIL; // |fontFamily| uses the GDI/GDI+ font naming convention so try to create DirectWrite font // using the GDI family name and then create a text format using the DirectWrite family name // obtained from it. WCHAR dwFamilyName[LF_FACESIZE]; DWRITE_FONT_WEIGHT dwFontWeight; DWRITE_FONT_STYLE dwFontStyle; DWRITE_FONT_STRETCH dwFontStretch; if (GetDWPropertiesFromGDIProperties( fontFamily, bold, italic, dwFontWeight, dwFontStyle, dwFontStretch, dwFamilyName, _countof(dwFamilyName))) { hr = CanvasD2D::c_DWFactory->CreateTextFormat( dwFamilyName, nullptr, dwFontWeight, dwFontStyle, dwFontStretch, size * (4.0f / 3.0f), L"", &m_TextFormat); } if (FAILED(hr)) { // Fallback in case above fails. hr = CanvasD2D::c_DWFactory->CreateTextFormat( fontFamily, nullptr, bold ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_REGULAR, italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, size * (4.0f / 3.0f), L"", &m_TextFormat); } if (SUCCEEDED(hr)) { SetHorizontalAlignment(GetHorizontalAlignment()); SetVerticalAlignment(GetVerticalAlignment()); } else { Dispose(); } }
const Matrix3x4& Sprite::GetTransform() const { if (positionDirty_) { Vector2 pos = floatPosition_; Matrix3x4 parentTransform; if (parent_) { Sprite* parentSprite = dynamic_cast<Sprite*>(parent_); if (parentSprite) parentTransform = parentSprite->GetTransform(); else { const IntVector2& parentScreenPos = parent_->GetScreenPosition() + parent_->GetChildOffset(); parentTransform = Matrix3x4::IDENTITY; parentTransform.SetTranslation(Vector3((float)parentScreenPos.x_, (float)parentScreenPos.y_, 0.0f)); } switch (GetHorizontalAlignment()) { case HA_LEFT: break; case HA_CENTER: pos.x_ += (float)(parent_->GetSize().x_ / 2); break; case HA_RIGHT: pos.x_ += (float)parent_->GetSize().x_; break; } switch (GetVerticalAlignment()) { case VA_TOP: break; case VA_CENTER: pos.y_ += (float)(parent_->GetSize().y_ / 2); break; case VA_BOTTOM: pos.y_ += (float)(parent_->GetSize().y_); break; } } else parentTransform = Matrix3x4::IDENTITY; Matrix3x4 hotspotAdjust(Matrix3x4::IDENTITY); hotspotAdjust.SetTranslation(Vector3((float)-hotSpot_.x_, (float)-hotSpot_.y_, 0.0f)); Matrix3x4 mainTransform(Vector3(pos, 0.0f), Quaternion(rotation_, Vector3::FORWARD), Vector3(scale_, 1.0f)); transform_ = parentTransform * mainTransform * hotspotAdjust; positionDirty_ = false; // Calculate an approximate screen position for GetElementAt(), or pixel-perfect child elements Vector3 topLeftCorner = transform_ * Vector3::ZERO; screenPosition_ = IntVector2((int)topLeftCorner.x_, (int)topLeftCorner.y_); } return transform_; }
void TextFormatD2D::SetProperties( const WCHAR* fontFamily, int size, bool bold, bool italic, const FontCollection* fontCollection) { auto fontCollectionD2D = (FontCollectionD2D*)fontCollection; Dispose(); WCHAR dwriteFamilyName[LF_FACESIZE]; DWRITE_FONT_WEIGHT dwriteFontWeight = bold ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_REGULAR; DWRITE_FONT_STYLE dwriteFontStyle = italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; DWRITE_FONT_STRETCH dwriteFontStretch = DWRITE_FONT_STRETCH_NORMAL; const float dwriteFontSize = size * (4.0f / 3.0f); // |fontFamily| uses the GDI/GDI+ font naming convention so try to create DirectWrite font // using the GDI family name and then create a text format using the DirectWrite family name // obtained from it. HRESULT hr = Util::GetDWritePropertiesFromGDIProperties( CanvasD2D::c_DWFactory.Get(), fontFamily, bold, italic, dwriteFontWeight, dwriteFontStyle, dwriteFontStretch, dwriteFamilyName, _countof(dwriteFamilyName)); if (SUCCEEDED(hr)) { hr = CanvasD2D::c_DWFactory->CreateTextFormat( dwriteFamilyName, nullptr, dwriteFontWeight, dwriteFontStyle, dwriteFontStretch, dwriteFontSize, L"", &m_TextFormat); } if (FAILED(hr)) { IDWriteFontCollection* dwriteFontCollection = nullptr; // If |fontFamily| is not in the system collection, use the font collection from // |fontCollectionD2D| if possible. if (!Util::IsFamilyInSystemFontCollection(CanvasD2D::c_DWFactory.Get(), fontFamily) && (fontCollectionD2D && fontCollectionD2D->InitializeCollection())) { IDWriteFont* dwriteFont = Util::FindDWriteFontInFontCollectionByGDIFamilyName( fontCollectionD2D->m_Collection, fontFamily); if (dwriteFont) { hr = Util::GetFamilyNameFromDWriteFont( dwriteFont, dwriteFamilyName, _countof(dwriteFamilyName)); if (SUCCEEDED(hr)) { fontFamily = dwriteFamilyName; Util::GetPropertiesFromDWriteFont( dwriteFont, bold, italic, &dwriteFontWeight, &dwriteFontStyle, &dwriteFontStretch); } dwriteFont->Release(); } dwriteFontCollection = fontCollectionD2D->m_Collection; } // Fallback in case above fails. hr = CanvasD2D::c_DWFactory->CreateTextFormat( fontFamily, dwriteFontCollection, dwriteFontWeight, dwriteFontStyle, dwriteFontStretch, dwriteFontSize, L"", &m_TextFormat); } if (SUCCEEDED(hr)) { SetHorizontalAlignment(GetHorizontalAlignment()); SetVerticalAlignment(GetVerticalAlignment()); // Get the family name to in case CreateTextFormat() fallbacked on some other family name. hr = m_TextFormat->GetFontFamilyName(dwriteFamilyName, _countof(dwriteFamilyName)); if (FAILED(hr)) return; Microsoft::WRL::ComPtr<IDWriteFontCollection> collection; Microsoft::WRL::ComPtr<IDWriteFontFamily> fontFamily; UINT32 familyNameIndex; BOOL exists; if (FAILED(m_TextFormat->GetFontCollection(collection.GetAddressOf())) || FAILED(collection->FindFamilyName(dwriteFamilyName, &familyNameIndex, &exists)) || FAILED(collection->GetFontFamily(familyNameIndex, fontFamily.GetAddressOf()))) { return; } Microsoft::WRL::ComPtr<IDWriteFont> font; hr = fontFamily->GetFirstMatchingFont( m_TextFormat->GetFontWeight(), m_TextFormat->GetFontStretch(), m_TextFormat->GetFontStyle(), font.GetAddressOf()); if (FAILED(hr)) return; DWRITE_FONT_METRICS fmetrics; font->GetMetrics(&fmetrics); // GDI+ compatibility: GDI+ adds extra padding below the string when |m_AccurateText| is // |false|. The bottom padding seems to be based on the font metrics so we can calculate it // once and keep using it regardless of the actual string. In some cases, GDI+ also adds // the line gap to the overall height so we will store it as well. const float pixelsPerDesignUnit = dwriteFontSize / (float)fmetrics.designUnitsPerEm; m_ExtraHeight = (((float)fmetrics.designUnitsPerEm / 8.0f) - fmetrics.lineGap) * pixelsPerDesignUnit; m_LineGap = fmetrics.lineGap * pixelsPerDesignUnit; } else { Dispose(); } }
const FVector2D UKUIInterfaceElement::CalculateAlignLocation( const FVector2D& v2Origin, const FVector2D& v2Extent, const FVector2D& v2Size, const FVector2D& v2Default ) { FVector2D v2AlignLocation; const FVector2D v2MarginSize = GetMarginSize(); // X+Z, Y+W if ( bDebug ) KUILogUO( "(%f,%f) (%f,%f) (%f,%f) (%f,%f)", ExpandV2( v2Origin ), ExpandV2( v2Extent ), ExpandV2( v2Size ), ExpandV2( v2Default ) ); switch ( GetHorizontalAlignment() ) { case EKUIInterfaceHAlign::HA_Left: v2AlignLocation.X = v2Origin.X; break; case EKUIInterfaceHAlign::HA_Centre: v2AlignLocation.X = v2Origin.X + ( v2Extent.X / 2.f ) - ( v2Size.X / 2.f ); break; case EKUIInterfaceHAlign::HA_Right: v2AlignLocation.X = v2Origin.X + v2Extent.X - v2Size.X; break; case EKUIInterfaceHAlign::HA_Left_Outer: v2AlignLocation.X = v2Origin.X - v2Size.X; break; case EKUIInterfaceHAlign::HA_Right_Outer: v2AlignLocation.X = v2Origin.X + v2Extent.X; break; case EKUIInterfaceHAlign::HA_Fill: SetSize( v2Extent.X - v2MarginSize.X, GetSize().Y ); v2AlignLocation.X = v2Origin.X; break; case EKUIInterfaceHAlign::HA_None: default: v2AlignLocation.X = v2Default.X; break; } switch ( GetVerticalAlignment() ) { case EKUIInterfaceVAlign::VA_Top: v2AlignLocation.Y = v2Origin.Y; break; case EKUIInterfaceVAlign::VA_Centre: v2AlignLocation.Y = v2Origin.Y + ( v2Extent.Y / 2.f ) - ( v2Size.Y / 2.f ); break; case EKUIInterfaceVAlign::VA_Bottom: v2AlignLocation.Y = v2Origin.Y + v2Extent.Y - v2Size.Y; break; case EKUIInterfaceVAlign::VA_Top_Outer: v2AlignLocation.Y = v2Origin.Y - v2Size.Y; break; case EKUIInterfaceVAlign::VA_Bottom_Outer: v2AlignLocation.Y = v2Origin.Y + v2Extent.Y; break; case EKUIInterfaceVAlign::VA_Fill: SetSize( GetSize().X, v2Extent.Y - v2MarginSize.Y ); v2AlignLocation.Y = v2Origin.Y; break; case EKUIInterfaceVAlign::VA_None: default: v2AlignLocation.Y = v2Default.Y; break; } v2AlignLocation += GetMarginOffset(); if ( bDebug ) KUILogUO( "%f,%f", ExpandV2( v2AlignLocation ) ); return v2AlignLocation; }