Improve synthetic bold quality and use synthetic bold for most Open Sans uses

This commit is contained in:
elasota
2021-04-18 18:11:38 -04:00
parent d826a908e9
commit f15a87041a
15 changed files with 122 additions and 61 deletions

View File

@@ -16,8 +16,9 @@ namespace PortabilityLayer
FontFamilyFlag_None = 0,
FontFamilyFlag_Bold = 1,
FontFamilyFlag_SyntheticBold = 2,
FontFamilyFlag_All = 1,
FontFamilyFlag_All = (FontFamilyFlag_Bold | FontFamilyFlag_SyntheticBold),
};
class FontFamily final

View File

@@ -6,6 +6,6 @@ namespace PortabilityLayer
{
FontHacks_None,
FontHacks_Roboto,
FontHacks_SyntheticBold,
FontHacks_SyntheticBold_OpenSans,
};
}

View File

@@ -50,8 +50,9 @@ namespace PortabilityLayer
RenderedFont *m_rfont;
int m_fontCacheID;
int m_size;
uint32_t m_lastUsage;
int m_flags;
bool m_aa;
uint32_t m_lastUsage;
};
struct FontPreset
@@ -64,7 +65,7 @@ namespace PortabilityLayer
FontManagerImpl();
bool FindOrReserveCacheSlot(int cacheID, int size, bool aa, CachedRenderedFont *&outCacheSlot, RenderedFont *&outRF);
bool FindOrReserveCacheSlot(int cacheID, int size, bool aa, int flags, CachedRenderedFont *&outCacheSlot, RenderedFont *&outRF);
void ReplaceCachedRenderedFont(CachedRenderedFont &cacheSlot, RenderedFont *rfont, int cacheID, int size, bool aa, int flags);
void ResetUsageCounter();
@@ -97,6 +98,7 @@ namespace PortabilityLayer
{
m_fontFamilies[FontFamilyIDs::kApplication]->AddFont(FontFamilyFlag_None, VirtualDirectories::kFonts, "Fonts/OpenSans/OpenSans-SemiBold.ttf", 0, FontHacks_None);
m_fontFamilies[FontFamilyIDs::kApplication]->AddFont(FontFamilyFlag_Bold, VirtualDirectories::kFonts, "Fonts/OpenSans/OpenSans-Bold.ttf", 0, FontHacks_None);
m_fontFamilies[FontFamilyIDs::kApplication]->AddFont(FontFamilyFlag_SyntheticBold, VirtualDirectories::kFonts, "Fonts/OpenSans/OpenSans-Regular.ttf", 0, FontHacks_SyntheticBold_OpenSans);
}
if (m_fontFamilies[FontFamilyIDs::kHandwriting])
@@ -143,23 +145,10 @@ namespace PortabilityLayer
*outAA = ms_fontPresets[preset].m_aa;
if (outFamilyID)
{
switch (ms_fontPresets[preset].m_familyID)
{
case FontFamilyIDs::kApplication:
if (!m_hasPreinstalledFonts && ms_fontPresets[preset].m_textSize < 11 && (ms_fontPresets[preset].m_variationFlags & FontFamilyFlag_Bold) != 0)
*outFamilyID = FontFamilyIDs::kSystem; // Use heavier font below 11pt
else
*outFamilyID = FontFamilyIDs::kApplication;
break;
default:
*outFamilyID = ms_fontPresets[preset].m_familyID;
break;
}
}
*outFamilyID = ms_fontPresets[preset].m_familyID;
}
bool FontManagerImpl::FindOrReserveCacheSlot(int cacheID, int size, bool aa, CachedRenderedFont *&outCacheSlot, RenderedFont *&outRF)
bool FontManagerImpl::FindOrReserveCacheSlot(int cacheID, int size, bool aa, int flags, CachedRenderedFont *&outCacheSlot, RenderedFont *&outRF)
{
CachedRenderedFont *newCacheSlot = &m_cachedRenderedFonts[0];
@@ -172,7 +161,7 @@ namespace PortabilityLayer
break;
}
if (crf.m_fontCacheID == cacheID && crf.m_size == size && crf.m_aa == aa)
if (crf.m_fontCacheID == cacheID && crf.m_size == size && crf.m_aa == aa && crf.m_flags == flags)
{
crf.m_lastUsage = m_usageCounter;
RenderedFont *rf = crf.m_rfont;
@@ -203,6 +192,7 @@ namespace PortabilityLayer
cacheSlot.m_size = size;
cacheSlot.m_rfont = rfont;
cacheSlot.m_aa = aa;
cacheSlot.m_flags = flags;
if (m_usageCounter == UINT32_MAX)
ResetUsageCounter();
@@ -231,7 +221,7 @@ namespace PortabilityLayer
CachedRenderedFont *cacheSlot = nullptr;
RenderedFont *rfont = nullptr;
if (this->FindOrReserveCacheSlot(familyID, size, aa, cacheSlot, rfont))
if (this->FindOrReserveCacheSlot(familyID, size, aa, flags, cacheSlot, rfont))
return rfont;
rfont = LoadAndRenderFont(familyID, size, aa, flags);
@@ -424,11 +414,12 @@ namespace PortabilityLayer
{ FontFamilyIDs::kApplication, 8, FontFamilyFlag_None, true },
{ FontFamilyIDs::kApplication, 9, FontFamilyFlag_None, true },
{ FontFamilyIDs::kApplication, 9, FontFamilyFlag_Bold, true },
{ FontFamilyIDs::kApplication, 10, FontFamilyFlag_Bold, true },
{ FontFamilyIDs::kApplication, 9, FontFamilyFlag_SyntheticBold, true },
{ FontFamilyIDs::kApplication, 10, FontFamilyFlag_SyntheticBold, true },
{ FontFamilyIDs::kApplication, 12, FontFamilyFlag_Bold, true },
{ FontFamilyIDs::kApplication, 12, FontFamilyFlag_SyntheticBold, true },
{ FontFamilyIDs::kApplication, 14, FontFamilyFlag_None, true },
{ FontFamilyIDs::kApplication, 14, FontFamilyFlag_Bold, true },
{ FontFamilyIDs::kApplication, 14, FontFamilyFlag_SyntheticBold, true },
{ FontFamilyIDs::kApplication, 18, FontFamilyFlag_None, true },
{ FontFamilyIDs::kApplication, 40, FontFamilyFlag_None, true },

View File

@@ -11,11 +11,12 @@ namespace PortabilityLayer
kApplication8,
kApplication9,
kApplication9Bold,
kApplication10Bold,
kApplication9SyntheticBold,
kApplication10SyntheticBold,
kApplication12Bold,
kApplication12SyntheticBold,
kApplication14,
kApplication14Bold,
kApplication14SyntheticBold,
kApplication18,
kApplication40,

View File

@@ -59,6 +59,8 @@ namespace PortabilityLayer
BEInt16_t m_bearingX;
BEInt16_t m_bearingY;
BEInt16_t m_advanceX;
BEInt16_t m_bitmapOffsetX;
BEInt16_t m_bitmapOffsetY;
};
struct SerializedFontMetrics
@@ -101,7 +103,7 @@ namespace PortabilityLayer
static FontRendererImpl *GetInstance();
private:
static void SynthesizeBoldAA(IGpFontRenderedGlyph *&glyph, unsigned int xScale, unsigned int yScale, bool aa);
static void SynthesizeBoldAA(IGpFontRenderedGlyph *&glyph, unsigned int xScale, unsigned int yScale, bool aa, uint8_t character, int size, FontHacks fontHacks);
static FontRendererImpl ms_instance;
};
@@ -315,6 +317,8 @@ namespace PortabilityLayer
result.m_glyphDataPitch = static_cast<uint32_t>(metrics.m_glyphDataPitch);
result.m_glyphHeight = metrics.m_glyphHeight;
result.m_glyphWidth = metrics.m_glyphWidth;
result.m_bitmapOffsetX = metrics.m_bitmapOffsetX;
result.m_bitmapOffsetY = metrics.m_bitmapOffsetY;
return result;
}
@@ -328,6 +332,8 @@ namespace PortabilityLayer
result.m_glyphDataPitch = static_cast<uint32_t>(metrics.m_glyphDataPitch);
result.m_glyphHeight = metrics.m_glyphHeight;
result.m_glyphWidth = metrics.m_glyphWidth;
result.m_bitmapOffsetX = metrics.m_bitmapOffsetX;
result.m_bitmapOffsetY = metrics.m_bitmapOffsetY;
return result;
}
@@ -369,16 +375,20 @@ namespace PortabilityLayer
for (unsigned int i = 0; i < numCharacters; i++)
glyphs[i] = nullptr;
bool isSyntheticBold = false;
if (fontHacks == FontHacks_SyntheticBold_OpenSans)
isSyntheticBold = true;
unsigned int xScale = 1;
unsigned int yScale = 1;
bool syntheticBoldAA = false;
if (fontHacks == FontHacks_SyntheticBold)
if (isSyntheticBold)
{
if (aa)
{
syntheticBoldAA = true;
xScale = 16;
yScale = 16;
xScale = 8;
yScale = 8;
}
}
@@ -391,14 +401,14 @@ namespace PortabilityLayer
glyphs[i] = font->Render(unicodeCodePoint, size, xScale, yScale, aa);
}
if (fontHacks == FontHacks_SyntheticBold)
if (isSyntheticBold)
{
if (syntheticBoldAA)
{
for (unsigned int i = 0; i < numCharacters; i++)
{
if (glyphs[i])
SynthesizeBoldAA(glyphs[i], xScale, yScale, syntheticBoldAA);
SynthesizeBoldAA(glyphs[i], xScale, yScale, syntheticBoldAA, i, size, fontHacks);
}
}
}
@@ -448,6 +458,20 @@ namespace PortabilityLayer
}
}
/*
if (fontHacks == FontHacks_SyntheticBold_OpenSans && size == 12)
{
if (i == 'i')
metrics.m_bearingX++;
}
if (fontHacks == FontHacks_SyntheticBold_OpenSans && size == 9)
{
if (i == 'V')
metrics.m_advanceX++;
}
*/
rfont->SetCharData(i, data, fillOffset, metrics);
fillOffset += metrics.m_glyphDataPitch * metrics.m_glyphHeight;
@@ -512,16 +536,45 @@ namespace PortabilityLayer
return true;
}
void FontRendererImpl::SynthesizeBoldAA(IGpFontRenderedGlyph *&glyph, unsigned int xScale, unsigned int yScale, bool aa)
void FontRendererImpl::SynthesizeBoldAA(IGpFontRenderedGlyph *&glyph, unsigned int xScale, unsigned int yScale, bool aa, uint8_t character, int size, FontHacks fontHacks)
{
unsigned int extraWidth = 1;
GpRenderedGlyphMetrics metrics = glyph->GetMetrics();
const void *existingData = glyph->GetData();
uint32_t existingWidth = metrics.m_glyphWidth;
uint32_t existingHeight = metrics.m_glyphHeight;
uint32_t newWidth = (existingWidth + xScale - 1) / xScale + 1;
uint32_t newHeight = (existingHeight + yScale - 1) / yScale;
uint32_t leftPadding = 0;
uint32_t topPadding = 0;
{
const int32_t leftCoord = metrics.m_bitmapOffsetX;
int32_t leftCoordRemainder = leftCoord % static_cast<int32_t>(xScale);
if (leftCoordRemainder > 0)
leftPadding = leftCoordRemainder;
else if (leftCoordRemainder < 0)
leftPadding = leftCoordRemainder + static_cast<int32_t>(xScale);
const int32_t topCoord = metrics.m_bitmapOffsetY;
int32_t topCoordRemainder = topCoord % static_cast<int32_t>(yScale);
if (topCoordRemainder != 0)
{
if (topCoordRemainder < 0)
topCoordRemainder += static_cast<int32_t>(yScale);
topPadding = static_cast<int32_t>(yScale) - topCoordRemainder;
}
}
uint32_t paddedWidth = existingWidth + leftPadding;
uint32_t paddedHeight = existingHeight + topPadding;
uint32_t newWidth = (paddedWidth + xScale - 1) / xScale + extraWidth;
uint32_t newHeight = (paddedHeight + yScale - 1) / yScale;
ReRenderedGlyph *newGlyph = ReRenderedGlyph::Create(newWidth, newHeight, aa);
if (!newGlyph)
@@ -535,9 +588,11 @@ namespace PortabilityLayer
}
GpRenderedGlyphMetrics &newMetrics = newGlyph->GetMutableMetrics();
newMetrics.m_advanceX = metrics.m_advanceX + 1;
newMetrics.m_bearingX = metrics.m_bearingX;
newMetrics.m_bearingY = metrics.m_bearingY;
newMetrics.m_advanceX = metrics.m_advanceX + static_cast<int16_t>(extraWidth);
newMetrics.m_bearingX = (metrics.m_bitmapOffsetX - static_cast<int16_t>(leftPadding)) / static_cast<int16_t>(xScale);
newMetrics.m_bearingY = (metrics.m_bitmapOffsetY + static_cast<int16_t>(topPadding)) / static_cast<int16_t>(yScale);
newMetrics.m_bitmapOffsetX = newMetrics.m_bearingX;
newMetrics.m_bitmapOffsetY = newMetrics.m_bearingY;
const size_t existingDataPitch = metrics.m_glyphDataPitch;
const size_t newPitch = newMetrics.m_glyphDataPitch;
@@ -549,7 +604,11 @@ namespace PortabilityLayer
for (unsigned int subY = 0; subY < yScale; subY++)
{
unsigned int originalY = subY + outY * yScale;
uint32_t originalY = subY + outY * yScale;
if (originalY < topPadding)
continue;
originalY -= topPadding;
if (originalY >= existingHeight)
break;
@@ -558,14 +617,19 @@ namespace PortabilityLayer
unsigned int streakCounter = 0;
unsigned int outX = 0;
unsigned int outSubX = 0;
for (unsigned int originalX = 0; originalX < newWidth * xScale; originalX++)
for (unsigned int unpaddedOriginalX = 0; unpaddedOriginalX < newWidth * xScale; unpaddedOriginalX++)
{
if (originalX < existingWidth)
if (unpaddedOriginalX > leftPadding)
{
//if (existingRow[originalX / 8] & (1 << (originalX & 7)))
uint8_t v = ((existingRow[originalX / 2] >> ((originalX & 1) * 4)) & 0xf);
if (v >= 8)
streakCounter = xScale + 1;
uint32_t originalX = unpaddedOriginalX - leftPadding;
if (originalX < existingWidth)
{
//if (existingRow[originalX / 8] & (1 << (originalX & 7)))
uint8_t v = ((existingRow[originalX / 2] >> ((originalX & 1) * 4)) & 0xf);
if (v >= 8)
streakCounter = xScale + 1;
}
}
if (streakCounter > 0)

View File

@@ -593,7 +593,7 @@ namespace PortabilityLayer
if (window->GetStyleFlags() & WindowStyleFlags::kCloseBox)
RenderChromeCloseBox(surface, rect, false);
PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication10Bold);
PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication10SyntheticBold);
int32_t ascender = appFont->GetMetrics().m_ascent;
const PLPasStr titlePStr = window->GetTitle().ToShortStr();