static void getDirtyRects(HWND window, Vector<CGRect>& outRects)
{
    ASSERT_ARG(outRects, outRects.isEmpty());

    RECT clientRect;
    if (!GetClientRect(window, &clientRect))
        return;

    auto region = adoptGDIObject(::CreateRectRgn(0, 0, 0, 0));
    int regionType = GetUpdateRgn(window, region.get(), false);
    if (regionType != COMPLEXREGION) {
        RECT dirtyRect;
        if (GetUpdateRect(window, &dirtyRect, false))
            outRects.append(winRectToCGRect(dirtyRect, clientRect));
        return;
    }

    DWORD dataSize = ::GetRegionData(region.get(), 0, 0);
    auto regionDataBuffer = std::make_unique<unsigned char[]>(dataSize);
    RGNDATA* regionData = reinterpret_cast<RGNDATA*>(regionDataBuffer.get());
    if (!::GetRegionData(region.get(), dataSize, regionData))
        return;

    outRects.resize(regionData->rdh.nCount);

    RECT* rect = reinterpret_cast<RECT*>(regionData->Buffer);
    for (size_t i = 0; i < outRects.size(); ++i, ++rect)
        outRects[i] = winRectToCGRect(*rect, clientRect);
}
FontPlatformData FontCustomPlatformData::fontPlatformData(const FontDescription& fontDescription, bool bold, bool italic)
{
    int size = fontDescription.computedPixelSize();
    FontRenderingMode renderingMode = fontDescription.renderingMode();

    LOGFONT logFont;
    memset(&logFont, 0, sizeof(LOGFONT));
    wcsncpy(logFont.lfFaceName, m_name.charactersWithNullTermination().data(), LF_FACESIZE - 1);

    logFont.lfHeight = -size;
    if (renderingMode == FontRenderingMode::Normal)
        logFont.lfHeight *= 32;
    logFont.lfWidth = 0;
    logFont.lfEscapement = 0;
    logFont.lfOrientation = 0;
    logFont.lfUnderline = false;
    logFont.lfStrikeOut = false;
    logFont.lfCharSet = DEFAULT_CHARSET;
    logFont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
    logFont.lfQuality = CLEARTYPE_QUALITY;
    logFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
    logFont.lfItalic = italic;
    logFont.lfWeight = bold ? 700 : 400;

    auto hfont = adoptGDIObject(::CreateFontIndirect(&logFont));

    cairo_font_face_t* fontFace = cairo_win32_font_face_create_for_hfont(hfont.get());

    FontPlatformData fontPlatformData(WTFMove(hfont), fontFace, size, bold, italic);

    cairo_font_face_destroy(fontFace);

    return fontPlatformData;
}
Пример #3
0
// FIXME: Is it possible to merge getWindowsContext and createWindowsBitmap into a single API
// suitable for all clients?
void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
{
    bool createdBitmap = mayCreateBitmap && (!m_data->m_hdc || isInTransparencyLayer());
    if (!createdBitmap) {
        m_data->restore();
        return;
    }

    if (dstRect.isEmpty())
        return;

    auto bitmap = adoptGDIObject(static_cast<HBITMAP>(::GetCurrentObject(hdc, OBJ_BITMAP)));

    DIBPixelData pixelData(bitmap.get());

    ASSERT(pixelData.bitsPerPixel() == 32);

    CGContextRef bitmapContext = CGBitmapContextCreate(pixelData.buffer(), pixelData.size().width(), pixelData.size().height(), 8,
                                                       pixelData.bytesPerRow(), deviceRGBColorSpaceRef(), kCGBitmapByteOrder32Little |
                                                       (supportAlphaBlend ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst));

    CGImageRef image = CGBitmapContextCreateImage(bitmapContext);
    CGContextDrawImage(m_data->m_cgContext.get(), dstRect, image);
    
    // Delete all our junk.
    CGImageRelease(image);
    CGContextRelease(bitmapContext);
    ::DeleteDC(hdc);
}
Пример #4
0
DragImageRef createDragImageFromImage(Image* img, ImageOrientationDescription)
{
    HWndDC dc(0);
    auto workingDC = adoptGDIObject(::CreateCompatibleDC(dc));
    if (!workingDC)
        return 0;

    CGContextRef drawContext = 0;
    auto hbmp = allocImage(workingDC.get(), img->size(), &drawContext);
    if (!hbmp || !drawContext)
        return 0;

    CGImageRef srcImage = img->getCGImageRef();
    CGRect rect;
    rect.size = img->size();
    rect.origin.x = 0;
    rect.origin.y = -rect.size.height;
    static const CGFloat white [] = {1.0, 1.0, 1.0, 1.0};
    CGContextScaleCTM(drawContext, 1, -1);
    CGContextSetFillColor(drawContext, white);
    CGContextFillRect(drawContext, rect);
    if (srcImage) {
        CGContextSetBlendMode(drawContext, kCGBlendModeNormal);
        CGContextDrawImage(drawContext, rect, srcImage);
    }
    CGContextRelease(drawContext);

    return hbmp.leak();
}
Пример #5
0
HFONT FontPlatformData::hfont() const
{
    if (!isValid())
        return 0;

    if (m_private->m_disabled)
        return 0;

    if (!m_private->m_rootFontData->m_hfont)
        m_private->m_rootFontData->m_hfont = adoptGDIObject(::CreateFontIndirect(&m_private->m_rootFontData->m_font));

    return m_private->m_rootFontData->m_hfont.get();
}
Пример #6
0
DragImageRef scaleDragImage(DragImageRef imageRef, FloatSize scale)
{
    // FIXME: due to the way drag images are done on windows we need 
    // to preprocess the alpha channel <rdar://problem/5015946>
    if (!imageRef)
        return 0;

    GDIObject<HBITMAP> hbmp;
    auto image = adoptGDIObject(imageRef);

    IntSize srcSize = dragImageSize(image.get());
    IntSize dstSize(static_cast<int>(srcSize.width() * scale.width()), static_cast<int>(srcSize.height() * scale.height()));

    HWndDC dc(0);
    auto dstDC = adoptGDIObject(::CreateCompatibleDC(dc));
    if (!dstDC)
        goto exit;

    CGContextRef targetContext;
    hbmp = allocImage(dstDC.get(), dstSize, &targetContext);
    if (!hbmp)
        goto exit;

    CGContextRef srcContext = createCgContextFromBitmap(image.get());
    CGImageRef srcImage = CGBitmapContextCreateImage(srcContext);
    CGRect rect;
    rect.origin.x = 0;
    rect.origin.y = 0;
    rect.size = dstSize;
    CGContextDrawImage(targetContext, rect, srcImage);
    CGImageRelease(srcImage);
    CGContextRelease(srcContext);
    CGContextRelease(targetContext);

exit:
    if (!hbmp)
        hbmp.swap(image);
    return hbmp.leak();
}
Пример #7
0
RefPtr<Font> Font::platformCreateScaledFont(const FontDescription& fontDescription, float scaleFactor) const
{
    float scaledSize = scaleFactor * m_platformData.size();
    if (isCustomFont()) {
        FontPlatformData scaledFont(m_platformData);
        scaledFont.setSize(scaledSize);
        return Font::create(scaledFont, true, false);
    }

    LOGFONT winfont;
    GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winfont);
    winfont.lfHeight = -lroundf(scaledSize * (m_platformData.useGDI() ? 1 : 32));
    auto hfont = adoptGDIObject(::CreateFontIndirect(&winfont));
    return Font::create(FontPlatformData(WTFMove(hfont), scaledSize, m_platformData.syntheticBold(), m_platformData.syntheticOblique(), m_platformData.useGDI()), isCustomFont(), false);
}
Пример #8
0
HFONT FontPlatformData::getScaledFontHandle(int height, int width) const
{
    if (!isValid() || m_private->m_disabled)
        return 0;

    if (!m_private->m_hfontScaled || m_private->m_fontScaledHeight != height || m_private->m_fontScaledWidth != width) {
        m_private->m_fontScaledHeight = height;
        m_private->m_fontScaledWidth = width;
        LOGFONT font = m_private->m_rootFontData->m_font;
        font.lfHeight = -height;
        font.lfWidth = width;
        m_private->m_hfontScaled = adoptGDIObject(::CreateFontIndirect(&font));
    }

    return m_private->m_hfontScaled.get();
}
PassRefPtr<BitmapContext> createBitmapContextFromWebView(bool onscreen, bool incrementalRepaint, bool sweepHorizontally, bool drawSelectionRect)
{
    RECT frame;
    if (!GetWindowRect(webViewWindow, &frame))
        return nullptr;

    BITMAPINFO bmp = {0};
    bmp.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmp.bmiHeader.biWidth = frame.right - frame.left;
    bmp.bmiHeader.biHeight = -(frame.bottom - frame.top);
    bmp.bmiHeader.biPlanes = 1;
    bmp.bmiHeader.biBitCount = 32;
    bmp.bmiHeader.biCompression = BI_RGB;

    void* bits = 0;
    HBITMAP bitmap = ::CreateDIBSection(0, &bmp, DIB_RGB_COLORS, &bits, 0, 0);
    if (!bitmap)
        return nullptr;

    auto memoryDC = adoptGDIObject(::CreateCompatibleDC(0));
    ::SelectObject(memoryDC.get(), bitmap);
    SendMessage(webViewWindow, WM_PRINT, reinterpret_cast<WPARAM>(memoryDC.get()), PRF_CLIENT | PRF_CHILDREN | PRF_OWNED);

    BITMAP info = {0};
    GetObject(bitmap, sizeof(info), &info);
    ASSERT(info.bmBitsPixel == 32);

    // We create a context that has an alpha channel below so that the PNGs we generate will also
    // have an alpha channel. But WM_PRINT doesn't necessarily write anything into the alpha
    // channel, so we set the alpha channel to constant full opacity to make sure the resulting image is opaque.
    makeAlphaChannelOpaque(info.bmBits, info.bmWidth, info.bmHeight);

#if USE(CG)
    RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB());
    CGContextRef context = CGBitmapContextCreate(info.bmBits, info.bmWidth, info.bmHeight, 8,
                                                info.bmWidthBytes, colorSpace.get(), kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst);
