// Paints the tabs that intersect the window's update rectangle. void Paint(HDC hdc, RECT &rc) { IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); // paint the background bool isTranslucentMode = inTitlebar && dwm::IsCompositionEnabled(); if (isTranslucentMode) PaintParentBackground(hwnd, hdc); else { HBRUSH brush = CreateSolidBrush(color.bar); FillRect(hdc, &rc, brush); DeleteObject(brush); } // TODO: GDI+ doesn't seem to cope well with SetWorldTransform XFORM ctm = { 1.0, 0, 0, 1.0, 0, 0 }; SetWorldTransform(hdc, &ctm); Graphics graphics(hdc); graphics.SetCompositingMode(CompositingModeSourceCopy); graphics.SetCompositingQuality(CompositingQualityHighQuality); graphics.SetSmoothingMode(SmoothingModeHighQuality); graphics.SetTextRenderingHint(TextRenderingHintClearTypeGridFit); graphics.SetPageUnit(UnitPixel); GraphicsPath shapes(data->Points, data->Types, data->Count); GraphicsPath shape; GraphicsPathIterator iterator(&shapes); SolidBrush br(Color(0, 0, 0)); Pen pen(&br, 2.0f); Font f(hdc, GetDefaultGuiFont()); // TODO: adjust these constant values for DPI? RectF layout((REAL)DpiScaleX(hwnd,3), 1.0f, REAL(width - DpiScaleX(hwnd,20)), (REAL)height); StringFormat sf(StringFormat::GenericDefault()); sf.SetFormatFlags(StringFormatFlagsNoWrap); sf.SetLineAlignment(StringAlignmentCenter); sf.SetTrimming(StringTrimmingEllipsisCharacter); REAL yPosTab = inTitlebar ? 0.0f : REAL(ClientRect(hwnd).dy - height - 1); for (int i = 0; i < Count(); i++) { graphics.ResetTransform(); graphics.TranslateTransform(1.f + (REAL)(width + 1) * i - (REAL)rc.left, yPosTab - (REAL)rc.top); if (!graphics.IsVisible(0, 0, width + 1, height + 1)) continue; // in firefox style we only paint current and highlighed tabs // all other tabs only show bool onlyText = g_FirefoxStyle && !((current == i) || (highlighted == i)); if (onlyText) { #if 0 // we need to first paint the background with the same color as caption, // otherwise the text looks funny (because is transparent?) // TODO: what is the damn bg color of caption? bar is too light, outline is too dark Color bgColTmp; bgColTmp.SetFromCOLORREF(color.bar); { SolidBrush bgBr(bgColTmp); graphics.FillRectangle(&bgBr, layout); } bgColTmp.SetFromCOLORREF(color.outline); { SolidBrush bgBr(bgColTmp); graphics.FillRectangle(&bgBr, layout); } #endif // TODO: this is a hack. If I use no background and cleartype, the // text looks funny (is bold). // CompositingModeSourceCopy doesn't work with clear type // another option is to draw background before drawing text, but // I can't figure out what is the actual color of caption graphics.SetTextRenderingHint(TextRenderingHintAntiAliasGridFit); graphics.SetCompositingMode(CompositingModeSourceCopy); //graphics.SetCompositingMode(CompositingModeSourceOver); br.SetColor(ToColor(color.text)); graphics.DrawString(text.At(i), -1, &f, layout, &sf, &br); graphics.SetTextRenderingHint(TextRenderingHintClearTypeGridFit); continue; } COLORREF bgCol = color.background;; if (current == i) { bgCol = color.current; } else if (highlighted == i) { bgCol = color.highlight; } // ensure contrast between text and background color // TODO: adjust threshold (and try adjusting both current/background tabs) COLORREF textCol = color.text; float bgLight = GetLightness(bgCol), textLight = GetLightness(textCol); if (textLight < bgLight ? bgLight < 0x70 : bgLight > 0x90) textCol = textLight ? AdjustLightness(textCol, 255.0f / textLight - 1.0f) : RGB(255, 255, 255); if (fabs(textLight - bgLight) < 0x40) textCol = bgLight < 0x80 ? RGB(255, 255, 255) : RGB(0, 0, 0); // paint tab's body graphics.SetCompositingMode(CompositingModeSourceCopy); iterator.NextMarker(&shape); br.SetColor(ToColor(bgCol)); graphics.FillPath(&br, &shape); // draw tab's text graphics.SetCompositingMode(CompositingModeSourceOver); br.SetColor(ToColor(textCol)); graphics.DrawString(text.At(i), -1, &f, layout, &sf, &br); // paint "x"'s circle iterator.NextMarker(&shape); if (xClicked == i || xHighlighted == i) { br.SetColor(ToColor(i == xClicked ? color.x_click : color.x_highlight)); graphics.FillPath(&br, &shape); } // paint "x" iterator.NextMarker(&shape); if (xClicked == i || xHighlighted == i) pen.SetColor(ToColor(color.x_line)); else pen.SetColor(ToColor(color.outline)); graphics.DrawPath(&pen, &shape); iterator.Rewind(); } }
// Paints the tabs that intersect the window's update rectangle. void Paint(HDC hdc, RECT& rc) { IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); // paint the background #if 0 bool isTranslucentMode = inTitlebar && dwm::IsCompositionEnabled(); if (isTranslucentMode) { PaintParentBackground(hwnd, hdc); } else { // note: not sure what color should be used here and painting // background works fine /*HBRUSH brush = CreateSolidBrush(colors.bar); FillRect(hdc, &rc, brush); DeleteObject(brush);*/ } #else PaintParentBackground(hwnd, hdc); #endif // TODO: GDI+ doesn't seem to cope well with SetWorldTransform XFORM ctm = {1.0, 0, 0, 1.0, 0, 0}; SetWorldTransform(hdc, &ctm); Graphics gfx(hdc); gfx.SetCompositingMode(CompositingModeSourceCopy); gfx.SetCompositingQuality(CompositingQualityHighQuality); gfx.SetSmoothingMode(SmoothingModeHighQuality); gfx.SetTextRenderingHint(TextRenderingHintClearTypeGridFit); gfx.SetPageUnit(UnitPixel); GraphicsPath shapes(data->Points, data->Types, data->Count); GraphicsPath shape; GraphicsPathIterator iterator(&shapes); SolidBrush br(Color(0, 0, 0)); Pen pen(&br, 2.0f); Font f(hdc, GetDefaultGuiFont()); // TODO: adjust these constant values for DPI? RectF layout((REAL)DpiScaleX(hwnd, 3), 1.0f, REAL(width - DpiScaleX(hwnd, 20)), (REAL)height); StringFormat sf(StringFormat::GenericDefault()); sf.SetFormatFlags(StringFormatFlagsNoWrap); sf.SetLineAlignment(StringAlignmentCenter); sf.SetTrimming(StringTrimmingEllipsisCharacter); REAL yPosTab = inTitlebar ? 0.0f : REAL(ClientRect(hwnd).dy - height - 1); for (int i = 0; i < Count(); i++) { gfx.ResetTransform(); gfx.TranslateTransform(1.f + (REAL)(width + 1) * i - (REAL)rc.left, yPosTab - (REAL)rc.top); if (!gfx.IsVisible(0, 0, width + 1, height + 1)) continue; // Get the correct colors based on the state and the current theme COLORREF bgCol = GetAppColor(AppColor::TabBackgroundBg); COLORREF textCol = GetAppColor(AppColor::TabBackgroundText); COLORREF xColor = GetAppColor(AppColor::TabBackgroundCloseX); COLORREF circleColor = GetAppColor(AppColor::TabBackgroundCloseCircle); if (selectedTabIdx == i) { bgCol = GetAppColor(AppColor::TabSelectedBg); textCol = GetAppColor(AppColor::TabSelectedText); xColor = GetAppColor(AppColor::TabSelectedCloseX); circleColor = GetAppColor(AppColor::TabSelectedCloseCircle); } else if (highlighted == i) { bgCol = GetAppColor(AppColor::TabHighlightedBg); textCol = GetAppColor(AppColor::TabHighlightedText); xColor = GetAppColor(AppColor::TabHighlightedCloseX); circleColor = GetAppColor(AppColor::TabHighlightedCloseCircle); } if (xHighlighted == i) { xColor = GetAppColor(AppColor::TabHoveredCloseX); circleColor = GetAppColor(AppColor::TabHoveredCloseCircle); } if (xClicked == i) { xColor = GetAppColor(AppColor::TabClickedCloseX); circleColor = GetAppColor(AppColor::TabClickedCloseCircle); } // paint tab's body gfx.SetCompositingMode(CompositingModeSourceCopy); iterator.NextMarker(&shape); br.SetColor(ToColor(bgCol)); Point points[4]; shape.GetPathPoints(points, 4); Rect body(points[0].X, points[0].Y, points[2].X - points[0].X, points[2].Y - points[0].Y); body.Inflate(0, 0); gfx.SetClip(body); body.Inflate(5, 5); gfx.FillRectangle(&br, body); gfx.ResetClip(); // draw tab's text gfx.SetCompositingMode(CompositingModeSourceOver); br.SetColor(ToColor(textCol)); gfx.DrawString(text.at(i), -1, &f, layout, &sf, &br); // paint "x"'s circle iterator.NextMarker(&shape); bool closeCircleEnabled = true; if ((xClicked == i || xHighlighted == i) && closeCircleEnabled) { br.SetColor(ToColor(circleColor)); gfx.FillPath(&br, &shape); } // paint "x" iterator.NextMarker(&shape); pen.SetColor(ToColor(xColor)); gfx.DrawPath(&pen, &shape); iterator.Rewind(); } }