bool UniscribeController::shape(const UChar* str, int len, SCRIPT_ITEM item, const Font* fontData, Vector<WORD>& glyphs, Vector<WORD>& clusters, Vector<SCRIPT_VISATTR>& visualAttributes) { HWndDC hdc; HFONT oldFont = 0; HRESULT shapeResult = E_PENDING; int glyphCount = 0; if (!fontData) return false; do { shapeResult = ScriptShape(hdc, fontData->scriptCache(), str, len, glyphs.size(), &item.a, glyphs.data(), clusters.data(), visualAttributes.data(), &glyphCount); if (shapeResult == E_PENDING) { // The script cache isn't primed with enough info yet. We need to select our HFONT into // a DC and pass the DC in to ScriptShape. ASSERT(!hdc); hdc.setHWnd(0); HFONT hfont = fontData->platformData().hfont(); oldFont = (HFONT)SelectObject(hdc, hfont); } else if (shapeResult == E_OUTOFMEMORY) { // Need to resize our buffers. glyphs.resize(glyphs.size() * 2); visualAttributes.resize(glyphs.size()); } } while (shapeResult == E_PENDING || shapeResult == E_OUTOFMEMORY); if (hdc) SelectObject(hdc, oldFont); if (FAILED(shapeResult)) return false; glyphs.shrink(glyphCount); visualAttributes.shrink(glyphCount); return true; }
void PopupMenuWin::paint(const IntRect& damageRect, HDC hdc) { if (!m_popup) return; if (!m_DC) { m_DC = adoptGDIObject(::CreateCompatibleDC(HWndDC(m_popup))); if (!m_DC) return; } if (m_bmp) { bool keepBitmap = false; BITMAP bitmap; if (::GetObject(m_bmp.get(), sizeof(bitmap), &bitmap)) keepBitmap = bitmap.bmWidth == clientRect().width() && bitmap.bmHeight == clientRect().height(); if (!keepBitmap) m_bmp.clear(); } if (!m_bmp) { BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(clientRect().size()); void* pixels = 0; m_bmp = adoptGDIObject(::CreateDIBSection(m_DC.get(), &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0)); if (!m_bmp) return; ::SelectObject(m_DC.get(), m_bmp.get()); } GraphicsContext context(m_DC.get()); int itemCount = client()->listSize(); // listRect is the damageRect translated into the coordinates of the entire menu list (which is itemCount * m_itemHeight pixels tall) IntRect listRect = damageRect; listRect.move(IntSize(0, m_scrollOffset * m_itemHeight)); for (int y = listRect.y(); y < listRect.maxY(); y += m_itemHeight) { int index = y / m_itemHeight; Color optionBackgroundColor, optionTextColor; PopupMenuStyle itemStyle = client()->itemStyle(index); if (index == focusedIndex()) { optionBackgroundColor = RenderTheme::defaultTheme()->activeListBoxSelectionBackgroundColor(); optionTextColor = RenderTheme::defaultTheme()->activeListBoxSelectionForegroundColor(); } else { optionBackgroundColor = itemStyle.backgroundColor(); optionTextColor = itemStyle.foregroundColor(); } // itemRect is in client coordinates IntRect itemRect(0, (index - m_scrollOffset) * m_itemHeight, damageRect.width(), m_itemHeight); // Draw the background for this menu item if (itemStyle.isVisible()) context.fillRect(itemRect, optionBackgroundColor); if (client()->itemIsSeparator(index)) { IntRect separatorRect(itemRect.x() + separatorPadding, itemRect.y() + (itemRect.height() - separatorHeight) / 2, itemRect.width() - 2 * separatorPadding, separatorHeight); context.fillRect(separatorRect, optionTextColor); continue; } String itemText = client()->itemText(index); TextRun textRun(itemText, 0, 0, AllowTrailingExpansion, itemStyle.textDirection(), itemStyle.hasTextDirectionOverride()); context.setFillColor(optionTextColor); FontCascade itemFont = client()->menuStyle().font(); if (client()->itemIsLabel(index)) { auto d = itemFont.fontDescription(); d.setWeight(d.bolderWeight()); itemFont = FontCascade(d, itemFont.letterSpacing(), itemFont.wordSpacing()); itemFont.update(m_popupClient->fontSelector()); } // Draw the item text if (itemStyle.isVisible()) { int textX = 0; if (client()->menuStyle().textDirection() == LTR) { textX = std::max<int>(0, client()->clientPaddingLeft() - client()->clientInsetLeft()); if (RenderTheme::defaultTheme()->popupOptionSupportsTextIndent()) textX += minimumIntValueForLength(itemStyle.textIndent(), itemRect.width()); } else { textX = itemRect.width() - client()->menuStyle().font().width(textRun); textX = std::min<int>(textX, textX - client()->clientPaddingRight() + client()->clientInsetRight()); if (RenderTheme::defaultTheme()->popupOptionSupportsTextIndent()) textX -= minimumIntValueForLength(itemStyle.textIndent(), itemRect.width()); } int textY = itemRect.y() + itemFont.fontMetrics().ascent() + (itemRect.height() - itemFont.fontMetrics().height()) / 2; context.drawBidiText(itemFont, textRun, IntPoint(textX, textY)); } } if (m_scrollbar) m_scrollbar->paint(context, damageRect); HWndDC hWndDC; HDC localDC = hdc ? hdc : hWndDC.setHWnd(m_popup); ::BitBlt(localDC, damageRect.x(), damageRect.y(), damageRect.width(), damageRect.height(), m_DC.get(), damageRect.x(), damageRect.y(), SRCCOPY); }