#elif USE(CAIRO) 
    cairo_surface_t* image = cairo_image_surface_create_for_data((unsigned char*)info.bmBits, CAIRO_FORMAT_ARGB32, 
                                                      info.bmWidth, info.bmHeight, info.bmWidthBytes); 
    cairo_t* context = cairo_create(image); 
    cairo_surface_destroy(image); 
#endif 

   return BitmapContext::createByAdoptingBitmapAndContext(bitmap, context);
}
Пример #10
0
GDIObject<HBITMAP> allocImage(HDC dc, IntSize size, CGContextRef *targetRef)
{
    BitmapInfo bmpInfo = BitmapInfo::create(size);

    LPVOID bits;
    auto hbmp = adoptGDIObject(::CreateDIBSection(dc, &bmpInfo, DIB_RGB_COLORS, &bits, 0, 0));

    if (!targetRef)
        return hbmp;

    CGContextRef bitmapContext = CGBitmapContextCreate(bits, bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight, 8,
                                                       bmpInfo.bmiHeader.biWidth * 4, deviceRGBColorSpaceRef(),
                                                       kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst);
    if (!bitmapContext)
        return GDIObject<HBITMAP>();

    *targetRef = bitmapContext;
    return hbmp;
}
Пример #11
0
PassRefPtr<FixedSizeFontData> FixedSizeFontData::create(const AtomicString& family, unsigned weight, bool italic)
{
    FixedSizeFontData* fontData = new FixedSizeFontData();

    fontData->m_weight = weight;
    fontData->m_italic = italic;

    LOGFONT& winFont = fontData->m_font;
    // The size here looks unusual.  The negative number is intentional.
    winFont.lfHeight = -72;
    winFont.lfWidth = 0;
    winFont.lfEscapement = 0;
    winFont.lfOrientation = 0;
    winFont.lfUnderline = false;
    winFont.lfStrikeOut = false;
    winFont.lfCharSet = DEFAULT_CHARSET;
    winFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
    winFont.lfQuality = CLEARTYPE_QUALITY; //DEFAULT_QUALITY;
    winFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
    winFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
    winFont.lfItalic = italic;
    winFont.lfWeight = FontPlatformData::adjustedGDIFontWeight(weight, family);

    int len = std::min(family.length(), (unsigned int)LF_FACESIZE - 1);
    wmemcpy(winFont.lfFaceName, family.characters(), len);
    winFont.lfFaceName[len] = L'\0';

    fontData->m_hfont = adoptGDIObject(::CreateFontIndirect(&winFont));

    HGDIOBJ oldFont = SelectObject(g_screenDC, fontData->m_hfont.get());

    GetTextMetrics(g_screenDC, &fontData->m_metrics);

    if (IMLangFontLinkType* langFontLink = fontCache()->getFontLinkInterface()) {
        langFontLink->GetFontCodePages(g_screenDC, fontData->m_hfont.get(), &fontData->m_codePages);
        fontData->m_codePages |= FontPlatformData::getKnownFontCodePages(winFont.lfFaceName);
    }

    SelectObject(g_screenDC, oldFont);

    return adoptRef(fontData);
}
Пример #12
0
HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
{
    // FIXME: Should a bitmap be created also when a shadow is set?
    if (mayCreateBitmap && (!m_data->m_hdc || isInTransparencyLayer())) {
        if (dstRect.isEmpty())
            return 0;

        // Create a bitmap DC in which to draw.
        BitmapInfo bitmapInfo = BitmapInfo::create(dstRect.size());

        void* pixels = 0;
        HBITMAP bitmap = ::CreateDIBSection(NULL, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0);
        if (!bitmap)
            return 0;

        auto bitmapDC = adoptGDIObject(::CreateCompatibleDC(m_data->m_hdc));
        ::SelectObject(bitmapDC.get(), bitmap);

        // Fill our buffer with clear if we're going to alpha blend.
        if (supportAlphaBlend)
           fillWithClearColor(bitmap);

        // Make sure we can do world transforms.
        ::SetGraphicsMode(bitmapDC.get(), GM_ADVANCED);

        // Apply a translation to our context so that the drawing done will be at (0,0) of the bitmap.
        XFORM xform = TransformationMatrix().translate(-dstRect.x(), -dstRect.y());

        ::SetWorldTransform(bitmapDC.get(), &xform);

        return bitmapDC.leak();
    }

    m_data->flush();
    m_data->save();
    return m_data->m_hdc;
}
Пример #13
0
DragImageRef createDragImageForLink(URL& url, const String& inLabel, FontRenderingMode fontRenderingMode)
{
    // This is more or less an exact match for the Mac OS X code.

    const Font* labelFont;
    const Font* urlFont;
    FontCachePurgePreventer fontCachePurgePreventer;

    if (fontRenderingMode == AlternateRenderingMode) {
        static const Font alternateRenderingModeLabelFont = dragLabelFont(DragLinkLabelFontsize, true, AlternateRenderingMode);
        static const Font alternateRenderingModeURLFont = dragLabelFont(DragLinkUrlFontSize, false, AlternateRenderingMode);
        labelFont = &alternateRenderingModeLabelFont;
        urlFont = &alternateRenderingModeURLFont;
    } else {
        static const Font normalRenderingModeLabelFont = dragLabelFont(DragLinkLabelFontsize, true, NormalRenderingMode);
        static const Font normalRenderingModeURLFont = dragLabelFont(DragLinkUrlFontSize, false, NormalRenderingMode);
        labelFont = &normalRenderingModeLabelFont;
        urlFont = &normalRenderingModeURLFont;
    }

    bool drawURLString = true;
    bool clipURLString = false;
    bool clipLabelString = false;

    String urlString = url.string(); 
    String label = inLabel;
    if (label.isEmpty()) {
        drawURLString = false;
        label = urlString;
    }

    // First step in drawing the link drag image width.
    TextRun labelRun(label.impl());
    TextRun urlRun(urlString.impl());
    IntSize labelSize(labelFont->width(labelRun), labelFont->fontMetrics().ascent() + labelFont->fontMetrics().descent());

    if (labelSize.width() > MaxDragLabelStringWidth) {
        labelSize.setWidth(MaxDragLabelStringWidth);
        clipLabelString = true;
    }
    
    IntSize urlStringSize;
    IntSize imageSize(labelSize.width() + DragLabelBorderX * 2, labelSize.height() + DragLabelBorderY * 2);

    if (drawURLString) {
        urlStringSize.setWidth(urlFont->width(urlRun));
        urlStringSize.setHeight(urlFont->fontMetrics().ascent() + urlFont->fontMetrics().descent()); 
        imageSize.setHeight(imageSize.height() + urlStringSize.height());
        if (urlStringSize.width() > MaxDragLabelStringWidth) {
            imageSize.setWidth(MaxDragLabelWidth);
            clipURLString = true;
        } else
            imageSize.setWidth(std::max(labelSize.width(), urlStringSize.width()) + DragLabelBorderX * 2);
    }

    // We now know how big the image needs to be, so we create and
    // fill the background
    HWndDC dc(0);
    auto workingDC = adoptGDIObject(::CreateCompatibleDC(dc));
    if (!workingDC)
        return 0;

    PlatformGraphicsContext* contextRef;
    auto image = allocImage(workingDC.get(), imageSize, &contextRef);
    if (!image)
        return 0;
        
    ::SelectObject(workingDC.get(), image.get());
    GraphicsContext context(contextRef);
    // On Mac alpha is {0.7, 0.7, 0.7, 0.8}, however we can't control alpha
    // for drag images on win, so we use 1
    static const Color backgroundColor(140, 140, 140);
    static const IntSize radii(DragLabelRadius, DragLabelRadius);
    IntRect rect(0, 0, imageSize.width(), imageSize.height());
    context.fillRoundedRect(FloatRoundedRect(rect, radii, radii, radii, radii), backgroundColor, ColorSpaceDeviceRGB);
 
    // Draw the text
    static const Color topColor(0, 0, 0, 255); // original alpha = 0.75
    static const Color bottomColor(255, 255, 255, 127); // original alpha = 0.5
    if (drawURLString) {
        if (clipURLString)
            urlString = StringTruncator::rightTruncate(urlString, imageSize.width() - (DragLabelBorderX * 2.0f), *urlFont, StringTruncator::EnableRoundingHacks);
        IntPoint textPos(DragLabelBorderX, imageSize.height() - (LabelBorderYOffset + urlFont->fontMetrics().descent()));
        WebCoreDrawDoubledTextAtPoint(context, urlString, textPos, *urlFont, topColor, bottomColor);
    }
    
    if (clipLabelString)
        label = StringTruncator::rightTruncate(label, imageSize.width() - (DragLabelBorderX * 2.0f), *labelFont, StringTruncator::EnableRoundingHacks);

    IntPoint textPos(DragLabelBorderX, DragLabelBorderY + labelFont->pixelSize());
    WebCoreDrawDoubledTextAtPoint(context, label, textPos, *labelFont, topColor, bottomColor);

    deallocContext(contextRef);
    return image.leak();
}
Пример #14
0
static PassRefPtr<SharedCursor> createSharedCursor(Image* img, const IntPoint& hotSpot)
{
    RefPtr<SharedCursor> impl;

    IntPoint effectiveHotSpot = determineHotSpot(img, hotSpot);
    static bool doAlpha = windowsVersion() >= WindowsXP;
    BitmapInfo cursorImage = BitmapInfo::create(IntSize(img->width(), img->height()));

    HWndDC dc(0);
    auto workingDC = adoptGDIObject(::CreateCompatibleDC(dc));
    if (doAlpha) {
        auto hCursor = adoptGDIObject(::CreateDIBSection(dc, (BITMAPINFO *)&cursorImage, DIB_RGB_COLORS, 0, 0, 0));
        ASSERT(hCursor);

        img->getHBITMAP(hCursor.get()); 
        HBITMAP hOldBitmap = (HBITMAP)SelectObject(workingDC.get(), hCursor.get());
        SetBkMode(workingDC.get(), TRANSPARENT);
        SelectObject(workingDC.get(), hOldBitmap);

        Vector<unsigned char, 128> maskBits;
        maskBits.fill(0xff, (img->width() + 7) / 8 * img->height());
        auto hMask = adoptGDIObject(::CreateBitmap(img->width(), img->height(), 1, 1, maskBits.data()));

        ICONINFO ii;
        ii.fIcon = FALSE;
        ii.xHotspot = effectiveHotSpot.x();
        ii.yHotspot = effectiveHotSpot.y();
        ii.hbmMask = hMask.get();
        ii.hbmColor = hCursor.get();

        impl = SharedCursor::create(::CreateIconIndirect(&ii));
    } else {
        // Platform doesn't support alpha blended cursors, so we need
        // to create the mask manually
        auto andMaskDC = adoptGDIObject(::CreateCompatibleDC(dc));
        auto xorMaskDC = adoptGDIObject(::CreateCompatibleDC(dc));
        auto hCursor = adoptGDIObject(::CreateDIBSection(dc, &cursorImage, DIB_RGB_COLORS, 0, 0, 0));
        ASSERT(hCursor);
        img->getHBITMAP(hCursor.get()); 
        BITMAP cursor;
        GetObject(hCursor.get(), sizeof(BITMAP), &cursor);
        auto andMask = adoptGDIObject(::CreateBitmap(cursor.bmWidth, cursor.bmHeight, 1, 1, 0));
        auto xorMask = adoptGDIObject(::CreateCompatibleBitmap(dc, cursor.bmWidth, cursor.bmHeight));
        HBITMAP oldCursor = (HBITMAP)SelectObject(workingDC.get(), hCursor.get());
        HBITMAP oldAndMask = (HBITMAP)SelectObject(andMaskDC.get(), andMask.get());
        HBITMAP oldXorMask = (HBITMAP)SelectObject(xorMaskDC.get(), xorMask.get());

        SetBkColor(workingDC.get(), RGB(0, 0, 0));  
        BitBlt(andMaskDC.get(), 0, 0, cursor.bmWidth, cursor.bmHeight, workingDC.get(), 0, 0, SRCCOPY);
    
        SetBkColor(xorMaskDC.get(), RGB(255, 255, 255));
        SetTextColor(xorMaskDC.get(), RGB(255, 255, 255));
        BitBlt(xorMaskDC.get(), 0, 0, cursor.bmWidth, cursor.bmHeight, andMaskDC.get(), 0, 0, SRCCOPY);
        BitBlt(xorMaskDC.get(), 0, 0, cursor.bmWidth, cursor.bmHeight, workingDC.get(), 0, 0, SRCAND);

        SelectObject(workingDC.get(), oldCursor);
        SelectObject(andMaskDC.get(), oldAndMask);
        SelectObject(xorMaskDC.get(), oldXorMask);

        ICONINFO icon = {0};
        icon.fIcon = FALSE;
        icon.xHotspot = effectiveHotSpot.x();
        icon.yHotspot = effectiveHotSpot.y();
        icon.hbmMask = andMask.get();
        icon.hbmColor = xorMask.get();
        impl = SharedCursor::create(CreateIconIndirect(&icon));
    }

    return impl.release();
}