always render glyphs as mono

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2021-12-25 12:46:35 +02:00
parent f6204c0552
commit 7b68bf1f8f
7 changed files with 71 additions and 414 deletions

View file

@ -988,7 +988,6 @@ void qt_init(QApplicationPrivate *priv, Display *display,
#if !defined(QT_NO_FONTCONFIG)
if (qgetenv("QT_X11_NO_FONTCONFIG").isNull())
qt_x11Data->has_fontconfig = FcInit();
qt_x11Data->fc_antialias = true;
#endif
#ifndef QT_NO_XRENDER
@ -1226,58 +1225,6 @@ void qt_init(QApplicationPrivate *priv, Display *display,
QX11Info::setAppDpiY(s, dpi);
}
}
for (int s = 0; s < ScreenCount(qt_x11Data->display); ++s) {
int subpixel = FC_RGBA_UNKNOWN;
#if !defined(QT_NO_XRENDER) && (RENDER_MAJOR > 0 || RENDER_MINOR >= 6)
if (qt_x11Data->use_xrender) {
int rsp = XRenderQuerySubpixelOrder(qt_x11Data->display, s);
switch (rsp) {
case SubPixelHorizontalRGB:
subpixel = FC_RGBA_RGB;
break;
case SubPixelHorizontalBGR:
subpixel = FC_RGBA_BGR;
break;
case SubPixelVerticalRGB:
subpixel = FC_RGBA_VRGB;
break;
case SubPixelVerticalBGR:
subpixel = FC_RGBA_VBGR;
break;
case SubPixelNone:
subpixel = FC_RGBA_NONE;
break;
case SubPixelUnknown:
default:
subpixel = FC_RGBA_UNKNOWN;
break;
}
}
#endif // QT_NO_XRENDER
char *rgba = XGetDefault(qt_x11Data->display, "Xft", FC_RGBA);
if (rgba) {
char *end = 0;
int v = strtol(rgba, &end, 0);
if (rgba != end) {
subpixel = v;
} else if (qstrncmp(rgba, "unknown", 7) == 0) {
subpixel = FC_RGBA_UNKNOWN;
} else if (qstrncmp(rgba, "rgb", 3) == 0) {
subpixel = FC_RGBA_RGB;
} else if (qstrncmp(rgba, "bgr", 3) == 0) {
subpixel = FC_RGBA_BGR;
} else if (qstrncmp(rgba, "vrgb", 4) == 0) {
subpixel = FC_RGBA_VRGB;
} else if (qstrncmp(rgba, "vbgr", 4) == 0) {
subpixel = FC_RGBA_VBGR;
} else if (qstrncmp(rgba, "none", 4) == 0) {
subpixel = FC_RGBA_NONE;
}
}
qt_x11Data->screens[s].subpixel = subpixel;
}
getXDefault("Xft", FC_ANTIALIAS, &qt_x11Data->fc_antialias);
#ifdef FC_HINT_STYLE
qt_x11Data->fc_hint_style = -1;
getXDefault("Xft", FC_HINT_STYLE, &qt_x11Data->fc_hint_style);

View file

@ -115,7 +115,6 @@ struct QX11InfoData {
Visual *visual;
bool defaultColormap;
bool defaultVisual;
int subpixel;
};
class QDrag;
@ -265,7 +264,6 @@ struct QX11Data
static void copyXImageToQImageWithMask(XImage *ximage, QImage &image, const QImage &mask);
bool has_fontconfig;
bool fc_antialias;
int fc_hint_style;
char *startupId;

View file

