diff options
Diffstat (limited to '')
-rw-r--r-- | vcl/skia/x11/gdiimpl.cxx | 161 | ||||
-rw-r--r-- | vcl/skia/x11/salvd.cxx | 86 | ||||
-rw-r--r-- | vcl/skia/x11/textrender.cxx | 80 |
3 files changed, 327 insertions, 0 deletions
diff --git a/vcl/skia/x11/gdiimpl.cxx b/vcl/skia/x11/gdiimpl.cxx new file mode 100644 index 000000000..1602218c1 --- /dev/null +++ b/vcl/skia/x11/gdiimpl.cxx @@ -0,0 +1,161 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Some of this code is based on Skia source code, covered by the following + * license notice (see readlicense_oo for the full license): + * + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + */ + +#include <skia/x11/gdiimpl.hxx> + +#include <tools/sk_app/unix/WindowContextFactory_unix.h> + +#include <skia/utils.hxx> +#include <skia/zone.hxx> + +#include <X11/Xutil.h> + +X11SkiaSalGraphicsImpl::X11SkiaSalGraphicsImpl(X11SalGraphics& rParent) + : SkiaSalGraphicsImpl(rParent, rParent.GetGeometryProvider()) + , mX11Parent(rParent) +{ +} + +X11SkiaSalGraphicsImpl::~X11SkiaSalGraphicsImpl() {} + +void X11SkiaSalGraphicsImpl::Init() +{ + // The m_pFrame and m_pVDev pointers are updated late in X11 + setProvider(mX11Parent.GetGeometryProvider()); + SkiaSalGraphicsImpl::Init(); +} + +void X11SkiaSalGraphicsImpl::createWindowContext(bool forceRaster) +{ + assert(mX11Parent.GetDrawable() != None); + mWindowContext = createWindowContext( + mX11Parent.GetXDisplay(), mX11Parent.GetDrawable(), &mX11Parent.GetVisual(), GetWidth(), + GetHeight(), forceRaster ? SkiaHelper::RenderRaster : SkiaHelper::renderMethodToUse(), + false); +} + +std::unique_ptr<sk_app::WindowContext> +X11SkiaSalGraphicsImpl::createWindowContext(Display* display, Drawable drawable, + const XVisualInfo* visual, int width, int height, + SkiaHelper::RenderMethod renderMethod, bool temporary) +{ + SkiaZone zone; + sk_app::DisplayParams displayParams; + displayParams.fColorType = kN32_SkColorType; + sk_app::window_context_factory::XlibWindowInfo winInfo; + assert(display); + winInfo.fDisplay = display; + winInfo.fWindow = drawable; + winInfo.fFBConfig = nullptr; // not used + winInfo.fVisualInfo = const_cast<XVisualInfo*>(visual); + assert(winInfo.fVisualInfo->visual != nullptr); // make sure it's not an uninitialized SalVisual + winInfo.fWidth = width; + winInfo.fHeight = height; +#ifdef DBG_UTIL + // Our patched Skia has VulkanWindowContext that shares GrContext, which requires + // that the X11 visual is always the same. Ensure it is so. + static VisualID checkVisualID = -1U; + // Exception is for the temporary case during startup, when SkiaHelper's + // checkDeviceBlacklisted() needs a WindowContext and may be called before SalVisual + // is ready. + if (!temporary) + { + assert(checkVisualID == -1U || winInfo.fVisualInfo->visualid == checkVisualID); + checkVisualID = winInfo.fVisualInfo->visualid; + } +#else + (void)temporary; +#endif + switch (renderMethod) + { + case SkiaHelper::RenderRaster: + // TODO The Skia Xlib code actually requires the non-native color type to work properly. + displayParams.fColorType + = (displayParams.fColorType == kBGRA_8888_SkColorType ? kRGBA_8888_SkColorType + : kBGRA_8888_SkColorType); + return sk_app::window_context_factory::MakeRasterForXlib(winInfo, displayParams); + case SkiaHelper::RenderVulkan: + return sk_app::window_context_factory::MakeVulkanForXlib(winInfo, displayParams); + } + abort(); +} + +bool X11SkiaSalGraphicsImpl::avoidRecreateByResize() const +{ + if (!mSurface || isOffscreen()) + return false; + // Skia's WindowContext uses actual dimensions of the X window, which due to X11 being + // asynchronous may be temporarily different from what VCL thinks are the dimensions. + // That can lead to us repeatedly calling recreateSurface() because of "incorrect" + // size, and we otherwise need to check for size changes, because VCL does not inform us. + // Avoid the problem here by checking the size of the X window and bail out if Skia + // would just return the same size as it is now. + Window r; + int x, y; + unsigned int w, h, border, depth; + XGetGeometry(mX11Parent.GetXDisplay(), mX11Parent.GetDrawable(), &r, &x, &y, &w, &h, &border, + &depth); + return mSurface->width() == int(w) && mSurface->height() == int(h); +} + +void X11SkiaSalGraphicsImpl::DeInit() +{ + SkiaZone zone; + SkiaSalGraphicsImpl::DeInit(); + mWindowContext.reset(); +} + +void X11SkiaSalGraphicsImpl::freeResources() {} + +void X11SkiaSalGraphicsImpl::performFlush() +{ + SkiaZone zone; + flushDrawing(); + // TODO XPutImage() is somewhat inefficient, XShmPutImage() should be preferred. + mWindowContext->swapBuffers(); +} + +std::unique_ptr<sk_app::WindowContext> createVulkanWindowContext(bool temporary) +{ + SalDisplay* salDisplay = vcl_sal::getSalDisplay(GetGenericUnixSalData()); + const XVisualInfo* visual; + XVisualInfo* visuals = nullptr; + if (!temporary) + visual = &salDisplay->GetVisual(salDisplay->GetDefaultXScreen()); + else + { + // SalVisual from salDisplay may not be setup yet at this point, get + // info for the default visual. + XVisualInfo search; + search.visualid = XVisualIDFromVisual( + DefaultVisual(salDisplay->GetDisplay(), salDisplay->GetDefaultXScreen().getXScreen())); + int count; + visuals = XGetVisualInfo(salDisplay->GetDisplay(), VisualIDMask, &search, &count); + assert(count == 1); + visual = visuals; + } + std::unique_ptr<sk_app::WindowContext> ret = X11SkiaSalGraphicsImpl::createWindowContext( + salDisplay->GetDisplay(), None, visual, 1, 1, SkiaHelper::RenderVulkan, temporary); + if (temporary) + XFree(visuals); + return ret; +} + +void X11SkiaSalGraphicsImpl::prepareSkia() { SkiaHelper::prepareSkia(createVulkanWindowContext); } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/skia/x11/salvd.cxx b/vcl/skia/x11/salvd.cxx new file mode 100644 index 000000000..a4db9c75d --- /dev/null +++ b/vcl/skia/x11/salvd.cxx @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <vcl/sysdata.hxx> + +#include <unx/salunx.h> +#include <unx/saldisp.hxx> +#include <unx/salgdi.h> +#include <unx/salvd.h> + +#include <skia/x11/salvd.hxx> + +void X11SalGraphics::Init(X11SkiaSalVirtualDevice* pDevice) +{ + SalDisplay* pDisplay = pDevice->GetDisplay(); + + m_nXScreen = pDevice->GetXScreenNumber(); + m_pColormap = &pDisplay->GetColormap(m_nXScreen); + + m_pVDev = pDevice; + m_pFrame = nullptr; + + bWindow_ = pDisplay->IsDisplay(); + bVirDev_ = true; + + mxImpl->Init(); +} + +X11SkiaSalVirtualDevice::X11SkiaSalVirtualDevice(SalGraphics const* pGraphics, long nDX, long nDY, + const SystemGraphicsData* pData, + std::unique_ptr<X11SalGraphics> pNewGraphics) + : mpGraphics(std::move(pNewGraphics)) + , mbGraphics(false) + , mnXScreen(0) +{ + assert(mpGraphics); + + // TODO Check where a VirtualDevice is created from SystemGraphicsData + assert(pData == nullptr); + (void)pData; + + mpDisplay = vcl_sal::getSalDisplay(GetGenericUnixSalData()); + mnXScreen = pGraphics ? static_cast<X11SalGraphics const*>(pGraphics)->GetScreenNumber() + : vcl_sal::getSalDisplay(GetGenericUnixSalData())->GetDefaultXScreen(); + mnWidth = nDX; + mnHeight = nDY; + mpGraphics->Init(this); +} + +X11SkiaSalVirtualDevice::~X11SkiaSalVirtualDevice() {} + +SalGraphics* X11SkiaSalVirtualDevice::AcquireGraphics() +{ + if (mbGraphics) + return nullptr; + + if (mpGraphics) + mbGraphics = true; + + return mpGraphics.get(); +} + +void X11SkiaSalVirtualDevice::ReleaseGraphics(SalGraphics*) { mbGraphics = false; } + +bool X11SkiaSalVirtualDevice::SetSize(long nDX, long nDY) +{ + if (!nDX) + nDX = 1; + if (!nDY) + nDY = 1; + + mnWidth = nDX; + mnHeight = nDY; + if (mpGraphics) + mpGraphics->Init(this); + + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/skia/x11/textrender.cxx b/vcl/skia/x11/textrender.cxx new file mode 100644 index 000000000..13eff3012 --- /dev/null +++ b/vcl/skia/x11/textrender.cxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <skia/x11/textrender.hxx> + +#include <unx/fc_fontoptions.hxx> +#include <unx/freetype_glyphcache.hxx> +#include <vcl/svapp.hxx> +#include <sallayout.hxx> +#include <skia/gdiimpl.hxx> + +#include <SkFont.h> +#include <SkFontMgr_fontconfig.h> + +void SkiaTextRender::DrawTextLayout(const GenericSalLayout& rLayout, const SalGraphics& rGraphics) +{ + const FreetypeFontInstance& rInstance = static_cast<FreetypeFontInstance&>(rLayout.GetFont()); + const FreetypeFont& rFont = rInstance.GetFreetypeFont(); + const FontSelectPattern& rFSD = rInstance.GetFontSelectPattern(); + int nHeight = rFSD.mnHeight; + int nWidth = rFSD.mnWidth ? rFSD.mnWidth : nHeight; + if (nWidth == 0 || nHeight == 0) + return; + + if (FreetypeFont::AlmostHorizontalDrainsRenderingPool(nWidth * 10 / nHeight, rFSD)) + return; + + if (!fontManager) + { + // Get the global FcConfig that our VCL fontconfig code uses, and refcount it. + fontManager = SkFontMgr_New_FontConfig(FcConfigReference(nullptr)); + } + sk_sp<SkTypeface> typeface + = SkFontMgr_createTypefaceFromFcPattern(fontManager, rFont.GetFontOptions()->GetPattern()); + SkFont font(typeface, nHeight); + // TODO are these correct? + if (rFont.NeedsArtificialItalic()) + font.setSkewX(-0x6000L / 0x10000L); + if (rFont.NeedsArtificialBold()) + font.setEmbolden(true); + font.setEdging(rFont.GetAntialiasAdvice() ? SkFont::Edging::kAntiAlias + : SkFont::Edging::kAlias); + + assert(dynamic_cast<SkiaSalGraphicsImpl*>(rGraphics.GetImpl())); + SkiaSalGraphicsImpl* impl = static_cast<SkiaSalGraphicsImpl*>(rGraphics.GetImpl()); + impl->drawGenericLayout(rLayout, mnTextColor, font, + SkiaSalGraphicsImpl::GlyphOrientation::Apply); +} + +void SkiaTextRender::ClearDevFontCache() { fontManager.reset(); } + +#if 0 +// SKIA TODO +void FontConfigFontOptions::cairo_font_options_substitute(FcPattern* pPattern) +{ + ImplSVData* pSVData = ImplGetSVData(); + const cairo_font_options_t* pFontOptions = pSVData->mpDefInst->GetCairoFontOptions(); + if( !pFontOptions ) + return; + cairo_ft_font_options_substitute(pFontOptions, pPattern); +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |