Skip to content

Commit

Permalink
Advanced text: new "smooth" antialiased setting
Browse files Browse the repository at this point in the history
Relates to #428 .  Thank you to @0lm for the suggestion!

This new setting is primarily useful for softening glyph edges at large sizes; at small sizes, the aggressive edge sampling may be undesirable.

Note also that PhotoDemon exposes font hinting as a separate setting.  (In Photoshop, hinting is "merged" into the various antialiasing settings.)  This allows for a comprehensive range of glyph fit options by mixing both hinting *and* antialias settings in PD.
  • Loading branch information
tannerhelland committed Sep 13, 2022
1 parent 62b41a3 commit 48aed87
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 4 deletions.
43 changes: 40 additions & 3 deletions Classes/pdTextRenderer.cls
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,11 @@ Public Enum PD_TextAntialiasing
pdta_None = 0
pdta_Standard = 1
pdta_Crisp = 2
pdta_Smooth = 3
End Enum

#If False Then
Private Const pdta_None = 0, pdta_Standard = 1, pdta_Crisp = 2
Private Const pdta_None = 0, pdta_Standard = 1, pdta_Crisp = 2, pdta_Smooth = 3
#End If

'Text hinting and AA are merged into a single setting in GDI+
Expand Down Expand Up @@ -449,6 +450,8 @@ Private Function GetFontAntialiasingStringFromEnum(ByVal srcValue As PD_TextAnti
GetFontAntialiasingStringFromEnum = "standard"
ElseIf (srcValue = pdta_Crisp) Then
GetFontAntialiasingStringFromEnum = "crisp"
ElseIf (srcValue = pdta_Crisp) Then
GetFontAntialiasingStringFromEnum = "smooth"
Else
InternalError "GetFontAntialiasingStringFromEnum", "bad value: " & srcValue
GetFontAntialiasingStringFromEnum = "standard"
Expand All @@ -462,6 +465,8 @@ Private Function GetFontAntialiasingEnumFromString(ByRef srcValue As String) As
GetFontAntialiasingEnumFromString = pdta_Standard
ElseIf (srcValue = "crisp") Then
GetFontAntialiasingEnumFromString = pdta_Crisp
ElseIf (srcValue = "smooth") Then
GetFontAntialiasingEnumFromString = pdta_Smooth
Else
InternalError "GetFontAntialiasingEnumFromString", "bad value: " & srcValue
GetFontAntialiasingEnumFromString = pdta_Standard
Expand Down Expand Up @@ -1021,7 +1026,7 @@ Friend Function SetGenericTextProperty(ByVal desiredProperty As PD_TextProperty,
SetGenericTextProperty = True

'If we're using GDI for rendering, changing antialiasing requires us to recreate the font
If m_CurrentBackend = fb_GDI Then m_FontCacheClean = False
If (m_CurrentBackend = fb_GDI) Then m_FontCacheClean = False

End If

Expand Down Expand Up @@ -1666,7 +1671,7 @@ Private Function RenderTextToDIB_Glyphs(ByRef dstDIB As pdDIB, ByRef srcString A
targetSmoothingMode = GP_SM_Antialias
targetOffsetMode = GP_POM_None

Case pdta_Crisp
Case pdta_Crisp, pdta_Smooth
targetSmoothingMode = GP_SM_Antialias
targetOffsetMode = GP_POM_Half

Expand Down Expand Up @@ -1858,12 +1863,43 @@ Private Function RenderTextToDIB_Glyphs(ByRef dstDIB As pdDIB, ByRef srcString A

'Fill (if any)
If (gdipFillBrush <> 0) Then

gdipReturn = GdipFillPath(dstGraphics, gdipFillBrush, finalTextPath.GetHandle)
If (gdipReturn <> GP_OK) Then PDDebug.LogAction "WARNING! GdipFillPath failed; return code was " & gdipReturn

'If the user wants "smooth" antialiasing, we can achieve this by performing a fast scaledown+scaleup op on the
' filled surface. This softens antialiased boundaries slightly, with a minimal penalty to perf.
If (m_TextAntialiasing = pdta_Smooth) Then

Dim tmpDIB As pdDIB
Set tmpDIB = New pdDIB

Const SMOOTH_SCALE_FACTOR As Single = 0.95!

Dim tmpWidth As Long, tmpHeight As Long
tmpWidth = Int(dstDIB.GetDIBWidth * SMOOTH_SCALE_FACTOR + 0.5)
If (tmpWidth >= dstDIB.GetDIBWidth) Then tmpWidth = dstDIB.GetDIBWidth - 1
If (tmpWidth <= 0) Then tmpWidth = dstDIB.GetDIBWidth

tmpHeight = Int(dstDIB.GetDIBHeight * SMOOTH_SCALE_FACTOR + 0.5)
If (tmpHeight >= dstDIB.GetDIBHeight) Then tmpHeight = dstDIB.GetDIBHeight - 1
If (tmpHeight <= 0) Then tmpHeight = dstDIB.GetDIBHeight

tmpDIB.CreateBlank tmpWidth, tmpHeight, 32, 0, 0
tmpDIB.SetInitialAlphaPremultiplicationState True

GDI_Plus.GDIPlus_StretchBlt tmpDIB, 0, 0, tmpWidth, tmpHeight, dstDIB, 0, 0, dstDIB.GetDIBWidth, dstDIB.GetDIBHeight, interpolationType:=GP_IM_HighQualityBicubic, isZoomedIn:=True, dstCopyIsOkay:=True
dstDIB.ResetDIB 0
GDI_Plus.GDIPlus_StretchBlt dstDIB, 0, 0, dstDIB.GetDIBWidth, dstDIB.GetDIBHeight, tmpDIB, 0, 0, tmpWidth, tmpHeight, interpolationType:=GP_IM_HighQualityBicubic, isZoomedIn:=True, dstCopyIsOkay:=True
Set tmpDIB = Nothing

End If

If REPORT_TEXT_RENDER_TIMING Then
PDDebug.LogAction "RenderTextToDIB_Glyphs - fill: " & VBHacks.GetTimeDiffNowAsString(startTime)
VBHacks.GetHighResTime startTime
End If

End If

'If outline mode is active *and* the user wants the outline on top, stroke the text *now*
Expand Down Expand Up @@ -2296,6 +2332,7 @@ Private Sub Class_Initialize()
m_FillActive = True
m_StretchToFit = stf_None
m_OutlineAboveFill = True
m_TextHinting = True

'Set default graphics container text settings
m_TextContrast = 4
Expand Down
1 change: 1 addition & 0 deletions Forms/Toolpanel_Typography.frm
Original file line number Diff line number Diff line change
Expand Up @@ -1504,6 +1504,7 @@ Private Sub Form_Load()
cboTextRenderingHint.AddItem "none", 0
cboTextRenderingHint.AddItem "normal", 1
cboTextRenderingHint.AddItem "crisp", 2
cboTextRenderingHint.AddItem "smooth", 3
cboTextRenderingHint.ListIndex = 1
cboTextRenderingHint.SetAutomaticRedraws True

Expand Down
2 changes: 1 addition & 1 deletion PhotoDemon.vbp
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ Description="PhotoDemon Photo Editor"
CompatibleMode="0"
MajorVer=9
MinorVer=0
RevisionVer=14
RevisionVer=15
AutoIncrementVer=1
ServerSupportFiles=0
VersionComments="Copyright 2000-2022 Tanner Helland - photodemon.org"
Expand Down

0 comments on commit 48aed87

Please sign in to comment.