@ -35,6 +35,8 @@
QT_BEGIN_NAMESPACE
static const QVector<QRgb> qt_alphamapcolortable = { qt_transparentrgba, qt_blackrgba };
// Harfbuzz helper functions
static HB_Bool hb_stringToGlyphs(HB_Font font, const HB_UChar16 *string, hb_uint32 length, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool rightToLeft)
@ -499,33 +501,12 @@ void QFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int n
const int w = alphaMask.width();
const int h = alphaMask.height();
const int srcBpl = alphaMask.bytesPerLine();
QImage bitmap;
if (alphaMask.depth() == 1) {
bitmap = alphaMask;
} else {
bitmap = QImage(w, h, QImage::Format_Mono);
const uchar *imageData = alphaMask.bits();
const int destBpl = bitmap.bytesPerLine();
uchar *bitmapData = bitmap.bits();
for (int yi = 0; yi < h; ++yi) {
const uchar *src = imageData + yi*srcBpl;
uchar *dst = bitmapData + yi*destBpl;
for (int xi = 0; xi < w; ++xi) {
const int byte = xi / 8;
const int bit = xi % 8;
if (bit == 0)
dst[byte] = 0;
if (src[xi])
dst[byte] |= 128 >> bit;
}
}
}
const uchar *bitmap_data = bitmap.bits();
Q_ASSERT(alphaMask.depth() == 1);
const uchar *bitmap_data = alphaMask.constBits();
QFixedPoint offset = g.offsets[i];
advanceX += offset.x;
advanceY += offset.y;
qt_addBitmapToPath((advanceX + metrics.x).toReal(), (advanceY + metrics.y).toReal(), bitmap_data, bitmap.bytesPerLine(), w, h, path);
qt_addBitmapToPath((advanceX + metrics.x).toReal(), (advanceY + metrics.y).toReal(), bitmap_data, srcBpl, w, h, path);
advanceX += g.advances_x[i];
advanceY += g.advances_y[i];
}
@ -541,31 +522,10 @@ QImage QFontEngine::alphaMapForGlyph(glyph_t glyph)
if (glyph_width <= 0 || glyph_height <= 0)
return QImage();
QFixedPoint pt;
pt.x = -glyph_x;
pt.y = -glyph_y; // the baseline
QPainterPath path;
QImage im(glyph_width + 4, glyph_height, QImage::Format_ARGB32_Premultiplied);
im.fill(Qt::transparent);
QPainter p(&im);
addGlyphsToPath(&glyph, &pt, 1, &path, 0);
p.setPen(Qt::NoPen);
p.setBrush(Qt::black);
p.drawPath(path);
p.end();
QImage indexed(im.width(), im.height(), QImage::Format_ARGB32);
const int bpl = indexed.bytesPerLine();
uchar *dest = indexed.bits();
for (int y=0; y<im.height(); ++y) {
uchar *line = QFAST_SCAN_LINE(dest, bpl, y);
const uint *src = reinterpret_cast<const uint*>(im.constScanLine(y));
for (int x=0; x<im.width(); ++x)
line[x] = qAlpha(src[x]);
}
return indexed;
QImage im(glyph_width, glyph_height, QImage::Format_Mono);
im.fill(0);
im.setColorTable(qt_alphamapcolortable);
return im;
}
QFontEngine::Properties QFontEngine::properties() const
@ -858,14 +818,15 @@ QFontEngine::Type QFontEngineBox::type() const
QImage QFontEngineBox::alphaMapForGlyph(glyph_t)
{
QImage image(_size, _size, QImage::Format_ARGB32);
image.fill(Qt::transparent);
QImage image(_size, _size, QImage::Format_Mono);
image.fill(0);
image.setColorTable(qt_alphamapcolortable);
for (int i=2; i <= _size-3; ++i) {
image.setPixel(i, 2, qt_whitergba);
image.setPixel(i, _size-3, qt_whitergba);
image.setPixel(2, i, qt_whitergba);
image.setPixel(_size-3, i, qt_whitergba);
image.setPixel(i, 2, qt_blackrgba);
image.setPixel(i, _size-3, qt_blackrgba);
image.setPixel(2, i, qt_blackrgba);
image.setPixel(_size-3, i, qt_blackrgba);
}
return image;
}

View file

