diff --git a/kcms/CMakeLists.txt b/kcms/CMakeLists.txt --- a/kcms/CMakeLists.txt +++ b/kcms/CMakeLists.txt @@ -60,11 +60,12 @@ add_subdirectory(touchpad) endif() +if(FONTCONFIG_FOUND AND FREETYPE_FOUND) + add_subdirectory( kfontinst ) +endif() + if( FREETYPE_FOUND ) if(FONTCONFIG_FOUND ) add_subdirectory( fonts ) endif() endif() -if(FONTCONFIG_FOUND AND FREETYPE_FOUND) - add_subdirectory( kfontinst ) -endif() diff --git a/kcms/fonts/CMakeLists.txt b/kcms/fonts/CMakeLists.txt --- a/kcms/fonts/CMakeLists.txt +++ b/kcms/fonts/CMakeLists.txt @@ -8,7 +8,9 @@ ########### next target ############### -set(kcm_fonts_PART_SRCS ../krdb/krdb.cpp fonts.cpp) +include_directories(../kfontinst/lib) + +set(kcm_fonts_PART_SRCS ../krdb/krdb.cpp previewrenderengine.cpp previewimageprovider.cpp fonts.cpp ../kfontinst/lib/FcEngine.cpp) if(X11_FOUND) set(kcm_fonts_PART_SRCS ${kcm_fonts_PART_SRCS} ${libkxftconfig_SRCS}) @@ -19,8 +21,7 @@ add_library(kcm_fonts MODULE ${kcm_fonts_PART_SRCS}) - -target_link_libraries(kcm_fonts Qt5::DBus Qt5::Xml KF5::KCMUtils KF5::I18n KF5::KDELibs4Support ${FREETYPE_LIBRARIES}) +target_link_libraries(kcm_fonts Qt5::DBus Qt5::Xml KF5::KCMUtils KF5::I18n KF5::KDELibs4Support ${FREETYPE_LIBRARIES} kfontinst) if(X11_FOUND) target_link_libraries(kcm_fonts @@ -34,7 +35,7 @@ target_link_libraries(kcm_fonts ${FONTCONFIG_LIBRARIES}) endif() - target_link_libraries(kcm_fonts ${X11_LIBRARIES}) + target_link_libraries(kcm_fonts ${X11_LIBRARIES} ${X11_Xft_LIB}) endif() kcoreaddons_desktop_to_json(kcm_fonts "kcm_fonts.desktop") diff --git a/kcms/fonts/fonts.cpp b/kcms/fonts/fonts.cpp --- a/kcms/fonts/fonts.cpp +++ b/kcms/fonts/fonts.cpp @@ -47,6 +47,7 @@ #include #include "../krdb/krdb.h" +#include "previewimageprovider.h" /**** DLL Interface ****/ K_PLUGIN_FACTORY_WITH_JSON(KFontsFactory, "kcm_fonts.json", registerPlugin();) @@ -489,6 +490,8 @@ cg = KConfigGroup(config, "WM"); m_windowTitleFont = m_windowTitleFontOriginal = nearestExistingFont(cg.readEntry("activeFont", m_defaultFont)); + engine()->addImageProvider("preview", new PreviewImageProvider(generalFont())); + emit generalFontChanged(); emit fixedWidthFontChanged(); emit smallFontChanged(); diff --git a/kcms/fonts/package/contents/ui/main.qml b/kcms/fonts/package/contents/ui/main.qml --- a/kcms/fonts/package/contents/ui/main.qml +++ b/kcms/fonts/package/contents/ui/main.qml @@ -21,6 +21,7 @@ import QtQuick.Layouts 1.1 import QtQuick.Controls 2.0 as QtControls import QtQuick.Dialogs 1.2 as QtDialogs +import QtQuick.Window 2.0 as QtWindow import org.kde.kirigami 2.3 as Kirigami import org.kde.kcm 1.1 as KCM @@ -138,6 +139,26 @@ model: kcm.fontAASettings.subPixelOptionsModel textRole: "display" enabled: antiAliasingComboBox.currentIndex == 0 + delegate: QtControls.ItemDelegate { + id: subPixelDelegate + width: subPixelComboImage.implicitWidth + contentItem: ColumnLayout { + id: subPixelLayout + width: subPixelComboImage.implicitWidth + QtControls.Label { + id: subPixelComboText + text: model.display + } + Image { + id: subPixelComboImage + source: "image://preview/" + model.index + "_" + kcm.fontAASettings.hintingCurrentIndex + ".png" + transform: Scale { + xScale: 1. / QtWindow.Screen.devicePixelRatio; + yScale: 1. / QtWindow.Screen.devicePixelRatio; + } + } + } + } } QtControls.ComboBox { @@ -149,6 +170,26 @@ model: kcm.fontAASettings.hintingOptionsModel textRole: "display" enabled: antiAliasingComboBox.currentIndex == 0 + delegate: QtControls.ItemDelegate { + id: hintingDelegate + width: hintingComboImage.implicitWidth + contentItem: ColumnLayout { + id: hintingLayout + width: hintingComboImage.implicitWidth + QtControls.Label { + id: hintingComboText + text: model.display + } + Image { + id: hintingComboImage + source: "image://preview/" + kcm.fontAASettings.subPixelCurrentIndex + "_" + model.index + ".png" + transform: Scale { + xScale: 1. / QtWindow.Screen.devicePixelRatio; + yScale: 1. / QtWindow.Screen.devicePixelRatio; + } + } + } + } } RowLayout { diff --git a/kcms/fonts/previewimageprovider.h b/kcms/fonts/previewimageprovider.h new file mode 100644 --- /dev/null +++ b/kcms/fonts/previewimageprovider.h @@ -0,0 +1,36 @@ +/* + Copyright (c) 2018 Julian Wolff + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __PREVIEW_IMAGE_PROVIDER_H__ +#define __PREVIEW_IMAGE_PROVIDER_H__ + +#include +#include + +class PreviewImageProvider : public QQuickImageProvider +{ +public: + PreviewImageProvider(const QFont& font); + QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize); + +private: + QFont m_font; +}; + +#endif // __PREVIEW_IMAGE_PROVIDER_H__ diff --git a/kcms/fonts/previewimageprovider.cpp b/kcms/fonts/previewimageprovider.cpp new file mode 100644 --- /dev/null +++ b/kcms/fonts/previewimageprovider.cpp @@ -0,0 +1,84 @@ +/* + Copyright (c) 2018 Julian Wolff + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include + +#include "kxftconfig.h" +#include "previewimageprovider.h" +#include "previewrenderengine.h" + +PreviewImageProvider::PreviewImageProvider(const QFont& font) + : QQuickImageProvider(QQuickImageProvider::Image) + , m_font(font) +{ +} + +QImage PreviewImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize) +{ + int subPixelIndex = 0; + int hintingIndex = 0; + + const auto sections = id.splitRef(QLatin1Char('_')); + + if (sections.size() >= 2) { + subPixelIndex = sections[0].toInt(); + hintingIndex = sections[1].toInt(); + } + + KXftConfig xft; + + + KXftConfig::AntiAliasing::State oldAntialiasing = xft.getAntiAliasing(); + double oldStart,oldEnd; + xft.getExcludeRange(oldStart, oldEnd); + KXftConfig::SubPixel::Type oldSubPixelType; + xft.getSubPixelType(oldSubPixelType); + KXftConfig::Hint::Style oldHintStyle; + xft.getHintStyle(oldHintStyle); + + + xft.setAntiAliasing(KXftConfig::AntiAliasing::Enabled); + xft.setExcludeRange(0, 0); + + KXftConfig::SubPixel::Type subPixelType = (KXftConfig::SubPixel::Type)subPixelIndex; + xft.setSubPixelType(subPixelType); + + KXftConfig::Hint::Style hintStyle = (KXftConfig::Hint::Style)hintingIndex; + xft.setHintStyle(hintStyle); + + xft.apply(); + + + QColor text(QApplication::palette().color(QPalette::Text)); + QColor bgnd(QApplication::palette().color(QPalette::Window)); + + PreviewRenderEngine eng(true); + QImage img = eng.drawAutoSize(m_font, text, bgnd, eng.getDefaultPreviewString()); + + + xft.setAntiAliasing(oldAntialiasing); + xft.setExcludeRange(oldStart, oldEnd); + xft.setSubPixelType(oldSubPixelType); + xft.setHintStyle(oldHintStyle); + + *size = img.size(); + + return img; +} diff --git a/kcms/fonts/previewrenderengine.h b/kcms/fonts/previewrenderengine.h new file mode 100644 --- /dev/null +++ b/kcms/fonts/previewrenderengine.h @@ -0,0 +1,41 @@ +/* + Copyright (c) 2018 Julian Wolff + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __PREVIEW_RENDER_ENGINE_H +#define __PREVIEW_RENDER_ENGINE_H + +#include "kxftconfig.h" +#include "FcEngine.h" + +#ifdef HAVE_FONTCONFIG + +#include + +class PreviewRenderEngine : public KFI::CFcEngine +{ +public: + PreviewRenderEngine(bool init=true); + ~PreviewRenderEngine(); + + QImage drawAutoSize(const QFont &font, const QColor &txt, const QColor &bgnd, const QString &text); +}; + +#endif // HAVE_FONTCONFIG + +#endif // __PREVIEW_RENDER_ENGINE_H diff --git a/kcms/fonts/previewrenderengine.cpp b/kcms/fonts/previewrenderengine.cpp new file mode 100644 --- /dev/null +++ b/kcms/fonts/previewrenderengine.cpp @@ -0,0 +1,139 @@ +/* + Copyright (c) 2018 Julian Wolff + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + + + +#include "kxftconfig.h" +#include "previewrenderengine.h" +#include "Fc.h" + +#include +#include +#include + +#include + +#ifdef HAVE_FONTCONFIG + + +static int qtToFcWeight(int weight) +{ + switch(weight) + { + case 0: + return FC_WEIGHT_THIN; + case QFont::Light>>1: + return FC_WEIGHT_EXTRALIGHT; + case QFont::Light: + return FC_WEIGHT_LIGHT; + default: + case QFont::Normal: + return FC_WEIGHT_REGULAR; + case (QFont::Normal+QFont::DemiBold)>>1: +#ifdef KFI_HAVE_MEDIUM_WEIGHT + return FC_WEIGHT_MEDIUM; +#endif + case QFont::DemiBold: + return FC_WEIGHT_DEMIBOLD; + case QFont::Bold: + return FC_WEIGHT_BOLD; + case (QFont::Bold+QFont::Black)>>1: + return FC_WEIGHT_EXTRABOLD; + case QFont::Black: + return FC_WEIGHT_BLACK; + } +} + +#ifndef KFI_FC_NO_WIDTHS +static int qtToFcWidth(int weight) +{ + switch(weight) + { + case QFont::UltraCondensed: + return KFI_FC_WIDTH_ULTRACONDENSED; + case QFont::ExtraCondensed: + return KFI_FC_WIDTH_EXTRACONDENSED; + case QFont::Condensed: + return KFI_FC_WIDTH_CONDENSED; + case QFont::SemiCondensed: + return KFI_FC_WIDTH_SEMICONDENSED; + default: + case QFont::Unstretched: + return KFI_FC_WIDTH_NORMAL; + case QFont::SemiExpanded: + return KFI_FC_WIDTH_SEMIEXPANDED; + case QFont::Expanded: + return KFI_FC_WIDTH_EXPANDED; + case QFont::ExtraExpanded: + return KFI_FC_WIDTH_EXTRAEXPANDED; + case QFont::UltraExpanded: + return KFI_FC_WIDTH_ULTRAEXPANDED; + } +} +#endif + +static bool qtToFcSlant(int slant) +{ + switch(slant) + { + default: + case QFont::StyleNormal: + return FC_SLANT_ROMAN; + case QFont::StyleItalic: + return FC_SLANT_ITALIC; + case QFont::StyleOblique: + return FC_SLANT_OBLIQUE; + } +} + +static quint32 qtToFcStyle(const QFont &font) +{ + return KFI::FC::createStyleVal( + qtToFcWeight(font.weight()), + qtToFcWidth(font.stretch()), + qtToFcSlant(font.style()) + ); +} + +PreviewRenderEngine::PreviewRenderEngine(bool init) + : CFcEngine(init) +{ + if(init) + FcInitReinitialize(); +} + +PreviewRenderEngine::~PreviewRenderEngine() +{ +} + +QImage PreviewRenderEngine::drawAutoSize(const QFont &font, const QColor &txt, const QColor &bgnd, const QString &text) +{ + const QString& name = font.family(); + const quint32 style = qtToFcStyle(font); + int faceNo = 0; + + double ratio = QApplication::desktop()->screen()->devicePixelRatio(); + double dpi = QX11Info::appDpiY(); + + int fSize((int)(((font.pointSizeF()*dpi*ratio)/72.0)+0.5)); + + return draw(name, style, faceNo, txt, bgnd, fSize, text); +} + +#endif // HAVE_FONTCONFIG diff --git a/kcms/kfontinst/lib/FcEngine.h b/kcms/kfontinst/lib/FcEngine.h --- a/kcms/kfontinst/lib/FcEngine.h +++ b/kcms/kfontinst/lib/FcEngine.h @@ -71,13 +71,14 @@ static CFcEngine * instance(); CFcEngine(bool init=true); - ~CFcEngine(); + virtual ~CFcEngine(); void readConfig(KConfig &cfg); void writeConfig(KConfig &cfg); static void setDirty() { theirFcDirty=true; } QImage drawPreview(const QString &name, quint32 style, int faceNo, const QColor &txt, const QColor &bgnd, int h); + QImage draw(const QString &name, quint32 style, int faceNo, const QColor &txt, const QColor &bgnd, int fSize, const QString &text); QImage draw(const QString &name, quint32 style, int faceNo, const QColor &txt, const QColor &bgnd, int w, int h, bool thumb, const QList &range=QList(), QList *chars=NULL); int getNumIndexes() { return itsIndexCount; } // Only valid after draw has been called! diff --git a/kcms/kfontinst/lib/FcEngine.cpp b/kcms/kfontinst/lib/FcEngine.cpp --- a/kcms/kfontinst/lib/FcEngine.cpp +++ b/kcms/kfontinst/lib/FcEngine.cpp @@ -389,7 +389,7 @@ const FcChar16 *str=(FcChar16 *)(text.utf16()); XftTextExtents16(QX11Info::display(), xftFont, str, text.length(), &extents); - if(y+extents.height0) { @@ -759,6 +759,95 @@ return img; } +QImage CFcEngine::draw(const QString &name, quint32 style, int faceNo, const QColor &txt, const QColor &bgnd, int fSize, const QString &text_) +{ + QImage img; + QString text = text_; + + if(!name.isEmpty() && + ((name==itsName && style==itsStyle) || + parse(name, style, faceNo)) ) + { + + getSizes(); + + if(itsSizes.size()) + { + if(!itsScalable) // Then need to get nearest size... + { + int bSize=0; + + for(int s=0; sinit(needAlpha ? Qt::black : txt, needAlpha ? Qt::white : bgnd, w, h)) + { + bool rv=false; + + if(hasStr(xftFont, text) || hasStr(xftFont, text=text.toUpper()) || + hasStr(xftFont, text=text.toLower())) + { + XGlyphInfo extents; + const FcChar16 *str=(FcChar16 *)(text.utf16()); + + XftTextExtents16(QX11Info::display(), xftFont, str, text.length(), + &extents); + + int x=0, + y=0; + + rv=xft()->drawString(xftFont, text, x, y, h); + } + else + { + int x=0, + y=0; + QRect used; + + rv=xft()->drawAllGlyphs(xftFont, h, x, y, w, h, true, text.length(), &used); + } + + if(rv) + { + img=xft()->toImage(w, h); + if(!img.isNull()) + { + img=img.copy(0, 0, w, h); + + if(needAlpha) + setTransparentBackground(img, txt); + } + } + } + closeFont(xftFont); + } + } + } + + return img; +} + QImage CFcEngine::draw(const QString &name, quint32 style, int faceNo, const QColor &txt, const QColor &bgnd, int w, int h, bool thumb, const QList &range, QList *chars) {