[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[freetype2-demos] gsoc-2022-chariri-3 7532d1a 33/36: [ftinspect] Support
From: |
Werner Lemberg |
Subject: |
[freetype2-demos] gsoc-2022-chariri-3 7532d1a 33/36: [ftinspect] Support color layer font. |
Date: |
Wed, 27 Jul 2022 06:32:46 -0400 (EDT) |
branch: gsoc-2022-chariri-3
commit 7532d1a04f8ceced534629dca8824cb4026ebd75
Author: Charlie Jiang <w@chariri.moe>
Commit: Charlie Jiang <w@chariri.moe>
[ftinspect] Support color layer font.
TODO: After implemented SFNT, allow showing of the palette names.
* src/ftinspect/engine/engine.cpp, src/ftinspect/engine/engine.hpp:
Add fields to hold palettes info and functions to retrieve palette.
Add options about color layer rendering.
Add `tryDirectRenderColorLayers` to perform color layer rendering.
* src/ftinspect/engine/stringrenderer.cpp,
src/ftinspect/engine/stringrenderer.hpp: Support color layered rendering.
* src/ftinspect/rendering/glyphcontinuous.cpp,
src/ftinspect/rendering/glyphcontinuous.hpp: Add a callback to draw
pre-converted images.
* src/ftinspect/engine/paletteinfo.cpp,
src/ftinspect/engine/paletteinfo.hpp: New files. `PaletteInfo` holds
metadata about palettes.
* src/ftinspect/panels/continuous.cpp: Bugfix: Sync settings before calling
renderer to reload all glyphs.
* src/ftinspect/panels/settingpanel.cpp,
src/ftinspect/panels/settingpanel.hpp:
Add "Enable Color Layer" and "Palette" options. Add code populating
palettes from the engine, so rename `checkHinting` to a more general
`onFontChanged`. Minor lifecycle bugfix.
* src/ftinspect/maingui.cpp: Rename `SettingPanel::checkHinting` to
`onFontChanged`.
* src/ftinspect/CMakeLists.txt, src/ftinspect/meson.build: Updated.
---
src/ftinspect/CMakeLists.txt | 1 +
src/ftinspect/engine/engine.cpp | 164 ++++++++++++++++++++++++++++
src/ftinspect/engine/engine.hpp | 28 ++++-
src/ftinspect/engine/paletteinfo.cpp | 27 +++++
src/ftinspect/engine/paletteinfo.hpp | 22 ++++
src/ftinspect/engine/stringrenderer.cpp | 104 ++++++++++--------
src/ftinspect/engine/stringrenderer.hpp | 12 ++
src/ftinspect/maingui.cpp | 2 +-
src/ftinspect/meson.build | 1 +
src/ftinspect/panels/continuous.cpp | 1 +
src/ftinspect/panels/settingpanel.cpp | 79 +++++++++++++-
src/ftinspect/panels/settingpanel.hpp | 9 +-
src/ftinspect/rendering/glyphcontinuous.cpp | 18 +++
src/ftinspect/rendering/glyphcontinuous.hpp | 3 +
14 files changed, 418 insertions(+), 53 deletions(-)
diff --git a/src/ftinspect/CMakeLists.txt b/src/ftinspect/CMakeLists.txt
index e544f7e..aba5c6b 100644
--- a/src/ftinspect/CMakeLists.txt
+++ b/src/ftinspect/CMakeLists.txt
@@ -23,6 +23,7 @@ add_executable(ftinspect
"engine/engine.cpp"
"engine/fontfilemanager.cpp"
"engine/charmap.cpp"
+ "engine/paletteinfo.cpp"
"engine/stringrenderer.cpp"
"rendering/glyphbitmap.cpp"
diff --git a/src/ftinspect/engine/engine.cpp b/src/ftinspect/engine/engine.cpp
index 4ee99d0..2dd882e 100644
--- a/src/ftinspect/engine/engine.cpp
+++ b/src/ftinspect/engine/engine.cpp
@@ -343,6 +343,9 @@ Engine::loadFont(int fontIndex,
ftSize_ = NULL;
curFamilyName_ = QString();
curStyleName_ = QString();
+
+ curCharMaps_.clear();
+ curPaletteInfos_.clear();
}
else
{
@@ -362,6 +365,8 @@ Engine::loadFont(int fontIndex,
curCharMaps_.reserve(face->num_charmaps);
for (int i = 0; i < face->num_charmaps; i++)
curCharMaps_.emplace_back(i, face->charmaps[i]);
+
+ loadPaletteInfos();
}
curNumGlyphs_ = numGlyphs;
@@ -380,6 +385,22 @@ Engine::reloadFont()
}
+void
+Engine::loadPalette()
+{
+ palette_ = NULL;
+ if (paletteData_.num_palettes == 0
+ || paletteIndex_ < 0
+ || paletteData_.num_palettes <= paletteIndex_)
+ return;
+
+ FT_Palette_Select(ftSize_->face,
+ static_cast<FT_UShort>(paletteIndex_),
+ &palette_);
+ // XXX error handling
+}
+
+
void
Engine::removeFont(int fontIndex, bool closeFile)
{
@@ -817,6 +838,24 @@ Engine::queryEngine()
}
+void
+Engine::loadPaletteInfos()
+{
+ curPaletteInfos_.clear();
+
+ if (FT_Palette_Data_Get(ftSize_->face, &paletteData_))
+ {
+ // XXX Error handling
+ paletteData_.num_palettes = 0;
+ return;
+ }
+
+ curPaletteInfos_.reserve(paletteData_.num_palettes);
+ for (int i = 0; i < paletteData_.num_palettes; ++i)
+ curPaletteInfos_.emplace_back(ftSize_->face, paletteData_, i);
+}
+
+
void
convertLCDToARGB(FT_Bitmap& bitmap,
QImage& image,
@@ -978,6 +1017,131 @@ Engine::computeGlyphOffset(FT_Glyph glyph, bool inverseY)
}
+QImage*
+Engine::tryDirectRenderColorLayers(int glyphIndex,
+ QRect* outRect)
+{
+ if (palette_ == NULL
+ || !useColorLayer_
+ || paletteIndex_ >= paletteData_.num_palettes)
+ return NULL;
+
+ FT_LayerIterator iter = {};
+
+ FT_UInt layerGlyphIdx = 0;
+ FT_UInt layerColorIdx = 0;
+
+ bool next = FT_Get_Color_Glyph_Layer(ftSize_->face,
+ glyphIndex,
+ &layerGlyphIdx,
+ &layerColorIdx,
+ &iter);
+ if (!next)
+ return NULL;
+
+ // temporarily change lf
+ auto oldLoadFlags = imageType_.flags;
+ auto loadFlags = oldLoadFlags;
+ loadFlags &= ~FT_LOAD_COLOR;
+ loadFlags |= FT_LOAD_RENDER;
+
+ loadFlags &= ~FT_LOAD_TARGET_(0xF);
+ loadFlags |= FT_LOAD_TARGET_NORMAL;
+ imageType_.flags = loadFlags;
+
+ FT_Bitmap bitmap = {};
+ FT_Bitmap_Init(&bitmap);
+
+ FT_Vector bitmapOffset = {};
+ bool failed = false;
+
+ do
+ {
+ FT_Vector slotOffset;
+ FT_Glyph glyph;
+ if (FTC_ImageCache_Lookup(imageCache_,
+ &imageType_,
+ layerGlyphIdx,
+ &glyph,
+ NULL))
+ {
+ // XXX Error handling
+ failed = true;
+ break;
+ }
+
+ if (glyph->format != FT_GLYPH_FORMAT_BITMAP)
+ continue;
+
+ auto bitmapGlyph = reinterpret_cast<FT_BitmapGlyph>(glyph);
+ slotOffset.x = bitmapGlyph->left << 6;
+ slotOffset.y = bitmapGlyph->top << 6;
+
+ FT_Color color = {};
+
+ if (layerColorIdx == 0xFFFF)
+ {
+ // TODO: FT_Palette_Get_Foreground_Color: #1134
+ if (paletteData_.palette_flags
+ && (paletteData_.palette_flags[paletteIndex_]
+ & FT_PALETTE_FOR_DARK_BACKGROUND))
+ {
+ /* white opaque */
+ color.blue = 0xFF;
+ color.green = 0xFF;
+ color.red = 0xFF;
+ color.alpha = 0xFF;
+ }
+ else
+ {
+ /* black opaque */
+ color.blue = 0x00;
+ color.green = 0x00;
+ color.red = 0x00;
+ color.alpha = 0xFF;
+ }
+ }
+ else if (layerColorIdx < paletteData_.num_palette_entries)
+ color = palette_[layerColorIdx];
+ else
+ continue;
+
+ if (FT_Bitmap_Blend(library_,
+ &bitmapGlyph->bitmap, slotOffset,
+ &bitmap, &bitmapOffset,
+ color))
+ {
+ // XXX error
+ failed = true;
+ break;
+ }
+ } while (FT_Get_Color_Glyph_Layer(ftSize_->face,
+ glyphIndex,
+ &layerGlyphIdx,
+ &layerColorIdx,
+ &iter));
+
+ imageType_.flags = oldLoadFlags;
+ if (failed)
+ {
+ FT_Bitmap_Done(library_, &bitmap);
+ return NULL;
+ }
+
+ auto img = convertBitmapToQImage(&bitmap);
+ if (outRect)
+ {
+ outRect->setSize(img->size());
+ outRect->setLeft(bitmapOffset.x >> 6);
+ outRect->setTop(bitmapOffset.y >> 6);
+ }
+
+ FT_Bitmap_Done(library_, &bitmap);
+
+ return img;
+}
+
+
QHash<FT_Glyph_Format, QString> glyphFormatNamesCache;
QHash<FT_Glyph_Format, QString>&
glyphFormatNames()
diff --git a/src/ftinspect/engine/engine.hpp b/src/ftinspect/engine/engine.hpp
index f4bff2d..a4cf996 100644
--- a/src/ftinspect/engine/engine.hpp
+++ b/src/ftinspect/engine/engine.hpp
@@ -7,6 +7,7 @@
#include "fontfilemanager.hpp"
#include "charmap.hpp"
+#include "paletteinfo.hpp"
#include <vector>
#include <QString>
@@ -19,6 +20,7 @@
#include <freetype/ftoutln.h>
#include <freetype/ftcache.h>
#include <freetype/ftlcdfil.h>
+#include <freetype/ftcolor.h>
// This structure maps the (font, face, instance) index triplet to abstract
@@ -94,9 +96,22 @@ public:
bool inverseRectY);
QPoint computeGlyphOffset(FT_Glyph glyph, bool inverseY);
+ /*
+ * Directly render the glyph at the specified index
+ * to a `QImage`. If you want to perform color-layer
+ * rendering, call this before trying to load the
+ * glyph and do normal rendering, If the returning
+ * value is non-NULL, then there's no need to
+ * load the glyph the normal way, just draw the `QImage`.
+ * Will return NULL if not enabled or color layers not available.
+ */
+ QImage* tryDirectRenderColorLayers(int glyphIndex,
+ QRect* outRect);
+
// reload current triplet, but with updated settings, useful for updating
// `ftSize_` only
- void reloadFont();
+ void reloadFont();
+ void loadPalette();
void openFonts(QStringList fontFileNames);
void removeFont(int fontIndex, bool closeFile = true);
@@ -132,6 +147,7 @@ public:
FT_Vector currentFontKerning(int glyphIndex, int prevIndex);
std::vector<CharMapInfo>& currentFontCharMaps() { return curCharMaps_; }
+ std::vector<PaletteInfo>& currentFontPalettes() { return curPaletteInfos_; }
FontFileManager& fontFileManager() { return fontFileManager_; }
EngineDefaultValues& engineDefaults() { return engineDefaults_; }
bool antiAliasingEnabled() { return antiAliasingEnabled_; }
@@ -164,6 +180,8 @@ public:
void setRenderMode(int mode) { renderMode_ = mode; }
void setAntiAliasingEnabled(bool enabled) { antiAliasingEnabled_ = enabled; }
void setEmbeddedBitmap(bool force) { embeddedBitmap_ = force; }
+ void setUseColorLayer(bool colorLayer) { useColorLayer_ = colorLayer; }
+ void setPaletteIndex(int index) { paletteIndex_ = index; }
void setLCDUsesBGR(bool isBGR) { lcdUsesBGR_ = isBGR; }
void setLCDSubPixelPositioning(bool sp) { lcdSubPixelPositioning_ = sp; }
@@ -191,6 +209,7 @@ private:
QString curStyleName_;
int curNumGlyphs_ = -1;
std::vector<CharMapInfo> curCharMaps_;
+ std::vector<PaletteInfo> curPaletteInfos_;
FT_Library library_;
FTC_Manager cacheManager_;
@@ -199,8 +218,10 @@ private:
FTC_CMapCache cmapCache_;
FTC_ScalerRec scaler_ = {};
- FT_Size ftSize_;
FTC_ImageTypeRec imageType_;
+ FT_Size ftSize_;
+ FT_Palette_Data paletteData_ = {};
+ FT_Color* palette_ = NULL;
EngineDefaultValues engineDefaults_;
@@ -219,6 +240,8 @@ private:
bool doBlueZoneHinting_;
bool showSegments_;
bool embeddedBitmap_;
+ bool useColorLayer_;
+ int paletteIndex_ = -1;
int antiAliasingTarget_;
bool lcdUsesBGR_;
bool lcdSubPixelPositioning_;
@@ -228,6 +251,7 @@ private:
unsigned long loadFlags_;
void queryEngine();
+ void loadPaletteInfos();
public:
diff --git a/src/ftinspect/engine/paletteinfo.cpp
b/src/ftinspect/engine/paletteinfo.cpp
new file mode 100644
index 0000000..a89c894
--- /dev/null
+++ b/src/ftinspect/engine/paletteinfo.cpp
@@ -0,0 +1,27 @@
+// paletteinfo.cpp
+
+// Copyright (C) 2022 by Charlie Jiang.
+
+#include "paletteinfo.hpp"
+
+PaletteInfo::PaletteInfo(FT_Face face,
+ FT_Palette_Data& data,
+ int index)
+: index(index)
+{
+ if (data.palette_name_ids)
+ {
+ auto id = data.palette_name_ids[index];
+ FT_SfntName sname;
+ FT_Get_Sfnt_Name(face, id, &sname);
+ name = "(SFNT no impl)";
+ // TODO: Get SFNT Name: After implemented SFNT names functionality.
+ }
+ else
+ {
+ name = "(unnamed)";
+ }
+}
+
+
+// end of paletteinfo.cpp
diff --git a/src/ftinspect/engine/paletteinfo.hpp
b/src/ftinspect/engine/paletteinfo.hpp
new file mode 100644
index 0000000..980263e
--- /dev/null
+++ b/src/ftinspect/engine/paletteinfo.hpp
@@ -0,0 +1,22 @@
+// paletteinfo.hpp
+
+// Copyright (C) 2022 by Charlie Jiang.
+
+#pragma once
+
+#include <QString>
+
+#include <freetype/freetype.h>
+#include <freetype/ftcolor.h>
+#include <freetype/ftsnames.h>
+
+struct PaletteInfo
+{
+ int index;
+ QString name;
+
+ PaletteInfo(FT_Face face, FT_Palette_Data& data, int index);
+};
+
+
+// end of paletteinfo.hpp
diff --git a/src/ftinspect/engine/stringrenderer.cpp
b/src/ftinspect/engine/stringrenderer.cpp
index c0b8500..8d8adbd 100644
--- a/src/ftinspect/engine/stringrenderer.cpp
+++ b/src/ftinspect/engine/stringrenderer.cpp
@@ -150,6 +150,7 @@ void
StringRenderer::prepareRendering()
{
engine_->reloadFont();
+ engine_->loadPalette();
if (kerningDegree_ != KD_None)
trackingKerning_ = engine_->currentFontTrackingKerning(kerningDegree_);
else
@@ -499,70 +500,83 @@ StringRenderer::renderLine(int x,
if (!ctx.glyph)
continue;
- // copy the glyph because we're doing manipulation
- auto error = FT_Glyph_Copy(ctx.glyph, &image);
- if (error)
- continue;
+ advance = vertical_ ? ctx.vadvance : ctx.hadvance;
- glyphPreprocessCallback_(&image);
+ QRect rect;
+ QImage* colorLayerImage
+ = engine_->tryDirectRenderColorLayers(ctx.glyphIndex, &rect);
- if (image->format != FT_GLYPH_FORMAT_BITMAP)
+ if (colorLayerImage)
{
- if (vertical_)
- error = FT_Glyph_Transform(image, NULL, &ctx.vvector);
-
- if (!error)
- {
- if (matrixEnabled_)
- error = FT_Glyph_Transform(image, &matrix_, &pen);
- else
- error = FT_Glyph_Transform(image, NULL, &pen);
- }
-
- if (error)
- {
- FT_Done_Glyph(image);
- continue;
- }
+ rect.setX(rect.x() + (pen.x >> 6));
+ rect.setY(height - rect.y() - (pen.y >> 6));
+ renderImageCallback_(colorLayerImage, rect);
}
else
{
- auto bitmap = reinterpret_cast<FT_BitmapGlyph>(image);
+ // copy the glyph because we're doing manipulation
+ auto error = FT_Glyph_Copy(ctx.glyph, &image);
+ if (error)
+ continue;
+
+ glyphPreprocessCallback_(&image);
- if (vertical_)
+ if (image->format != FT_GLYPH_FORMAT_BITMAP)
{
- bitmap->left += (ctx.vvector.x + pen.x) >> 6;
- bitmap->top += (ctx.vvector.y + pen.y) >> 6;
+ if (vertical_)
+ error = FT_Glyph_Transform(image, NULL, &ctx.vvector);
+
+ if (!error)
+ {
+ if (matrixEnabled_)
+ error = FT_Glyph_Transform(image, &matrix_, &pen);
+ else
+ error = FT_Glyph_Transform(image, NULL, &pen);
+ }
+
+ if (error)
+ {
+ FT_Done_Glyph(image);
+ continue;
+ }
}
else
{
- bitmap->left += pen.x >> 6;
- bitmap->top += pen.y >> 6;
+ auto bitmap = reinterpret_cast<FT_BitmapGlyph>(image);
+
+ if (vertical_)
+ {
+ bitmap->left += (ctx.vvector.x + pen.x) >> 6;
+ bitmap->top += (ctx.vvector.y + pen.y) >> 6;
+ }
+ else
+ {
+ bitmap->left += pen.x >> 6;
+ bitmap->top += pen.y >> 6;
+ }
}
- }
- advance = vertical_ ? ctx.vadvance : ctx.hadvance;
+ if (matrixEnabled_)
+ FT_Vector_Transform(&advance, &matrix_);
- if (matrixEnabled_)
- FT_Vector_Transform(&advance, &matrix_);
+ FT_Glyph_Get_CBox(image, FT_GLYPH_BBOX_PIXELS, &bbox);
- FT_Glyph_Get_CBox(image, FT_GLYPH_BBOX_PIXELS, &bbox);
+ // check bounding box; if it is completely outside the
+ // display surface, we don't need to render it
+ if (bbox.xMax >= 0
+ && bbox.yMax >= 0
+ && bbox.xMin <= width
+ && bbox.yMin <= height)
+ {
+ FT_Vector penPos = { (pen.x >> 6), height - (pen.y >> 6) };
+ renderCallback_(image, penPos);
+ }
- // check bounding box; if it is completely outside the
- // display surface, we don't need to render it
- if (bbox.xMax >= 0
- && bbox.yMax >= 0
- && bbox.xMin <= width
- && bbox.yMin <= height)
- {
- FT_Vector penPos = { (pen.x >> 6), height - (pen.y >> 6) };
- renderCallback_(image, penPos);
+ FT_Done_Glyph(image);
}
-
+
pen.x += advance.x;
pen.y += advance.y;
-
- FT_Done_Glyph(image);
}
return offset + totalCount;
diff --git a/src/ftinspect/engine/stringrenderer.hpp
b/src/ftinspect/engine/stringrenderer.hpp
index 1e9585b..610b341 100644
--- a/src/ftinspect/engine/stringrenderer.hpp
+++ b/src/ftinspect/engine/stringrenderer.hpp
@@ -62,6 +62,12 @@ public:
* position.
*/
using RenderCallback = std::function<void(FT_Glyph, FT_Vector)>;
+ /*
+ * For color layered fonts, this will direct render the QImage for you.
+ * TODO: Remove `RenderCallback` and do QImage creation in this class?
+ * The receiver is responsible for deleteing the QImage.
+ */
+ using RenderImageCallback = std::function<void(QImage*, QRect)>;
/*
* The glyph pointer may be replaced. In that case, ownership is transfered
* to the renderer, and the new glyph will be eventually freed by
@@ -90,6 +96,11 @@ public:
renderCallback_ = std::move(cb);
}
void
+ setImageCallback(RenderImageCallback cb)
+ {
+ renderImageCallback_ = std::move(cb);
+ }
+ void
setPreprocessCallback(PreprocessCallback cb)
{
glyphPreprocessCallback_ = std::move(cb);
@@ -173,6 +184,7 @@ private:
bool matrixEnabled_ = false;
RenderCallback renderCallback_;
+ RenderImageCallback renderImageCallback_;
PreprocessCallback glyphPreprocessCallback_;
LineBeginCallback lineBeginCallback_;
diff --git a/src/ftinspect/maingui.cpp b/src/ftinspect/maingui.cpp
index add58e4..93acecf 100644
--- a/src/ftinspect/maingui.cpp
+++ b/src/ftinspect/maingui.cpp
@@ -148,7 +148,7 @@ void
MainGUI::onTripletChanged()
{
auto state = settingPanel_->blockSignals(true);
- settingPanel_->checkHinting();
+ settingPanel_->onFontChanged();
settingPanel_->blockSignals(state);
reloadCurrentTabFont();
}
diff --git a/src/ftinspect/meson.build b/src/ftinspect/meson.build
index ed9a328..cb6efbc 100644
--- a/src/ftinspect/meson.build
+++ b/src/ftinspect/meson.build
@@ -23,6 +23,7 @@ if qt5_dep.found()
'engine/engine.cpp',
'engine/fontfilemanager.cpp',
'engine/charmap.cpp',
+ 'engine/paletteinfo.cpp',
'engine/stringrenderer.cpp',
'rendering/glyphbitmap.cpp',
diff --git a/src/ftinspect/panels/continuous.cpp
b/src/ftinspect/panels/continuous.cpp
index 0ccaf7f..be80c57 100644
--- a/src/ftinspect/panels/continuous.cpp
+++ b/src/ftinspect/panels/continuous.cpp
@@ -230,6 +230,7 @@ ContinuousTab::charMapChanged()
}
updateLimitIndex();
+ syncSettings();
canvas_->stringRenderer().reloadAll();
repaintGlyph();
lastCharMapIndex_ = newIndex;
diff --git a/src/ftinspect/panels/settingpanel.cpp
b/src/ftinspect/panels/settingpanel.cpp
index 6eeec70..499bd58 100644
--- a/src/ftinspect/panels/settingpanel.cpp
+++ b/src/ftinspect/panels/settingpanel.cpp
@@ -25,14 +25,14 @@ SettingPanel::antiAliasingModeIndex()
void
SettingPanel::checkAllSettings()
{
- checkHinting();
+ onFontChanged();
checkAutoHinting();
checkAntiAliasing();
}
void
-SettingPanel::checkHinting()
+SettingPanel::onFontChanged()
{
if (hintingCheckBox_->isChecked())
{
@@ -76,6 +76,48 @@ SettingPanel::checkHinting()
emit repaintNeeded();
}
+
+ populatePalettes();
+}
+
+
+void
+SettingPanel::populatePalettes()
+{
+ auto needToReload = false;
+ auto& newPalettes = engine_->currentFontPalettes();
+ if (newPalettes.size() != paletteComboBox_->count())
+ needToReload = true;
+ else
+ for (int i = 0; i < newPalettes.size(); ++i)
+ {
+ auto oldNameVariant = paletteComboBox_->itemData(i);
+ if (!oldNameVariant.canConvert<QString>())
+ {
+ needToReload = true;
+ break;
+ }
+ if (oldNameVariant.toString() != newPalettes[i].name)
+ {
+ needToReload = true;
+ break;
+ }
+ }
+ if (!needToReload)
+ return;
+
+ {
+ QSignalBlocker blocker(paletteComboBox_);
+ paletteComboBox_->clear();
+ for (int i = 0; i < newPalettes.size(); ++i)
+ paletteComboBox_->addItem(
+ QString("%1: %2")
+ .arg(i)
+ .arg(newPalettes[i].name),
+ newPalettes[i].name);
+ }
+
+ emit fontReloadNeeded();
}
@@ -166,6 +208,14 @@ SettingPanel::checkAntiAliasing()
}
+void
+SettingPanel::checkPalette()
+{
+ paletteComboBox_->setEnabled(colorLayerCheckBox_->isChecked());
+ emit repaintNeeded();
+}
+
+
void
SettingPanel::syncSettings()
{
@@ -190,6 +240,9 @@ SettingPanel::syncSettings()
engine_->setGamma(gammaSlider_->value());
engine_->setEmbeddedBitmap(embeddedBitmapCheckBox_->isChecked());
+ engine_->setPaletteIndex(paletteComboBox_->currentIndex());
+
+ engine_->setUseColorLayer(colorLayerCheckBox_->isChecked());
engine_->setLCDUsesBGR(aaSettings.isBGR);
engine_->setLCDSubPixelPositioning(
antiAliasingComboBox_->currentIndex()
@@ -210,12 +263,15 @@ SettingPanel::createConnections()
connect(lcdFilterComboBox_,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &SettingPanel::repaintNeeded);
+ connect(paletteComboBox_,
+ QOverload<int>::of(&QComboBox::currentIndexChanged), this,
+ &SettingPanel::repaintNeeded);
connect(gammaSlider_, &QSlider::valueChanged,
this, &SettingPanel::repaintNeeded);
connect(hintingCheckBox_, &QCheckBox::clicked,
- this, &SettingPanel::checkHinting);
+ this, &SettingPanel::onFontChanged);
connect(horizontalHintingCheckBox_, &QCheckBox::clicked,
this, &SettingPanel::repaintNeeded);
@@ -230,6 +286,8 @@ SettingPanel::createConnections()
this, &SettingPanel::checkAutoHinting);
connect(embeddedBitmapCheckBox_, &QCheckBox::clicked,
this, &SettingPanel::fontReloadNeeded);
+ connect(colorLayerCheckBox_, &QCheckBox::clicked,
+ this, &SettingPanel::checkPalette);
}
@@ -252,6 +310,7 @@ SettingPanel::createLayout()
blueZoneHintingCheckBox_ = new QCheckBox(tr("Blue-Zone Hinting"), this);
segmentDrawingCheckBox_ = new QCheckBox(tr("Segment Drawing"), this);
embeddedBitmapCheckBox_ = new QCheckBox(tr("Enable Embedded Bitmap"), this);
+ colorLayerCheckBox_ = new QCheckBox(tr("Enable Color Layer"), this);
antiAliasingLabel_ = new QLabel(tr("Anti-Aliasing"), this);
antiAliasingLabel_->setAlignment(Qt::AlignRight);
@@ -261,7 +320,7 @@ SettingPanel::createLayout()
antiAliasingComboBox_->setModel(antiAliasingComboBoxModel_);
antiAliasingLabel_->setBuddy(antiAliasingComboBox_);
- lcdFilterLabel_ = new QLabel(tr("LCD Filter"));
+ lcdFilterLabel_ = new QLabel(tr("LCD Filter"), this);
lcdFilterLabel_->setAlignment(Qt::AlignRight);
lcdFilterComboboxModel_ = new LCDFilterComboBoxModel(this);
@@ -269,6 +328,11 @@ SettingPanel::createLayout()
lcdFilterComboBox_->setModel(lcdFilterComboboxModel_);
lcdFilterLabel_->setBuddy(lcdFilterComboBox_);
+ paletteLabel_ = new QLabel(tr("Palette: "), this);
+
+ paletteComboBox_ = new QComboBox(this);
+ paletteLabel_->setBuddy(paletteComboBox_);
+
int width;
// make all labels have the same width
width = hintingModeLabel_->minimumSizeHint().width();
@@ -327,6 +391,10 @@ SettingPanel::createLayout()
gammaLayout_->addWidget(gammaLabel_);
gammaLayout_->addWidget(gammaSlider_);
+ paletteLayout_ = new QHBoxLayout;
+ paletteLayout_->addWidget(paletteLabel_);
+ paletteLayout_->addWidget(paletteComboBox_);
+
generalTabLayout_ = new QVBoxLayout;
generalTabLayout_->addWidget(hintingCheckBox_);
generalTabLayout_->addLayout(hintingModeLayout_);
@@ -343,6 +411,8 @@ SettingPanel::createLayout()
generalTabLayout_->addStretch(1);
generalTabLayout_->addLayout(gammaLayout_);
generalTabLayout_->addWidget(embeddedBitmapCheckBox_);
+ generalTabLayout_->addWidget(colorLayerCheckBox_);
+ generalTabLayout_->addLayout(paletteLayout_);
generalTabLayout_->addSpacing(20); // XXX px
generalTabLayout_->addStretch(1);
@@ -393,6 +463,7 @@ SettingPanel::setDefaults()
verticalHintingCheckBox_->setChecked(true);
blueZoneHintingCheckBox_->setChecked(true);
embeddedBitmapCheckBox_->setChecked(false);
+ colorLayerCheckBox_->setChecked(true);
gammaSlider_->setValue(18); // 1.8
}
diff --git a/src/ftinspect/panels/settingpanel.hpp
b/src/ftinspect/panels/settingpanel.hpp
index 9724bde..17a7122 100644
--- a/src/ftinspect/panels/settingpanel.hpp
+++ b/src/ftinspect/panels/settingpanel.hpp
@@ -36,10 +36,11 @@ signals:
public slots:
void checkAllSettings();
- void checkHinting();
+ void onFontChanged();
void checkHintingMode();
void checkAutoHinting();
void checkAntiAliasing();
+ void checkPalette();
private:
Engine* engine_;
@@ -56,6 +57,7 @@ private:
QLabel* antiAliasingLabel_;
QLabel* hintingModeLabel_;
QLabel* lcdFilterLabel_;
+ QLabel* paletteLabel_;
QCheckBox* hintingCheckBox_;
QCheckBox* horizontalHintingCheckBox_;
@@ -64,6 +66,7 @@ private:
QCheckBox* segmentDrawingCheckBox_;
QCheckBox* autoHintingCheckBox_;
QCheckBox* embeddedBitmapCheckBox_;
+ QCheckBox* colorLayerCheckBox_;
AntiAliasingComboBoxModel* antiAliasingComboBoxModel_;
HintingModeComboBoxModel* hintingModeComboBoxModel_;
@@ -72,6 +75,7 @@ private:
QComboBox* hintingModeComboBox_;
QComboBox* antiAliasingComboBox_;
QComboBox* lcdFilterComboBox_;
+ QComboBox* paletteComboBox_;
QSlider* gammaSlider_;
@@ -84,6 +88,7 @@ private:
QHBoxLayout* antiAliasingLayout_;
QHBoxLayout* lcdFilterLayout_;
QHBoxLayout* gammaLayout_;
+ QHBoxLayout* paletteLayout_;
QVBoxLayout* generalTabLayout_;
@@ -92,6 +97,8 @@ private:
void createConnections();
void createLayout();
void setDefaults();
+
+ void populatePalettes();
};
diff --git a/src/ftinspect/rendering/glyphcontinuous.cpp
b/src/ftinspect/rendering/glyphcontinuous.cpp
index 0d7f63b..9497bec 100644
--- a/src/ftinspect/rendering/glyphcontinuous.cpp
+++ b/src/ftinspect/rendering/glyphcontinuous.cpp
@@ -101,6 +101,11 @@ GlyphContinuous::paintByRenderer(QPainter* painter)
{
drawSingleGlyph(painter, glyph, penPos);
});
+ stringRenderer_.setImageCallback(
+ [&](QImage* image, QRect pos)
+ {
+ drawSingleGlyphImage(painter, image, pos);
+ });
stringRenderer_.setPreprocessCallback(
[&](FT_Glyph* ptr)
{
@@ -285,4 +290,17 @@ GlyphContinuous::drawSingleGlyph(QPainter* painter,
}
+void
+GlyphContinuous::drawSingleGlyphImage(QPainter* painter,
+ QImage* image,
+ QRect pos)
+{
+ // TODO red square?
+
+ pos.setLeft(pos.left() + sizeIndicatorOffset_);
+ painter->drawImage(pos, *image);
+ delete image;
+}
+
+
// end of glyphcontinuous.cpp
diff --git a/src/ftinspect/rendering/glyphcontinuous.hpp
b/src/ftinspect/rendering/glyphcontinuous.hpp
index 9260b50..109d022 100644
--- a/src/ftinspect/rendering/glyphcontinuous.hpp
+++ b/src/ftinspect/rendering/glyphcontinuous.hpp
@@ -103,6 +103,9 @@ private:
void drawSingleGlyph(QPainter* painter,
FT_Glyph glyph,
FT_Vector penPos);
+ void drawSingleGlyphImage(QPainter* painter,
+ QImage* image,
+ QRect pos);
};
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [freetype2-demos] gsoc-2022-chariri-3 7532d1a 33/36: [ftinspect] Support color layer font.,
Werner Lemberg <=