@ -178,11 +178,10 @@ HB_Error QFreetypeFace::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 p
return HB_Err_Ok;
}
void QFreetypeFace::computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing)
void QFreetypeFace::computeSize(const QFontDef &fontDef, int *xsize, int *ysize)
{
*ysize = qRound(fontDef.pixelSize * 64);
*xsize = *ysize * fontDef.stretch / 100;
*outline_drawing = false;
/*
* Bitmap only faces must match exactly, so find the closest
@ -215,8 +214,6 @@ void QFreetypeFace::computeSize(const QFontDef &fontDef, int *xsize, int *ysize,
if (err)
*xsize = *ysize = 0;
}
} else {
*outline_drawing = (*xsize > (QT_MAX_CACHED_GLYPH_SIZE<<6) || *ysize > (QT_MAX_CACHED_GLYPH_SIZE<<6));
}
}
@ -371,62 +368,6 @@ QFontEngineFT::Glyph::~Glyph()
delete [] data;
}
static const uint subpixel_filter[3][3] = {
{ 180, 60, 16 },
{ 38, 180, 38 },
{ 16, 60, 180 }
};
static inline uint filterPixel(uint red, uint green, uint blue, bool legacyFilter)
{
uint res;
if (legacyFilter) {
uint high = (red*subpixel_filter[0][0] + green*subpixel_filter[0][1] + blue*subpixel_filter[0][2]) >> 8;
uint mid = (red*subpixel_filter[1][0] + green*subpixel_filter[1][1] + blue*subpixel_filter[1][2]) >> 8;
uint low = (red*subpixel_filter[2][0] + green*subpixel_filter[2][1] + blue*subpixel_filter[2][2]) >> 8;
res = (mid << 24) + (high << 16) + (mid << 8) + low;
} else {
uint alpha = green;
res = (alpha << 24) + (red << 16) + (green << 8) + blue;
}
return res;
}
static void convertRGBToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter)
{
int h = height;
const int offs = bgr ? -1 : 1;
const int w = width * 3;
while (h--) {
uint *dd = dst;
for (int x = 0; x < w; x += 3) {
uint red = src[x+1-offs];
uint green = src[x+1];
uint blue = src[x+1+offs];
*dd = filterPixel(red, green, blue, legacyFilter);
++dd;
}
dst += width;
src += src_pitch;
}
}
static void convertRGBToARGB_V(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter)
{
int h = height;
const int offs = bgr ? -src_pitch : src_pitch;
while (h--) {
for (int x = 0; x < width; x++) {
uint red = src[x+src_pitch-offs];
uint green = src[x+src_pitch];
uint blue = src[x+src_pitch+offs];
dst[x] = filterPixel(red, green, blue, legacyFilter);
}
dst += width;
src += 3*src_pitch;
}
}
QFontEngineFT::QFontEngineFT(const QFontDef &fd)
{
fontDef = fd;
@ -440,17 +381,6 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd)
freetype = 0;
default_load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
default_hint_style = HintNone;
subpixelType = Subpixel_None;
#if defined(FT_LCD_FILTER_H)
lcdFilterType = (int)((quintptr) FT_LCD_FILTER_DEFAULT);
antialias = true;
defaultFormat = Format_A32;
#else
antialias = false;
defaultFormat = Format_Mono;
lcdFilterType = 0;
#endif
embeddedbitmap = false;
}
QFontEngineFT::~QFontEngineFT()
@ -458,7 +388,7 @@ QFontEngineFT::~QFontEngineFT()
delete freetype;
}
bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format)
bool QFontEngineFT::init(FaceId faceId)
{
freetype = new QFreetypeFace(faceId);
if (!freetype->face) {
@ -466,10 +396,6 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format)
ysize = 0;
return false;
}
#if defined(FT_LCD_FILTER_H)
defaultFormat = format;
this->antialias = antialias;
#endif
face_id = faceId;
@ -481,7 +407,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format)
}
lbearing = rbearing = SHRT_MIN;
freetype->computeSize(fontDef, &xsize, &ysize, &defaultGlyphSet.outline_drawing);
freetype->computeSize(fontDef, &xsize, &ysize);
FT_Face face = getFace();
@ -523,63 +449,33 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format)
return true;
}
int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags,
bool &hsubpixel, int &vfactor) const
int QFontEngineFT::loadFlags(QGlyphSet *set, int flags) const
{
int load_flags = FT_LOAD_DEFAULT | default_load_flags;
int load_target = default_hint_style == HintLight
? FT_LOAD_TARGET_LIGHT
: FT_LOAD_TARGET_NORMAL;
if (format == Format_None) {
format = defaultFormat;
}
if (format == Format_Mono) {
load_target = FT_LOAD_TARGET_MONO;
} else if (format == Format_A32) {
if (subpixelType == QFontEngineFT::Subpixel_RGB || subpixelType == QFontEngineFT::Subpixel_BGR) {
if (default_hint_style == HintFull)
load_target = FT_LOAD_TARGET_LCD;
hsubpixel = true;
} else if (subpixelType == QFontEngineFT::Subpixel_VRGB || subpixelType == QFontEngineFT::Subpixel_VBGR) {
if (default_hint_style == HintFull)
load_target = FT_LOAD_TARGET_LCD_V;
vfactor = 3;
}
}
if (set && set->outline_drawing)
load_flags = FT_LOAD_NO_BITMAP;
if (default_hint_style == HintNone || (flags & HB_ShaperFlag_UseDesignMetrics) || (set && set->outline_drawing))
if (default_hint_style == HintNone || (flags & HB_ShaperFlag_UseDesignMetrics)) {
load_flags |= FT_LOAD_NO_HINTING;
else
load_flags |= load_target;
} else if (default_hint_style == HintLight) {
load_flags |= FT_LOAD_TARGET_LIGHT;
} else if (default_hint_style == HintMedium) {
load_flags |= FT_LOAD_TARGET_LCD;
} else if (default_hint_style == HintFull) {
load_flags |= FT_LOAD_TARGET_LCD_V;
} else {
load_flags |= FT_LOAD_TARGET_MONO;
}
return load_flags;
}
QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(glyph_t glyph,
GlyphFormat format,
bool fetchMetricsOnly) const
QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(glyph_t glyph, bool fetchMetricsOnly) const
{
if (format == Format_None) {
format = defaultFormat;
}
Glyph *g = defaultGlyphSet.getGlyph(glyph);
if (g && g->format == format) {
if (g) {
return g;
}
Q_ASSERT(format != Format_None);
bool hsubpixel = false;
int vfactor = 1;
int load_flags = loadFlags(&defaultGlyphSet, format, 0, hsubpixel, vfactor);
if (format != Format_Mono && !embeddedbitmap)
load_flags |= FT_LOAD_NO_BITMAP;
int load_flags = loadFlags(&defaultGlyphSet, 0);
FT_Matrix matrix = freetype->matrix;
bool transform = matrix.xx != 0x10000
@ -587,8 +483,9 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(glyph_t glyph,
|| matrix.xy != 0
|| matrix.yx != 0;
if (transform)
if (transform) {
load_flags |= FT_LOAD_NO_BITMAP;
}
FT_Face face = freetype->face;
@ -604,45 +501,26 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(glyph_t glyph,
load_flags |= FT_LOAD_FORCE_AUTOHINT;
err = FT_Load_Glyph(face, glyph, load_flags);
}
if (err != FT_Err_Ok)
if (err != FT_Err_Ok) {
qWarning("load glyph failed err=%x face=%p, glyph=%d", err, face, glyph);
}
if (defaultGlyphSet.outline_drawing && fetchMetricsOnly)
if (fetchMetricsOnly) {
return 0;
}
FT_GlyphSlot slot = face->glyph;
if (embolden) FT_GlyphSlot_Embolden(slot);
FT_Library library = freetype->library;
FT_Render_Mode rendermode = FT_RENDER_MODE_MONO;
#if defined(FT_LCD_FILTER_H)
if (antialias || hsubpixel) {
rendermode = FT_RENDER_MODE_LCD;
} else if (vfactor != 1) {
rendermode = FT_RENDER_MODE_LCD_V;
}
if (slot->format == FT_GLYPH_FORMAT_OUTLINE && (hsubpixel || vfactor != 1)) {
err = FT_Library_SetLcdFilter(library, (FT_LcdFilter)lcdFilterType);
}
if (err != FT_Err_Ok) {
qWarning("setting render filter failed err=%x face=%p, glyph=%d", err, face, glyph);
}
#endif
err = FT_Render_Glyph(slot, rendermode);
err = FT_Render_Glyph(slot, FT_RENDER_MODE_MONO);
if (err != FT_Err_Ok) {
qWarning("render glyph failed err=%x face=%p, glyph=%d", err, face, glyph);
}
#if defined(FT_LCD_FILTER_H)
FT_Library_SetLcdFilter(library, FT_LCD_FILTER_NONE);
#endif
const unsigned short gheight = slot->bitmap.rows;
const unsigned short gwidth = slot->bitmap.width;
const unsigned short gheight = slot->bitmap.rows / vfactor;
const unsigned short gwidth = ((rendermode == FT_RENDER_MODE_MONO) ? slot->bitmap.width : (slot->bitmap.width / 3));
const int glyph_buffer_size = (rendermode == FT_RENDER_MODE_MONO ? (gwidth * gheight) : (gwidth * gheight * 4));
const int glyph_buffer_size = (gwidth * gheight);
if (!glyph_buffer_size) {
// e.g. 3 or 2798
// qWarning("glyph size is zero face=%p, glyph=%d", face, glyph);
@ -651,39 +529,17 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(glyph_t glyph,
Q_ASSERT(glyph_buffer_size >= 1);
uchar *glyph_buffer = new uchar[glyph_buffer_size];
bool useLegacyLcdFilter = false;
#if defined(FT_LCD_FILTER_H)
useLegacyLcdFilter = (lcdFilterType == FT_LCD_FILTER_LEGACY);
#endif
#if defined(FT_LCD_FILTER_H)
if (rendermode == FT_RENDER_MODE_LCD) {
Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_LCD);
convertRGBToARGB(slot->bitmap.buffer, (uint *)glyph_buffer, gwidth, gheight, slot->bitmap.pitch, subpixelType != QFontEngineFT::Subpixel_RGB, useLegacyLcdFilter);
} else if (rendermode == FT_RENDER_MODE_LCD_V) {
Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V);
convertRGBToARGB_V(slot->bitmap.buffer, (uint *)glyph_buffer, gwidth, gheight, slot->bitmap.pitch, subpixelType != QFontEngineFT::Subpixel_VRGB, useLegacyLcdFilter);
} else
#endif
{
Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO);
const int bytes = ((((gwidth + 7) & ~7) >> 3) * slot->bitmap.rows);
::memcpy(glyph_buffer, slot->bitmap.buffer, bytes);
}
if (!g) {
g = new Glyph;
g->data = 0;
}
Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO);
const int bytes = ((((gwidth + 7) & ~7) >> 3) * slot->bitmap.rows);
::memcpy(glyph_buffer, slot->bitmap.buffer, bytes);
g = new Glyph;
g->linearAdvance = slot->linearHoriAdvance >> 10;
g->width = gwidth;
g->height = gheight;
g->x = slot->bitmap_left;
g->y = slot->bitmap_top;
g->advance = TRUNC(ROUND(slot->advance.x));
g->format = format;
delete [] g->data;
g->data = glyph_buffer;
defaultGlyphSet.setGlyph(glyph, g);
@ -903,42 +759,21 @@ bool QFontEngineFT::canRender(const QChar *string, int len)
return true;
}
void QFontEngineFT::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
{
if (!glyphs.numGlyphs)
return;
if (FT_IS_SCALABLE(freetype->face)) {
QFontEngine::addOutlineToPath(x, y, glyphs, path, flags);
} else {
QVarLengthArray<QFixedPoint> positions;
QVarLengthArray<glyph_t> positioned_glyphs;
const QTransform matrix = QTransform::fromTranslate(x, y);
getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions);
FT_Face face = getFace(Unscaled);
for (int gl = 0; gl < glyphs.numGlyphs; gl++) {
FT_UInt glyph = positioned_glyphs[gl];
FT_Load_Glyph(face, glyph, FT_LOAD_TARGET_MONO);
freetype->addBitmapToPath(face->glyph, positions[gl], path);
}
}
}
void QFontEngineFT::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs,
QPainterPath *path, QTextItem::RenderFlags)
{
FT_Face face = getFace(Unscaled);
FT_Face face = getFace();
for (int gl = 0; gl < numGlyphs; gl++) {
FT_UInt glyph = glyphs[gl];
FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP);
int load_flags = loadFlags(&defaultGlyphSet, 0);
FT_Load_Glyph(face, glyph, load_flags);
FT_GlyphSlot g = face->glyph;
if (g->format != FT_GLYPH_FORMAT_OUTLINE)
continue;
QFreetypeFace::addGlyphToPath(face, g, positions[gl], path, xsize, ysize);
if (!FT_IS_SCALABLE(face))
QFreetypeFace::addBitmapToPath(face->glyph, positions[gl], path);
else
QFreetypeFace::addGlyphToPath(face, face->glyph, positions[gl], path, face->units_per_EM << 6, face->units_per_EM << 6);
}
}
@ -993,7 +828,7 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlag
default_hint_style == HintLight ||
(flags & HB_ShaperFlag_UseDesignMetrics)) && FT_IS_SCALABLE(face);
for (int i = 0; i < glyphs->numGlyphs; i++) {
Glyph *g = loadGlyph(glyphs->glyphs[i], Format_None, true);
Glyph *g = loadGlyph(glyphs->glyphs[i], true);
if (g) {
glyphs->advances_x[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance);
} else {
@ -1019,7 +854,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs) const
QFixed ymax = 0;
QFixed xmax = 0;
for (int i = 0; i < glyphs.numGlyphs; i++) {
Glyph *g = loadGlyph(glyphs.glyphs[i], Format_None, true);
Glyph *g = loadGlyph(glyphs.glyphs[i], true);
if (g) {
QFixed x = overall.xoff + glyphs.offsets[i].x + g->x;
QFixed y = overall.yoff + glyphs.offsets[i].y - g->y;
@ -1053,7 +888,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph) const
{
FT_Face face = getFace();
glyph_metrics_t overall;
Glyph *g = loadGlyph(glyph, Format_None, true);
Glyph *g = loadGlyph(glyph, true);
if (g) {
overall.x = g->x;
overall.y = -g->y;
@ -1081,22 +916,20 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g)
{
getFace();
Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, Format_None);
Glyph *glyph = loadGlyph(g);
if (!glyph) {
return QFontEngine::alphaMapForGlyph(g);
}
const int pitch = (antialias ? glyph->width * 4 : ((glyph->width + 31) & ~31) >> 3);
const int pitch = (((glyph->width + 31) & ~31) >> 3);
QImage img(glyph->width, glyph->height, antialias ? QImage::Format_ARGB32 : QImage::Format_Mono);
if (!antialias) {
static const QVector<QRgb> colors = { qt_transparentrgba, qt_blackrgba };
img.setColorTable(colors);
}
QImage img(glyph->width, glyph->height, QImage::Format_Mono);
static const QVector<QRgb> colors = { qt_transparentrgba, qt_blackrgba };
img.setColorTable(colors);
Q_ASSERT(img.bytesPerLine() == pitch);
if (glyph->width) {
for (int y = 0; y < glyph->height; ++y)
memcpy(img.scanLine(y), &glyph->data[y * pitch], pitch);
::memcpy(img.scanLine(y), &glyph->data[y * pitch], pitch);
}
return img;
@ -1143,7 +976,6 @@ FT_Face QFontEngineFT::non_locked_face() const
QFontEngineFT::QGlyphSet::QGlyphSet()
: outline_drawing(false)
{
}
@ -1166,9 +998,7 @@ void QFontEngineFT::QGlyphSet::setGlyph(glyph_t index, Glyph *glyph)
HB_Error QFontEngineFT::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
{
getFace();
bool hsubpixel = true;
int vfactor = 1;
int load_flags = loadFlags(0, Format_None, flags, hsubpixel, vfactor);
int load_flags = loadFlags(0, flags);
HB_Error result = freetype->getPointInOutline(glyph, load_flags, point, xpos, ypos, nPoints);
return result;
}

View file

@ -61,7 +61,7 @@ public:
QFreetypeFace(const QFontEngine::FaceId &face_id);
~QFreetypeFace();
void computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing);
void computeSize(const QFontDef &fontDef, int *xsize, int *ysize);
QFontEngine::Properties properties() const;
FT_Face face;
@ -105,21 +105,11 @@ public:
uchar *data;
};
enum SubpixelAntialiasingType {
Subpixel_None,
Subpixel_RGB,
Subpixel_BGR,
Subpixel_VRGB,
Subpixel_VBGR
};
struct QGlyphSet
{
QGlyphSet();
~QGlyphSet();
bool outline_drawing;
void clear();
inline Glyph *getGlyph(glyph_t index) const;
@ -161,8 +151,6 @@ private:
virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
QPainterPath *path, QTextItem::RenderFlags flags);
virtual void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs,
QPainterPath *path, QTextItem::RenderFlags flags);
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
QTextEngine::ShaperFlags flags) const;
@ -185,12 +173,12 @@ private:
inline bool invalid() const { return xsize == 0 && ysize == 0; }
Glyph *loadGlyph(glyph_t glyph, GlyphFormat format = Format_None, bool fetchMetricsOnly = false) const;
Glyph *loadGlyph(glyph_t glyph, bool fetchMetricsOnly = false) const;
QFontEngineFT(const QFontDef &fd);
virtual ~QFontEngineFT();
bool init(FaceId faceId, bool antiaalias, GlyphFormat defaultFormat = Format_None);
bool init(FaceId faceId);
virtual HB_Error getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints);
@ -207,16 +195,11 @@ protected:
HintStyle default_hint_style;
bool antialias;
bool embolden;
SubpixelAntialiasingType subpixelType;
int lcdFilterType;
bool embeddedbitmap;
private:
int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const;
int loadFlags(QGlyphSet *set, int flags) const;
GlyphFormat defaultFormat;
FT_Matrix matrix;
mutable QGlyphSet defaultGlyphSet;

View file

@ -67,12 +67,6 @@ public:
Freetype
};
enum GlyphFormat {
Format_None,
Format_Mono,
Format_A32
};
QFontEngine();
virtual ~QFontEngine();
@ -126,10 +120,10 @@ public:
void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags,
QVarLengthArray<glyph_t> &glyphs_out, QVarLengthArray<QFixedPoint> &positions);
virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags);
void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags);
/**
* Create a qimage with the alpha values for the glyph.
* Create a qimage for the glyph.
*/
virtual QImage alphaMapForGlyph(glyph_t);

View file

@ -180,10 +180,8 @@ QFontEngineX11FT::QFontEngineX11FT(FcPattern *pattern, const QFontDef &fd, int s
: QFontEngineFT(fd)
{
// FcPatternPrint(pattern);
bool antialias = qt_x11Data->fc_antialias;
QFontEngine::FaceId face_id;
FcChar8 *fileName;
FcBool antiAlias;
FcPatternGetString(pattern, FC_FILE, 0, &fileName);
face_id.filename = (const char *)fileName;
@ -191,27 +189,6 @@ QFontEngineX11FT::QFontEngineX11FT(FcPattern *pattern, const QFontDef &fd, int s
if (!FcPatternGetInteger(pattern, FC_INDEX, 0, &face_id.index))
face_id.index = 0;
if (FcPatternGetBool(pattern, FC_ANTIALIAS, 0, &antiAlias) == FcResultMatch)
antialias = antiAlias;
subpixelType = Subpixel_None;
if (antialias) {
int subpixel = qt_x11Data->display ? qt_x11Data->screens[screen].subpixel : FC_RGBA_UNKNOWN;
if (subpixel == FC_RGBA_UNKNOWN)
(void) FcPatternGetInteger(pattern, FC_RGBA, 0, &subpixel);
if (subpixel == FC_RGBA_UNKNOWN)
subpixel = FC_RGBA_NONE;
switch (subpixel) {
case FC_RGBA_NONE: subpixelType = Subpixel_None; break;
case FC_RGBA_RGB: subpixelType = Subpixel_RGB; break;
case FC_RGBA_BGR: subpixelType = Subpixel_BGR; break;
case FC_RGBA_VRGB: subpixelType = Subpixel_VRGB; break;
case FC_RGBA_VBGR: subpixelType = Subpixel_VBGR; break;
default: break;
}
}
if (fd.hintingPreference != QFont::PreferDefaultHinting) {
switch (fd.hintingPreference) {
case QFont::PreferNoHinting:
@ -263,40 +240,7 @@ QFontEngineX11FT::QFontEngineX11FT(FcPattern *pattern, const QFontDef &fd, int s
}
#endif
#if defined(FC_LCD_FILTER) && defined(FT_LCD_FILTER_H)
{
int filter = FC_LCD_FILTER_NONE;
if (FcPatternGetInteger(pattern, FC_LCD_FILTER, 0, &filter) == FcResultMatch) {
switch (filter) {
case FC_LCD_FILTER_NONE:
lcdFilterType = FT_LCD_FILTER_NONE;
break;
case FC_LCD_FILTER_DEFAULT:
lcdFilterType = FT_LCD_FILTER_DEFAULT;
break;
case FC_LCD_FILTER_LIGHT:
lcdFilterType = FT_LCD_FILTER_LIGHT;
break;
case FC_LCD_FILTER_LEGACY:
lcdFilterType = FT_LCD_FILTER_LEGACY;
break;
default:
// new unknown lcd filter type?!
break;
}
}
}
#endif
#ifdef FC_EMBEDDED_BITMAP
{
FcBool b;
if (FcPatternGetBool(pattern, FC_EMBEDDED_BITMAP, 0, &b) == FcResultMatch)
embeddedbitmap = b;
}
#endif
if (!init(face_id, antialias, antialias ? Format_A32 : Format_Mono))
if (!init(face_id))
return;
}