aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@google.com>2018-05-02 13:53:53 +0000
committerGravatar Mike Klein <mtklein@google.com>2018-05-02 13:54:54 +0000
commitc76e26a6bb8af9ac9b0c7226851b2ded12d18687 (patch)
tree368bb3cfb1d09e08cfb59cbf666b3e1769267640
parent78a9aed075ecb342545d913bc92ef9abc6431b49 (diff)
Revert "Remove devKerning"
This reverts commit c86c5c0144b85d0bc8ec791f9609ee2d4e7d835a. Reason for revert: 4 of 5 Original change's description: > Remove devKerning > > Dev kerning is not supported by any scalers. This is > mostly removed. The remaining fields fRsbDelta and > fLsbDelta are kept to keep Android compiling. > > Change-Id: If1a9ee9bb599d4e1bdf4b3751ac0c65246350809 > Reviewed-on: https://skia-review.googlesource.com/124921 > Reviewed-by: Ben Wagner <bungeman@google.com> > Commit-Queue: Herb Derby <herb@google.com> TBR=bungeman@google.com,herb@google.com,reed@google.com Change-Id: If865f702868192a1b72cd811baa996dd1282bbce No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://skia-review.googlesource.com/125263 Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Mike Klein <mtklein@google.com>
-rw-r--r--docs/SkPaint_Reference.bmh307
-rw-r--r--gn/core.gni1
-rw-r--r--include/core/SkPaint.h7
-rw-r--r--samplecode/SampleText.cpp3
-rw-r--r--src/core/SkAutoKern.h51
-rw-r--r--src/core/SkDraw.cpp1
-rw-r--r--src/core/SkFindAndPlaceGlyph.h38
-rw-r--r--src/core/SkGlyph.cpp2
-rw-r--r--src/core/SkGlyph.h4
-rw-r--r--src/core/SkPaint.cpp161
-rw-r--r--src/core/SkScalerContext.cpp15
-rw-r--r--src/core/SkScalerContext.h2
-rw-r--r--src/core/SkTextBlob.cpp1
-rw-r--r--src/core/SkTextToPathIter.h2
-rw-r--r--src/gpu/text/GrAtlasTextContext.cpp11
-rw-r--r--src/gpu/text/GrTextUtils.cpp2
-rw-r--r--src/ports/SkFontHost_FreeType.cpp10
-rw-r--r--src/ports/SkFontHost_mac.cpp3
-rw-r--r--src/ports/SkFontHost_win.cpp3
-rw-r--r--src/ports/SkScalerContext_win_dw.cpp6
-rw-r--r--src/ports/SkTypeface_win_dw.cpp1
-rw-r--r--tests/TextBlobTest.cpp2
-rw-r--r--tools/debugger/SkDrawCommand.cpp1
23 files changed, 442 insertions, 192 deletions
diff --git a/docs/SkPaint_Reference.bmh b/docs/SkPaint_Reference.bmh
index 677d5c1da5..47627361d4 100644
--- a/docs/SkPaint_Reference.bmh
+++ b/docs/SkPaint_Reference.bmh
@@ -12,7 +12,7 @@
Paint controls options applied when drawing and measuring. Paint collects all
options outside of the Canvas_Clip and Canvas_Matrix.
-Various options apply to text, strokes and fills, and images.
+Various options apply to text, strokes and fills, and images.
Some options may not be implemented on all platforms; in these cases, setting
the option has no effect. Some options are conveniences that duplicate Canvas
@@ -21,14 +21,14 @@ functionality; for instance, text size is identical to matrix scale.
Paint options are rarely exclusive; each option modifies a stage of the drawing
pipeline and multiple pipeline stages may be affected by a single Paint.
-Paint collects effects and filters that describe single-pass and multiple-pass
+Paint collects effects and filters that describe single-pass and multiple-pass
algorithms that alter the drawing geometry, color, and transparency. For instance,
-Paint does not directly implement dashing or blur, but contains the objects that do so.
+Paint does not directly implement dashing or blur, but contains the objects that do so.
The objects contained by Paint are opaque, and cannot be edited outside of the Paint
to affect it. The implementation is free to defer computations associated with the
Paint, or ignore them altogether. For instance, some GPU implementations draw all
-Path geometries with Anti-aliasing, regardless of how SkPaint::kAntiAlias_Flag
+Path geometries with Anti-aliasing, regardless of how SkPaint::kAntiAlias_Flag
is set in Paint.
Paint describes a single color, a single font, a single image quality, and so on.
@@ -108,7 +108,7 @@ Constructs Paint with default values.
#Table ##
The flags, text size, hinting, and miter limit may be overridden at compile time by defining
-paint default values. The overrides may be included in "SkUserConfig.h" or predefined by the
+paint default values. The overrides may be included in "SkUserConfig.h" or predefined by the
build system.
#Return default initialized Paint ##
@@ -226,7 +226,7 @@ Decreases Paint Reference_Count of owned objects: Typeface, Path_Effect, Shader,
Mask_Filter, Color_Filter, Draw_Looper, and Image_Filter. If the
objects containing Reference_Count go to zero, they are deleted.
-#NoExample
+#NoExample
##
##
@@ -428,21 +428,21 @@ as the Font_Engine.
#Const kSlight_Hinting 1
Modifies glyph outlines minimally to improve constrast.
With FreeType, this is equivalent in spirit to the
- FT_LOAD_TARGET_LIGHT value supplied to FT_Load_Glyph. It chooses a
+ FT_LOAD_TARGET_LIGHT value supplied to FT_Load_Glyph. It chooses a
lighter hinting algorithm for non-monochrome modes.
Generated Glyphs may be fuzzy but better resemble their original shape.
##
#Const kNormal_Hinting 2
Modifies glyph outlines to improve constrast. This is the default.
With FreeType, this supplies FT_LOAD_TARGET_NORMAL to FT_Load_Glyph,
- choosing the default hinting algorithm, which is optimized for standard
- gray-level rendering.
+ choosing the default hinting algorithm, which is optimized for standard
+ gray-level rendering.
##
#Const kFull_Hinting 3
Modifies glyph outlines for maxiumum constrast. With FreeType, this selects
- FT_LOAD_TARGET_LCD or FT_LOAD_TARGET_LCD_V if kLCDRenderText_Flag is set.
- FT_LOAD_TARGET_LCD is a variant of FT_LOAD_TARGET_NORMAL optimized for
- horizontally decimated LCD displays; FT_LOAD_TARGET_LCD_V is a
+ FT_LOAD_TARGET_LCD or FT_LOAD_TARGET_LCD_V if kLCDRenderText_Flag is set.
+ FT_LOAD_TARGET_LCD is a variant of FT_LOAD_TARGET_NORMAL optimized for
+ horizontally decimated LCD displays; FT_LOAD_TARGET_LCD_V is a
variant of FT_LOAD_TARGET_NORMAL optimized for vertically decimated LCD displays.
##
@@ -500,7 +500,7 @@ Set SkPaintDefaults_Hinting at compile time to change the default setting.
# kNo_Hinting # 0 # leaves glyph outlines unchanged from their native representation ##
# kSlight_Hinting # 1 # modifies glyph outlines minimally to improve contrast ##
# kNormal_Hinting # 2 # modifies glyph outlines to improve contrast ##
- # kFull_Hinting # 3 # modifies glyph outlines for maximum contrast ##
+ # kFull_Hinting # 3 # modifies glyph outlines for maximum contrast ##
##
#Param hintingLevel one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting ##
@@ -548,7 +548,7 @@ with a custom definition of SkPaintDefaults_Flags.
All flags can be read and written explicitly; Flags allows manipulating
multiple settings at once.
- #Const kAntiAlias_Flag 0x0001
+ #Const kAntiAlias_Flag 0x0001
mask for setting Anti-alias
##
#Const kDither_Flag 0x0004
@@ -562,16 +562,16 @@ multiple settings at once.
mask for setting Linear_Text
##
#Const kSubpixelText_Flag 0x0080
- mask for setting Subpixel_Text
+ mask for setting Subpixel_Text
##
#Const kDevKernText_Flag 0x0100
- #Deprecated
+ mask for setting Full_Hinting_Spacing
##
#Const kLCDRenderText_Flag 0x0200
mask for setting LCD_Text
##
#Const kEmbeddedBitmapText_Flag 0x0400
- mask for setting Font_Embedded_Bitmaps
+ mask for setting Font_Embedded_Bitmaps
##
#Const kAutoHinting_Flag 0x0800
mask for setting Automatic_Hinting
@@ -663,7 +663,7 @@ Anti-alias drawing approximates partial pixel coverage with transparency.
If kAntiAlias_Flag is clear, pixel centers contained by the shape edge are drawn opaque.
If kAntiAlias_Flag is set, pixels are drawn with Color_Alpha equal to their coverage.
-The rule for Aliased pixels is inconsistent across platforms. A shape edge
+The rule for Aliased pixels is inconsistent across platforms. A shape edge
passing through the pixel center may, but is not required to, draw the pixel.
Raster_Engine draws Aliased pixels whose centers are on or to the right of the start of an
@@ -767,10 +767,10 @@ at compile time.
#Subtopic Dither
#Line # distributing color error ##
-Dither increases fidelity by adjusting the color of adjacent pixels.
+Dither increases fidelity by adjusting the color of adjacent pixels.
This can help to smooth color transitions and reducing banding in gradients.
Dithering lessens visible banding from kRGB_565_SkColorType
-and kRGBA_8888_SkColorType gradients,
+and kRGBA_8888_SkColorType gradients,
and improves rendering into a kRGB_565_SkColorType Surface.
Dithering is always enabled for linear gradients drawing into
@@ -791,7 +791,7 @@ SK_IGNORE_GPU_DITHER
to ignore Dither on GPU_Surface.
#Example
-#Description
+#Description
Dithering in the bottom half more closely approximates the requested color by
alternating nearby colors from pixel to pixel.
##
@@ -817,7 +817,7 @@ void draw(SkCanvas* canvas) {
##
#Example
-#Description
+#Description
Dithering introduces subtle adjustments to color to smooth gradients.
Drawing the gradient repeatedly with SkBlendMode::kPlus exaggerates the
dither, making it easier to see.
@@ -849,7 +849,7 @@ void draw(SkCanvas* canvas) {
#In Dither
#Line # returns true if Dither is set ##
If true, color error may be distributed to smooth color transition.
-
+
Equivalent to getFlags masked with kDither_Flag.
#Return kDither_Flag state ##
@@ -905,19 +905,19 @@ void draw(SkCanvas* canvas) {
LCD_Text and Subpixel_Text increase the precision of glyph position.
-When set, Flags kLCDRenderText_Flag takes advantage of the organization of Color_RGB stripes that
+When set, Flags kLCDRenderText_Flag takes advantage of the organization of Color_RGB stripes that
create a color, and relies
on the small size of the stripe and visual perception to make the color fringing imperceptible.
LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
the color components as Color_RGB or Color_RBG.
-Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
+Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
As the opaqueness
of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
Either or both techniques can be enabled.
kLCDRenderText_Flag and kSubpixelText_Flag are clear by default.
-LCD_Text or Subpixel_Text can be enabled by default by setting SkPaintDefaults_Flags to
+LCD_Text or Subpixel_Text can be enabled by default by setting SkPaintDefaults_Flags to
kLCDRenderText_Flag or kSubpixelText_Flag (or both) at compile time.
#Example
@@ -1017,7 +1017,7 @@ If kLinearText_Flag is clear, it is the same as setting Hinting to kNo_Hinting.
canvas->drawString(width, 128, 0, paint);
}
}
- }
+ }
##
#SeeAlso isLinearText Hinting
@@ -1029,12 +1029,12 @@ If kLinearText_Flag is clear, it is the same as setting Hinting to kNo_Hinting.
#Alias Subpixel_Text
#Line # uses pixel transparency to represent fractional offset ##
-Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
+Flags kSubpixelText_Flag uses the pixel transparency to represent a fractional offset.
As the opaqueness
of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
#Method bool isSubpixelText() const
-
+
#In Subpixel_Text
#Line # returns true if Subpixel_Text is set ##
If true, Glyphs at different sub-pixel positions may differ on pixel edge coverage.
@@ -1090,7 +1090,7 @@ SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelTex
#Line # text relying on the order of Color_RGB stripes ##
#Alias LCD_Text # makes this a top level name, since it is under subtopic Device_Text
-When set, Flags kLCDRenderText_Flag takes advantage of the organization of Color_RGB stripes that
+When set, Flags kLCDRenderText_Flag takes advantage of the organization of Color_RGB stripes that
create a color, and relies
on the small size of the stripe and visual perception to make the color fringing imperceptible.
LCD_Text can be enabled on devices that orient stripes horizontally or vertically, and that order
@@ -1156,7 +1156,7 @@ SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderT
Font_Embedded_Bitmaps allows selecting custom sized bitmap Glyphs.
Flags kEmbeddedBitmapText_Flag when set chooses an embedded bitmap glyph over an outline contained
-in a font if the platform supports this option.
+in a font if the platform supports this option.
FreeType selects the bitmap glyph if available when kEmbeddedBitmapText_Flag is set, and selects
the outline glyph if kEmbeddedBitmapText_Flag is clear.
@@ -1343,7 +1343,7 @@ is positioned to the right of the preceding glyph. Vertical_Text sets successive
Glyphs to position below the preceding glyph.
Skia can translate text character codes as a series of Glyphs, but does not implement
-font substitution,
+font substitution,
textual substitution, line layout, or contextual spacing like Kerning pairs. Use
a text shaping engine like
#A HarfBuzz # http://harfbuzz.org/ ##
@@ -1434,12 +1434,12 @@ Fake_Bold approximates the bold font style accompanying a normal font when a bol
is not available. Skia does not provide font substitution; it is up to the client to find the
bold font face using the platform Font_Manager.
-Use Text_Skew_X to approximate an italic font style when the italic font face
+Use Text_Skew_X to approximate an italic font style when the italic font face
is not available.
A FreeType based port may define SK_USE_FREETYPE_EMBOLDEN at compile time to direct
the font engine to create the bold Glyphs. Otherwise, the extra bold is computed
-by increasing the stroke width and setting the Style to kStrokeAndFill_Style as needed.
+by increasing the stroke width and setting the Style to kStrokeAndFill_Style as needed.
Fake_Bold is disabled by default.
@@ -1527,11 +1527,48 @@ Full_Hinting_Spacing is not related to text Kerning, where the space between
a specific pair of characters is adjusted using data in the font Kerning tables.
#Method bool isDevKernText() const
-#Deprecated
+
+#In Full_Hinting_Spacing
+#Line # returns true if Full_Hinting_Spacing is set ##
+ Returns if character spacing may be adjusted by the hinting difference.
+
+ Equivalent to getFlags masked with kDevKernText_Flag.
+
+ #Return kDevKernText_Flag state ##
+
+ #Example
+ SkPaint paint;
+ SkDebugf("paint.isDevKernText() %c= !!(paint.getFlags() & SkPaint::kDevKernText_Flag)\n",
+ paint.isDevKernText() == !!(paint.getFlags() & SkPaint::kDevKernText_Flag) ? '=' : '!');
+ paint.setDevKernText(true);
+ SkDebugf("paint.isDevKernText() %c= !!(paint.getFlags() & SkPaint::kDevKernText_Flag)\n",
+ paint.isDevKernText() == !!(paint.getFlags() & SkPaint::kDevKernText_Flag) ? '=' : '!');
+ ##
+
##
-#Method void setDevKernText(bool)
-#Deprecated
+#Method void setDevKernText(bool devKernText)
+
+#In Full_Hinting_Spacing
+#Line # sets or clears Full_Hinting_Spacing ##
+ Requests, but does not require, to use hinting to adjust glyph spacing.
+
+ Sets kDevKernText_Flag if devKernText is true.
+ Clears kDevKernText_Flag if devKernText is false.
+
+ #Param devKernText setting for devKernText ##
+
+ #Example
+ SkPaint paint1, paint2;
+ paint1.setDevKernText(true);
+ paint2.setFlags(paint2.getFlags() | SkPaint::kDevKernText_Flag);
+ SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
+
+ #StdOut
+ paint1 == paint2
+ ##
+ ##
+
##
#Subtopic Full_Hinting_Spacing ##
@@ -1562,7 +1599,7 @@ Filter_Quality is kNone_SkFilterQuality by default.
void draw(SkCanvas* canvas) {
SkPaint paint;
canvas->scale(.2f, .2f);
- for (SkFilterQuality q : { kNone_SkFilterQuality, kLow_SkFilterQuality,
+ for (SkFilterQuality q : { kNone_SkFilterQuality, kLow_SkFilterQuality,
kMedium_SkFilterQuality, kHigh_SkFilterQuality } ) {
paint.setFilterQuality(q);
canvas->drawImage(image.get(), 0, 0, &paint);
@@ -1579,7 +1616,7 @@ void draw(SkCanvas* canvas) {
Returns Filter_Quality, the image filtering level. A lower setting
draws faster; a higher setting looks better when the image is scaled.
-#Return one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
+#Return one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
kMedium_SkFilterQuality, kHigh_SkFilterQuality
#Return ##
@@ -1602,9 +1639,9 @@ draws faster; a higher setting looks better when the image is scaled.
#Line # sets Filter_Quality, the image filtering level ##
Sets Filter_Quality, the image filtering level. A lower setting
draws faster; a higher setting looks better when the image is scaled.
-Does not check to see if quality is valid.
+Does not check to see if quality is valid.
-#Param quality one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
+#Param quality one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
kMedium_SkFilterQuality, kHigh_SkFilterQuality
##
@@ -1700,10 +1737,10 @@ a different arrangement.
#In Color_Methods
#Line # sets Color_Alpha and Color_RGB, one drawing color ##
Sets Alpha and Color_RGB used when stroking and filling. The color is a 32-bit value,
- Unpremultiplied, packing 8-bit components for Alpha, Red, Blue, and Green.
+ Unpremultiplied, packing 8-bit components for Alpha, Red, Blue, and Green.
#Param color Unpremultiplied Color_ARGB ##
-
+
#Example
SkPaint green1, green2;
unsigned a = 255;
@@ -1752,7 +1789,7 @@ Color_Alpha sets the transparency independent of Color_RGB: Color_RGB_Red, Color
#In Alpha_Methods
#Line # sets Color_Alpha, color opacity ##
- Replaces Alpha, leaving Color_RGB
+ Replaces Alpha, leaving Color_RGB
unchanged. An out of range value triggers an assert in the debug
build. a is a value from zero to 255.
a set to zero makes Color fully transparent; a set to 255 makes Color
@@ -1786,7 +1823,7 @@ Color_Alpha sets the transparency independent of Color_RGB: Color_RGB_Red, Color
#Param r amount of Color_RGB_Red, from no red (0) to full red (255) ##
#Param g amount of Color_RGB_Green, from no green (0) to full green (255) ##
#Param b amount of Color_RGB_Blue, from no blue (0) to full blue (255) ##
-
+
#Example
SkPaint transRed1, transRed2;
transRed1.setARGB(255 / 2, 255, 0, 0);
@@ -1838,8 +1875,8 @@ may have gaps, and if kAntiAlias_Flag is set, Color_Alpha will increase to visua
#Alias Hairline # maybe should be Stroke_Hairline ?
Stroke_Width of zero has a special meaning and switches drawing to use Hairline.
-Hairline draws the thinnest continuous frame. If kAntiAlias_Flag is clear, adjacent pixels
-flow horizontally, vertically,or diagonally.
+Hairline draws the thinnest continuous frame. If kAntiAlias_Flag is clear, adjacent pixels
+flow horizontally, vertically,or diagonally.
#ToDo what is the description of Anti-aliased hairlines? ##
@@ -1873,7 +1910,7 @@ a fill draw.
#Const kFill_Style 0
Set to fill geometry.
- Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
+ Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
Bitmap, Image, Patches, Region, Sprites, and Vertices are painted as if
kFill_Style is set, and ignore the set Style.
The Path_Fill_Type specifies additional rules to fill the area outside the path edge,
@@ -1883,7 +1920,7 @@ a fill draw.
#Const kStroke_Style 1
Set to stroke geometry.
- Applies to Rect, Region, Round_Rect, Arcs, Circles, Ovals, Path, and Text.
+ Applies to Rect, Region, Round_Rect, Arcs, Circles, Ovals, Path, and Text.
Arcs, Lines, and points, are always drawn as if kStroke_Style is set,
and ignore the set Style.
The stroke construction is unaffected by the Path_Fill_Type.
@@ -1893,7 +1930,7 @@ a fill draw.
Set to stroke and fill geometry.
Applies to Rect, Region, Round_Rect, Circles, Ovals, Path, and Text.
Path is treated as if it is set to SkPath::kWinding_FillType,
- and the set Path_Fill_Type is ignored.
+ and the set Path_Fill_Type is ignored.
##
#Const kStyleCount 3
@@ -1974,12 +2011,12 @@ May be used to verify that Style is a legal value.
#Line # thickness perpendicular to geometry ##
Stroke_Width sets the width for stroking. The width is the thickness
-of the stroke perpendicular to the path direction when the paint style is
+of the stroke perpendicular to the path direction when the paint style is
set to kStroke_Style or kStrokeAndFill_Style.
When width is greater than zero, the stroke encompasses as many pixels partially
or fully as needed. When the width equals zero, the paint enables hairlines;
-the stroke is always one pixel wide.
+the stroke is always one pixel wide.
The stroke dimensions are scaled by the canvas matrix, but Hairline stroke
remains one pixel wide regardless of scaling.
@@ -1990,12 +2027,12 @@ The default width for the paint is zero.
#Height 170
#Platform raster gpu
#Description
- The pixels hit to represent thin lines vary with the angle of the
+ The pixels hit to represent thin lines vary with the angle of the
line and the platform implementation.
##
void draw(SkCanvas* canvas) {
SkPaint paint;
- for (bool antialias : { false, true }) {
+ for (bool antialias : { false, true }) {
paint.setAntiAlias(antialias);
for (int width = 0; width <= 4; ++width) {
SkScalar offset = antialias * 100 + width * 20;
@@ -2015,7 +2052,7 @@ The default width for the paint is zero.
outline the shape.
#Return zero for Hairline, greater than zero for pen thickness ##
-
+
#Example
SkPaint paint;
SkDebugf("0 %c= paint.getStrokeWidth()\n", 0 == paint.getStrokeWidth() ? '=' : '!');
@@ -2032,10 +2069,10 @@ The default width for the paint is zero.
#In Stroke_Width
#Line # sets thickness of the stroke ##
Sets the thickness of the pen used by the paint to
- outline the shape.
- Has no effect if width is less than zero.
+ outline the shape.
+ Has no effect if width is less than zero.
- #Param width zero thickness for Hairline; greater than zero for pen thickness
+ #Param width zero thickness for Hairline; greater than zero for pen thickness
##
#Example
@@ -2229,7 +2266,7 @@ Stroke_Cap draws at the beginning and end of an open Path_Contour.
##
#Enum ##
-Stroke describes the area covered by a pen of Stroke_Width as it
+Stroke describes the area covered by a pen of Stroke_Width as it
follows the Path_Contour, moving parallel to the contour direction.
If the Path_Contour is not terminated by SkPath::kClose_Verb, the contour has a
@@ -2238,7 +2275,7 @@ visible beginning and end.
Path_Contour may start and end at the same point; defining Zero_Length_Contour.
kButt_Cap and Zero_Length_Contour is not drawn.
-kRound_Cap and Zero_Length_Contour draws a circle of diameter Stroke_Width
+kRound_Cap and Zero_Length_Contour draws a circle of diameter Stroke_Width
at the contour point.
kSquare_Cap and Zero_Length_Contour draws an upright square with a side of
Stroke_Width at the contour point.
@@ -2291,7 +2328,7 @@ Stroke_Cap is kButt_Cap by default.
#Param cap one of: kButt_Cap, kRound_Cap, kSquare_Cap;
has no effect if cap is not valid
- ##
+ ##
#Example
SkPaint paint;
@@ -2299,7 +2336,7 @@ Stroke_Cap is kButt_Cap by default.
paint.setStrokeCap((SkPaint::Cap) SkPaint::kCapCount);
SkDebugf("kRound_Cap %c= paint.getStrokeCap()\n",
SkPaint::kRound_Cap == paint.getStrokeCap() ? '=' : '!');
-
+
#StdOut
kRound_Cap == paint.getStrokeCap()
##
@@ -2315,7 +2352,7 @@ Stroke_Cap is kButt_Cap by default.
Stroke_Join draws at the sharp corners of an open or closed Path_Contour.
-Stroke describes the area covered by a pen of Stroke_Width as it
+Stroke describes the area covered by a pen of Stroke_Width as it
follows the Path_Contour, moving parallel to the contour direction.
If the contour direction changes abruptly, because the tangent direction leading
@@ -2361,7 +2398,7 @@ Choose miter join to draw sharp corners. Choose round join to draw a circle with
radius equal to the stroke width on top of the corner. Choose bevel join to minimally
connect the thick strokes.
-The fill path constructed to describe the stroked path respects the join setting but may
+The fill path constructed to describe the stroked path respects the join setting but may
not contain the actual join. For instance, a fill path constructed with round joins does
not necessarily include circles at each connected segment.
@@ -2384,7 +2421,7 @@ not necessarily include circles at each connected segment.
#Const kDefault_Join 1
Equivalent to kMiter_Join.
- Stroke_Join is set to kMiter_Join by default.
+ Stroke_Join is set to kMiter_Join by default.
##
#Const kJoinCount 3
@@ -2445,7 +2482,7 @@ void draw(SkCanvas* canvas) {
The geometry drawn at the corners of strokes.
#Param join one of: kMiter_Join, kRound_Join, kBevel_Join;
- otherwise, has no effect
+ otherwise, has no effect
##
#Example
@@ -2479,11 +2516,11 @@ destination Path.
Fill Path can request the Path_Effect to restrict to a culling rectangle, but
the Path_Effect is not required to do so.
-If Style is kStroke_Style or kStrokeAndFill_Style,
+If Style is kStroke_Style or kStrokeAndFill_Style,
and Stroke_Width is greater than zero, the Stroke_Width, Stroke_Cap, Stroke_Join,
and Miter_Limit operate on the destination Path, replacing it.
-Fill Path can specify the precision used by Stroke_Width to approximate the stroke geometry.
+Fill Path can specify the precision used by Stroke_Width to approximate the stroke geometry.
If the Style is kStroke_Style and the Stroke_Width is zero, getFillPath
returns false since Hairline has no filled equivalent.
@@ -2507,7 +2544,7 @@ returns false since Hairline has no filled equivalent.
#Height 192
#Description
A very small Quad stroke is turned into a filled path with increasing levels of precision.
- At the lowest precision, the Quad stroke is approximated by a rectangle.
+ At the lowest precision, the Quad stroke is approximated by a rectangle.
At the highest precision, the filled path has high fidelity compared to the original stroke.
##
void draw(SkCanvas* canvas) {
@@ -2578,7 +2615,7 @@ returns false since Hairline has no filled equivalent.
Shader defines the colors used when drawing a shape.
Shader may be an image, a gradient, or a computed fill.
-If Paint has no Shader, then Color fills the shape.
+If Paint has no Shader, then Color fills the shape.
Shader is modulated by Color_Alpha component of Color.
If Shader object defines only Color_Alpha, then Color modulated by Color_Alpha describes
@@ -2611,7 +2648,7 @@ void draw(SkCanvas* canvas) {
bitmap.setInfo(SkImageInfo::MakeA8(5, 1), 5); // bitmap only contains alpha
uint8_t pixels[5] = { 0x22, 0x55, 0x88, 0xBB, 0xFF };
bitmap.setPixels(pixels);
- paint.setShader(SkShader::MakeBitmapShader(bitmap,
+ paint.setShader(SkShader::MakeBitmapShader(bitmap,
SkShader::kMirror_TileMode, SkShader::kMirror_TileMode));
for (SkColor c : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
paint.setColor(c); // all components in color affect shader
@@ -2628,7 +2665,7 @@ void draw(SkCanvas* canvas) {
Optional colors used when filling a path, such as a gradient.
Does not alter Shader Reference_Count.
-
+
#Return Shader if previously set, nullptr otherwise ##
#Example
@@ -2732,7 +2769,7 @@ void draw(SkCanvas* canvas) {
#Line # returns Color_Filter, how colors are altered ##
Returns Color_Filter if set, or nullptr.
Does not alter Color_Filter Reference_Count.
-
+
#Return Color_Filter if previously set, nullptr otherwise ##
#Example
@@ -2839,10 +2876,10 @@ void draw(SkCanvas* canvas) {
#Example
void draw(SkCanvas* canvas) {
SkPaint paint;
- SkDebugf("kSrcOver %c= getBlendMode\n",
+ SkDebugf("kSrcOver %c= getBlendMode\n",
SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
paint.setBlendMode(SkBlendMode::kSrc);
- SkDebugf("kSrcOver %c= getBlendMode\n",
+ SkDebugf("kSrcOver %c= getBlendMode\n",
SkBlendMode::kSrcOver == paint.getBlendMode() ? '=' : '!');
}
@@ -2882,7 +2919,7 @@ void draw(SkCanvas* canvas) {
#In Blend_Mode_Methods
#Line # sets Blend_Mode, how colors combine with destination ##
- Sets Blend_Mode to mode.
+ Sets Blend_Mode to mode.
Does not check for valid input.
#Param mode SkBlendMode used to combine source color and destination ##
@@ -2932,7 +2969,7 @@ If Paint has no Path_Effect, the path geometry is unaltered when filled or strok
#Line # returns Path_Effect, modifications to path geometry; dashing ##
Returns Path_Effect if set, or nullptr.
Does not alter Path_Effect Reference_Count.
-
+
#Return Path_Effect if previously set, nullptr otherwise ##
#Example
@@ -3027,7 +3064,7 @@ modifying the draw.
#Line # returns Mask_Filter, alterations to Mask_Alpha ##
Returns Mask_Filter if set, or nullptr.
Does not alter Mask_Filter Reference_Count.
-
+
#Return Mask_Filter if previously set, nullptr otherwise ##
#Example
@@ -3053,7 +3090,7 @@ modifying the draw.
Returns Mask_Filter if set, or nullptr.
Increases Mask_Filter Reference_Count by one.
-
+
#Return Mask_Filter if previously set, nullptr otherwise ##
#Example
@@ -3127,7 +3164,7 @@ implementation.
#Line # returns Typeface, font description ##
Returns Typeface if set, or nullptr.
Increments Typeface Reference_Count by one.
-
+
#Return Typeface if previously set, nullptr otherwise ##
#Example
@@ -3157,7 +3194,7 @@ implementation.
#Example
void draw(SkCanvas* canvas) {
SkPaint paint1, paint2;
- paint1.setTypeface(SkTypeface::MakeFromName("monospace",
+ paint1.setTypeface(SkTypeface::MakeFromName("monospace",
SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
SkFontStyle::kItalic_Slant)));
SkDebugf("typeface1 %c= typeface2\n",
@@ -3179,7 +3216,7 @@ implementation.
#In Typeface_Methods
#Line # sets Typeface, font description ##
-Sets Typeface to typeface, decreasing Reference_Count of the previous Typeface.
+Sets Typeface to typeface, decreasing Reference_Count of the previous Typeface.
Pass nullptr to clear Typeface and use the default typeface. Increments
typeface Reference_Count by one.
@@ -3236,7 +3273,7 @@ Mask_Filter.
#Line # returns Image_Filter, alter pixels; blur ##
Returns Image_Filter if set, or nullptr.
Does not alter Image_Filter Reference_Count.
-
+
#Return Image_Filter if previously set, nullptr otherwise ##
#Example
@@ -3324,7 +3361,7 @@ to another to construct the draw.
Draw_Looper draws one or more times, modifying the canvas and paint each time.
Draw_Looper may be used to draw multiple colors or create a colored shadow.
-Set Draw_Looper to nullptr to prevent Draw_Looper from modifying the draw.
+Set Draw_Looper to nullptr to prevent Draw_Looper from modifying the draw.
#Example
#Height 128
@@ -3351,7 +3388,7 @@ Set Draw_Looper to nullptr to prevent Draw_Looper from modifying the draw.
#Line # returns Draw_Looper, multiple layers ##
Returns Draw_Looper if set, or nullptr.
Does not alter Draw_Looper Reference_Count.
-
+
#Return Draw_Looper if previously set, nullptr otherwise ##
#Example
@@ -3454,9 +3491,9 @@ Increments drawLooper Reference_Count by one.
Align adjusts the text relative to the text position.
Align affects Glyphs drawn with: SkCanvas::drawText, SkCanvas::drawPosText,
-SkCanvas::drawPosTextH, SkCanvas::drawTextOnPath,
+SkCanvas::drawPosTextH, SkCanvas::drawTextOnPath,
SkCanvas::drawTextOnPathHV, SkCanvas::drawTextRSXform, SkCanvas::drawTextBlob,
-and SkCanvas::drawString;
+and SkCanvas::drawString;
as well as calls that place text Glyphs like getTextWidths and getTextPath.
The text position is set by the font for both horizontal and vertical text.
@@ -3464,7 +3501,7 @@ Typically, for horizontal text, the position is to the left side of the glyph on
base line; and for vertical text, the position is the horizontal center of the glyph
at the caps height.
-Align adjusts the glyph position to center it or move it to abut the position
+Align adjusts the glyph position to center it or move it to abut the position
using the metrics returned by the font.
Align defaults to kLeft_Align.
@@ -3617,7 +3654,7 @@ Set SkPaintDefaults_TextSize at compile time to change the default setting.
#Line # sets text size in points ##
Sets Text_Size in points.
Has no effect if textSize is not greater than or equal to zero.
-
+
#Param textSize typographic height of text ##
#Example
@@ -3678,7 +3715,7 @@ Text_Scale_X defaults to 1.
#Line # sets the text horizontal scale; condensed text ##
Sets Text_Scale_X.
Default value is 1.
-
+
#Param scaleX text horizontal scale ##
#Example
@@ -3785,7 +3822,7 @@ in the total storage required.
#A UTF-32 # http://www.unicode.org/versions/Unicode5.0.0/ch03.pdf ##
encodes each character as one 32-bit word.
-Font_Manager uses font data to convert character code points into glyph indices.
+Font_Manager uses font data to convert character code points into glyph indices.
A glyph index is a 16-bit word.
TextEncoding is set to kUTF8_TextEncoding by default.
@@ -3838,16 +3875,16 @@ void draw(SkCanvas* canvas) {
Returns Text_Encoding.
Text_Encoding determines how character code points are mapped to font glyph indices.
- #Return one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
- kGlyphID_TextEncoding
+ #Return one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
+ kGlyphID_TextEncoding
##
#Example
SkPaint paint;
- SkDebugf("kUTF8_TextEncoding %c= text encoding\n",
+ SkDebugf("kUTF8_TextEncoding %c= text encoding\n",
SkPaint::kUTF8_TextEncoding == paint.getTextEncoding() ? '=' : '!');
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- SkDebugf("kGlyphID_TextEncoding %c= text encoding\n",
+ SkDebugf("kGlyphID_TextEncoding %c= text encoding\n",
SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding() ? '=' : '!');
#StdOut
@@ -3863,12 +3900,12 @@ void draw(SkCanvas* canvas) {
#In Text_Encoding
#Line # sets character or glyph encoded size ##
- Sets Text_Encoding to encoding.
+ Sets Text_Encoding to encoding.
Text_Encoding determines how character code points are mapped to font glyph indices.
Invalid values for encoding are ignored.
- #Param encoding one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
- kGlyphID_TextEncoding
+ #Param encoding one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
+ kGlyphID_TextEncoding
#Param ##
#Example
@@ -3889,7 +3926,7 @@ void draw(SkCanvas* canvas) {
#Line # common glyph dimensions ##
Font_Metrics describe dimensions common to the Glyphs in Typeface.
-The dimensions are computed by Font_Manager from font data and do not take
+The dimensions are computed by Font_Manager from font data and do not take
Paint settings other than Text_Size into account.
Font dimensions specify the anchor to the left of the glyph at baseline as the origin.
@@ -4242,12 +4279,12 @@ void draw(SkCanvas* canvas) {
#In Font_Metrics
#Line # returns union all glyph bounds ##
Returns the union of bounds of all Glyphs.
-Returned dimensions are computed by Font_Manager from font data,
+Returned dimensions are computed by Font_Manager from font data,
ignoring Hinting. Includes Text_Size, Text_Scale_X,
and Text_Skew_X, but not Fake_Bold or Path_Effect.
If Text_Size is large, Text_Scale_X is one, and Text_Skew_X is zero,
-returns the same bounds as Font_Metrics { FontMetrics::fXMin,
+returns the same bounds as Font_Metrics { FontMetrics::fXMin,
FontMetrics::fTop, FontMetrics::fXMax, FontMetrics::fBottom }.
#Return union of bounds of all Glyphs ##
@@ -4340,7 +4377,7 @@ text contains an invalid UTF-8 sequence, zero is returned.
#Method bool containsText(const void* text, size_t byteLength) const
#In Utility
#Line # returns if all text corresponds to Glyphs ##
- Returns true if all text corresponds to a non-zero glyph index.
+ Returns true if all text corresponds to a non-zero glyph index.
Returns false if any characters in text are not supported in
Typeface.
@@ -4364,7 +4401,7 @@ text contains an invalid UTF-8 sequence, zero is returned.
const uint16_t goodChar = 0x00B0; // degree symbol
const uint16_t badChar = 0xD800; // Unicode surrogate
paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
- SkDebugf("0x%04x %c= has char\n", goodChar,
+ SkDebugf("0x%04x %c= has char\n", goodChar,
paint.containsText(&goodChar, 2) ? '=' : '!');
SkDebugf("0x%04x %c= has char\n", badChar,
paint.containsText(&badChar, 2) ? '=' : '!');
@@ -4385,7 +4422,7 @@ text contains an invalid UTF-8 sequence, zero is returned.
const uint16_t zeroGlyph = 0;
const uint16_t badGlyph = 65535; // larger than glyph count in font
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- SkDebugf("0x%04x %c= has glyph\n", goodGlyph,
+ SkDebugf("0x%04x %c= has glyph\n", goodGlyph,
paint.containsText(&goodGlyph, 2) ? '=' : '!');
SkDebugf("0x%04x %c= has glyph\n", zeroGlyph,
paint.containsText(&zeroGlyph, 2) ? '=' : '!');
@@ -4410,8 +4447,8 @@ text contains an invalid UTF-8 sequence, zero is returned.
#In Utility
#Line # converts Glyphs into text ##
- Converts glyphs into text if possible.
- Glyph values without direct Unicode equivalents are mapped to zero.
+ Converts glyphs into text if possible.
+ Glyph values without direct Unicode equivalents are mapped to zero.
Uses the Typeface, but is unaffected
by Text_Encoding; the text values returned are equivalent to kUTF32_TextEncoding.
@@ -4459,7 +4496,7 @@ text contains an invalid UTF-8 sequence, zero is returned.
Path_Effect to scale the metrics and bounds.
Returns the bounding box of text if bounds is not nullptr.
The bounding box is computed as if the text was drawn at the origin.
-
+
#Param text character codes or glyph indices to be measured ##
#Param length number of bytes of text to measure ##
#Param bounds returns bounding box relative to (0, 0) if not nullptr ##
@@ -4535,7 +4572,7 @@ text contains an invalid UTF-8 sequence, zero is returned.
#Param maxWidth advance limit; text is measured while advance is less than maxWidth ##
#Param measuredWidth returns the width of the text less than or equal to maxWidth ##
#Return bytes of text that fit, always less than or equal to length ##
-
+
#Example
#Description
Line under "Breakfast" shows desired width, shorter than available characters.
@@ -4569,19 +4606,19 @@ text contains an invalid UTF-8 sequence, zero is returned.
the glyph count in text.
Both widths and bounds may be nullptr.
If widths is not nullptr, widths must be an array of glyph count entries.
- if bounds is not nullptr, bounds must be an array of glyph count entries.
+ if bounds is not nullptr, bounds must be an array of glyph count entries.
If kVerticalText_Flag is clear, widths returns the horizontal advance.
If kVerticalText_Flag is set, widths returns the vertical advance.
Uses Text_Encoding to decode text, Typeface to get the font metrics,
and Text_Size to scale the widths and bounds.
Does not scale the advance by Fake_Bold or Path_Effect.
Does include Fake_Bold and Path_Effect in the bounds.
-
+
#Param text character codes or glyph indices to be measured ##
#Param byteLength number of bytes of text to measure ##
#Param widths returns text advances for each glyph; may be nullptr ##
#Param bounds returns bounds for each glyph relative to (0, 0); may be nullptr ##
-
+
#Return glyph count in text ##
#Example
@@ -4721,13 +4758,13 @@ underline that skips Descenders.
Returns the number of intervals that intersect bounds.
bounds describes a pair of lines parallel to the text advance.
The return count is zero or a multiple of two, and is at most twice the number of Glyphs in
- the string.
+ the string.
Uses Text_Encoding to decode text, Typeface to get the glyph paths,
and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
Uses x, y, and Text_Align to position intervals.
-
+
Pass nullptr for intervals to determine the size of the interval array.
-
+
intervals are cached to improve performance for multiple calls.
#Param text character codes or glyph indices ##
@@ -4776,13 +4813,13 @@ void draw(SkCanvas* canvas) {
Returns the number of intervals that intersect bounds.
bounds describes a pair of lines parallel to the text advance.
The return count is zero or a multiple of two, and is at most twice the number of Glyphs in
- the string.
+ the string.
Uses Text_Encoding to decode text, Typeface to get the glyph paths,
and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
Uses pos array and Text_Align to position intervals.
-
+
Pass nullptr for intervals to determine the size of the interval array.
-
+
intervals are cached to improve performance for multiple calls.
#Param text character codes or glyph indices ##
@@ -4831,13 +4868,13 @@ void draw(SkCanvas* canvas) {
Returns the number of intervals that intersect bounds.
bounds describes a pair of lines parallel to the text advance.
The return count is zero or a multiple of two, and is at most twice the number of Glyphs in
- the string.
+ the string.
Uses Text_Encoding to decode text, Typeface to get the glyph paths,
and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
Uses xpos array, constY, and Text_Align to position intervals.
-
+
Pass nullptr for intervals to determine the size of the interval array.
-
+
intervals are cached to improve performance for multiple calls.
#Param text character codes or glyph indices ##
@@ -4891,15 +4928,15 @@ void draw(SkCanvas* canvas) {
Returns the number of intervals that intersect bounds.
bounds describes a pair of lines parallel to the text advance.
The return count is zero or a multiple of two, and is at most twice the number of Glyphs in
- the string.
+ the string.
Uses Typeface to get the glyph paths,
and Text_Size, Fake_Bold, and Path_Effect to scale and modify the glyph paths.
Uses run array and Text_Align to position intervals.
-
+
Text_Encoding must be set to SkPaint::kGlyphID_TextEncoding.
Pass nullptr for intervals to determine the size of the interval array.
-
+
intervals are cached to improve performance for multiple calls.
#Param blob Glyphs, positions, and text paint attributes ##
@@ -4917,11 +4954,11 @@ void draw(SkCanvas* canvas) {
SkPoint textPos = { 20, 110 };
int len = 3;
SkTextBlobBuilder textBlobBuilder;
- const SkTextBlobBuilder::RunBuffer& run =
+ const SkTextBlobBuilder::RunBuffer& run =
textBlobBuilder.allocRun(paint, len, textPos.fX, textPos.fY);
run.glyphs[0] = 10;
run.glyphs[1] = 20;
- run.glyphs[2] = 30;
+ run.glyphs[2] = 30;
sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
canvas->drawTextBlob(blob.get(), textPos.fX, textPos.fY, paint);
SkScalar bounds[] = { 116, 134 };
@@ -4959,7 +4996,7 @@ void draw(SkCanvas* canvas) {
#Example
void draw(SkCanvas* canvas) {
auto debugster = [](const char* prefix, const SkPaint& p) -> void {
- SkDebugf("%s nothing to draw: %s\n", prefix,
+ SkDebugf("%s nothing to draw: %s\n", prefix,
p.nothingToDraw() ? "true" : "false");
};
SkPaint paint;
@@ -4985,18 +5022,18 @@ void draw(SkCanvas* canvas) {
# ------------------------------------------------------------------------------
#Subtopic Fast_Bounds
#Line # approximate area required by Paint ##
- #Private
- To be made private.
+ #Private
+ To be made private.
##
Fast_Bounds methods conservatively outset a drawing bounds by additional area
Paint may draw to.
#Method bool canComputeFastBounds() const
-
+
#In Fast_Bounds
#Line # returns true if settings allow for fast bounds computation ##
- #Private
+ #Private
(to be made private)
##
@@ -5008,10 +5045,10 @@ Paint may draw to.
##
#Method const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const
-
+
#In Fast_Bounds
#Line # returns fill bounds for quick reject tests ##
- #Private
+ #Private
(to be made private)
##
@@ -5026,7 +5063,7 @@ Paint may draw to.
use the returned value. It is legal for orig and storage to be the same
Rect.
- #Private
+ #Private
e.g.
if (paint.canComputeFastBounds()) {
SkRect r, storage;
@@ -5048,7 +5085,7 @@ Paint may draw to.
SkRect* storage) const
#In Fast_Bounds
#Line # returns stroke bounds for quick reject tests ##
- #Private
+ #Private
(to be made private)
##
@@ -5062,7 +5099,7 @@ Paint may draw to.
Style style) const
#In Fast_Bounds
#Line # returns bounds for quick reject tests ##
- #Private
+ #Private
(to be made private)
##
diff --git a/gn/core.gni b/gn/core.gni
index cb7f63d3de..d396105c88 100644
--- a/gn/core.gni
+++ b/gn/core.gni
@@ -20,6 +20,7 @@ skia_core_sources = [
"$_src/core/SkAntiRun.h",
"$_src/core/SkATrace.cpp",
"$_src/core/SkATrace.h",
+ "$_src/core/SkAutoKern.h",
"$_src/core/SkAutoPixmapStorage.h",
"$_src/core/SkAutoPixmapStorage.cpp",
"$_src/core/SkBBHFactory.cpp",
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index a564824448..7a65e2ca47 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -451,7 +451,9 @@ public:
@return kDevKernText_Flag state
*/
- bool isDevKernText() const { return false; }
+ bool isDevKernText() const {
+ return SkToBool(this->getFlags() & kDevKernText_Flag);
+ }
/** Requests, but does not require, to use hinting to adjust glyph spacing.
@@ -460,7 +462,7 @@ public:
@param devKernText setting for devKernText
*/
- void setDevKernText(bool) { }
+ void setDevKernText(bool devKernText);
/** Returns SkFilterQuality, the image filtering level. A lower setting
draws faster; a higher setting looks better when the image is scaled.
@@ -1643,6 +1645,7 @@ private:
};
static GlyphCacheProc GetGlyphCacheProc(TextEncoding encoding,
+ bool isDevKern,
bool needFullMetrics);
SkScalar measure_text(SkGlyphCache*, const char* text, size_t length,
diff --git a/samplecode/SampleText.cpp b/samplecode/SampleText.cpp
index 1b67103ffd..bb3507ef41 100644
--- a/samplecode/SampleText.cpp
+++ b/samplecode/SampleText.cpp
@@ -92,7 +92,8 @@ protected:
SkPaint paint;
const char* s = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit";
- paint.setFlags(paint.getFlags() | SkPaint::kAntiAlias_Flag);
+ paint.setFlags(paint.getFlags() | SkPaint::kAntiAlias_Flag
+ | SkPaint::kDevKernText_Flag);
paint.setTextSize(SkIntToScalar(14));
canvas.drawString(s, SkIntToScalar(8), SkIntToScalar(14), paint);
}
diff --git a/src/core/SkAutoKern.h b/src/core/SkAutoKern.h
new file mode 100644
index 0000000000..8b032519b3
--- /dev/null
+++ b/src/core/SkAutoKern.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkAutoKern_DEFINED
+#define SkAutoKern_DEFINED
+
+#include "SkGlyph.h"
+
+#define SkAutoKern_Adjust(prev, next) SkIntToScalar(((next) - (prev) + 32) >> 6)
+
+/* this is a helper class to perform auto-kerning
+ * the adjust() method returns a SkScalar corresponding
+ * to a +1/0/-1 pixel adjustment
+ */
+
+class SkAutoKern {
+public:
+ SkAutoKern() : fPrevRsbDelta(0) {}
+
+ SkScalar adjust(const SkGlyph& glyph)
+ {
+// if (SkAbs32(glyph.fLsbDelta) > 47 || SkAbs32(glyph.fRsbDelta) > 47)
+// printf("------- %d> L %d R %d\n", glyph.f_GlyphID, glyph.fLsbDelta, glyph.fRsbDelta);
+
+#if 0
+ int distort = fPrevRsbDelta - glyph.fLsbDelta;
+
+ fPrevRsbDelta = glyph.fRsbDelta;
+
+ if (distort >= 32)
+ return -SK_Scalar1;
+ else if (distort < -32)
+ return +SK_Scalar1;
+ else
+ return 0;
+#else
+ SkScalar adjust = SkAutoKern_Adjust(fPrevRsbDelta, glyph.fLsbDelta);
+ fPrevRsbDelta = glyph.fRsbDelta;
+ return adjust;
+#endif
+ }
+private:
+ int fPrevRsbDelta;
+};
+
+#endif
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index 0526f76f8e..e3c81ba258 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -1571,6 +1571,7 @@ void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength, const SkS
paint.setPathEffect(nullptr);
SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(),
+ paint.isDevKernText(),
true);
auto cache = SkStrikeCache::FindOrCreateStrikeExclusive(
paint, props, this->scalerContextFlags(), nullptr);
diff --git a/src/core/SkFindAndPlaceGlyph.h b/src/core/SkFindAndPlaceGlyph.h
index 00417152ab..d92edb6b17 100644
--- a/src/core/SkFindAndPlaceGlyph.h
+++ b/src/core/SkFindAndPlaceGlyph.h
@@ -9,6 +9,7 @@
#define SkFindAndPositionGlyph_DEFINED
#include "SkArenaAlloc.h"
+#include "SkAutoKern.h"
#include "SkGlyph.h"
#include "SkGlyphCache.h"
#include "SkMatrixPriv.h"
@@ -319,8 +320,8 @@ private:
virtual ~GlyphFindAndPlaceInterface() { }
// findAndPositionGlyph calculates the position of the glyph, finds the glyph, and
- // returns the position of where the next glyph will be using the glyph's advance. The
- // returned position is used by drawText, but ignored by drawPosText.
+ // returns the position of where the next glyph will be using the glyph's advance and
+ // possibly kerning. The returned position is used by drawText, but ignored by drawPosText.
// The compiler should prune all this calculation if the return value is not used.
//
// This should be a pure virtual, but some versions of GCC <= 4.8 have a bug that causes a
@@ -382,20 +383,31 @@ private:
GlyphFinderInterface* fGlyphFinder;
};
+ enum SelectKerning {
+ kNoKerning = false,
+ kUseKerning = true
+ };
+
// GlyphFindAndPlaceFullPixel handles finding and placing glyphs when no sub-pixel
- // positioning is requested.
- template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment>
+ // positioning is requested. The kUseKerning argument should be true for drawText, and false
+ // for drawPosText.
+ template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment, SelectKerning kUseKerning>
class GlyphFindAndPlaceFullPixel final : public GlyphFindAndPlaceInterface<ProcessOneGlyph> {
public:
explicit GlyphFindAndPlaceFullPixel(GlyphFinderInterface* glyphFinder)
: fGlyphFinder(glyphFinder) {
+ // Kerning can only be used with SkPaint::kLeft_Align
+ static_assert(!kUseKerning || SkPaint::kLeft_Align == kTextAlignment,
+ "Kerning can only be used with left aligned text.");
}
SkPoint findAndPositionGlyph(
const char** text, SkPoint position, ProcessOneGlyph&& processOneGlyph) override {
SkPoint finalPosition = position;
const SkGlyph& glyph = fGlyphFinder->lookupGlyph(text);
-
+ if (kUseKerning) {
+ finalPosition += {fAutoKern.adjust(glyph), 0.0f};
+ }
if (glyph.fWidth > 0) {
finalPosition -= TextAlignmentAdjustment(kTextAlignment, glyph);
processOneGlyph(glyph, finalPosition, {SK_ScalarHalf, SK_ScalarHalf});
@@ -406,6 +418,8 @@ private:
private:
GlyphFinderInterface* fGlyphFinder;
+
+ SkAutoKern fAutoKern;
};
template <typename ProcessOneGlyph, SkPaint::Align kTextAlignment>
@@ -432,12 +446,14 @@ private:
SkScalar x = 0, y = 0;
const char* stop = text + byteLength;
+ SkAutoKern autokern;
+
while (text < stop) {
// don't need x, y here, since all subpixel variants will have the
// same advance
const SkGlyph& glyph = glyphFinder->lookupGlyph(&text);
- x += SkFloatToScalar(glyph.fAdvanceX);
+ x += autokern.adjust(glyph) + SkFloatToScalar(glyph.fAdvanceX);
y += SkFloatToScalar(glyph.fAdvanceY);
}
SkASSERT(text == stop);
@@ -527,17 +543,18 @@ inline void SkFindAndPlaceGlyph::ProcessPosText(
switch (textAlignment) {
case SkPaint::kLeft_Align:
findAndPosition = arena.make<
- GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kLeft_Align>>(glyphFinder);
+ GlyphFindAndPlaceFullPixel<ProcessOneGlyph,
+ SkPaint::kLeft_Align, kNoKerning>>(glyphFinder);
break;
case SkPaint::kCenter_Align:
findAndPosition = arena.make<
GlyphFindAndPlaceFullPixel<ProcessOneGlyph,
- SkPaint::kCenter_Align>>(glyphFinder);
+ SkPaint::kCenter_Align, kNoKerning>>(glyphFinder);
break;
case SkPaint::kRight_Align:
findAndPosition = arena.make<
GlyphFindAndPlaceFullPixel<ProcessOneGlyph,
- SkPaint::kRight_Align>>(glyphFinder);
+ SkPaint::kRight_Align, kNoKerning>>(glyphFinder);
break;
}
}
@@ -578,7 +595,8 @@ inline void SkFindAndPlaceGlyph::ProcessText(
findAndPosition = getSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align>(
&arena, axisAlignment, glyphFinder);
} else {
- using FullPixel = GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kLeft_Align>;
+ using FullPixel =
+ GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kLeft_Align, kUseKerning>;
findAndPosition = arena.make<FullPixel>(glyphFinder);
}
diff --git a/src/core/SkGlyph.cpp b/src/core/SkGlyph.cpp
index 33246cc2dc..2abe98aa1e 100644
--- a/src/core/SkGlyph.cpp
+++ b/src/core/SkGlyph.cpp
@@ -31,6 +31,8 @@ void SkGlyph::zeroMetrics() {
fHeight = 0;
fTop = 0;
fLeft = 0;
+ fRsbDelta = 0;
+ fLsbDelta = 0;
}
static size_t bits_to_bytes(size_t bits) {
diff --git a/src/core/SkGlyph.h b/src/core/SkGlyph.h
index 87cd852bd8..211039e520 100644
--- a/src/core/SkGlyph.h
+++ b/src/core/SkGlyph.h
@@ -131,6 +131,7 @@ struct SkPackedUnicharID : public SkPackedID {
}
};
+SK_BEGIN_REQUIRE_DENSE
class SkGlyph {
// Support horizontal and vertical skipping strike-through / underlines.
// The caller walks the linked list looking for a match. For a horizontal underline,
@@ -158,9 +159,7 @@ public:
int16_t fTop, fLeft;
uint8_t fMaskFormat;
-#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
int8_t fRsbDelta, fLsbDelta; // used by auto-kerning
-#endif
int8_t fForceBW;
void initWithGlyphID(SkPackedGlyphID glyph_id);
@@ -225,5 +224,6 @@ public:
#endif
SkPackedGlyphID fID;
};
+SK_END_REQUIRE_DENSE
#endif
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index ab3e2da9b5..141b60b252 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -7,6 +7,7 @@
#include "SkPaint.h"
#include "SkPaintPriv.h"
+#include "SkAutoKern.h"
#include "SkColorFilter.h"
#include "SkData.h"
#include "SkDraw.h"
@@ -244,6 +245,10 @@ void SkPaint::setFakeBoldText(bool doFakeBold) {
this->setFlags(set_clear_mask(fBitfields.fFlags, doFakeBold, kFakeBoldText_Flag));
}
+void SkPaint::setDevKernText(bool doDevKern) {
+ this->setFlags(set_clear_mask(fBitfields.fFlags, doDevKern, kDevKernText_Flag));
+}
+
void SkPaint::setStyle(Style style) {
if ((unsigned)style < kStyleCount) {
fBitfields.fStyle = style;
@@ -620,7 +625,8 @@ static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
}
SkPaint::GlyphCacheProc SkPaint::GetGlyphCacheProc(TextEncoding encoding,
- bool needFullMetrics) {
+ bool isDevKern,
+ bool needFullMetrics) {
static const GlyphCacheProc gGlyphCacheProcs[] = {
sk_getMetrics_utf8_next,
sk_getMetrics_utf16_next,
@@ -635,7 +641,7 @@ SkPaint::GlyphCacheProc SkPaint::GetGlyphCacheProc(TextEncoding encoding,
unsigned index = encoding;
- if (!needFullMetrics) {
+ if (!needFullMetrics && !isDevKern) {
index += 4;
}
@@ -646,6 +652,7 @@ SkPaint::GlyphCacheProc SkPaint::GetGlyphCacheProc(TextEncoding encoding,
///////////////////////////////////////////////////////////////////////////////
#define TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE ( \
+SkPaint::kDevKernText_Flag | \
SkPaint::kLinearText_Flag | \
SkPaint::kLCDRenderText_Flag | \
SkPaint::kEmbeddedBitmapText_Flag | \
@@ -732,6 +739,7 @@ SkScalar SkPaint::measure_text(SkGlyphCache* cache,
}
GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(this->getTextEncoding(),
+ this->isDevKernText(),
nullptr != bounds);
int xyIndex;
@@ -750,16 +758,33 @@ SkScalar SkPaint::measure_text(SkGlyphCache* cache,
SkScalar x = advance(*g, xyIndex);
if (nullptr == bounds) {
- for (; text < stop; n++) {
- x += advance(glyphCacheProc(cache, &text), xyIndex);
+ if (this->isDevKernText()) {
+ for (; text < stop; n++) {
+ const int rsb = g->fRsbDelta;
+ g = &glyphCacheProc(cache, &text);
+ x += SkAutoKern_Adjust(rsb, g->fLsbDelta) + advance(*g, xyIndex);
+ }
+ } else {
+ for (; text < stop; n++) {
+ x += advance(glyphCacheProc(cache, &text), xyIndex);
+ }
}
} else {
set_bounds(*g, bounds);
-
- for (; text < stop; n++) {
- g = &glyphCacheProc(cache, &text);
- joinBoundsProc(*g, bounds, x);
- x += advance(*g, xyIndex);
+ if (this->isDevKernText()) {
+ for (; text < stop; n++) {
+ const int rsb = g->fRsbDelta;
+ g = &glyphCacheProc(cache, &text);
+ x += SkAutoKern_Adjust(rsb, g->fLsbDelta);
+ joinBoundsProc(*g, bounds, x);
+ x += advance(*g, xyIndex);
+ }
+ } else {
+ for (; text < stop; n++) {
+ g = &glyphCacheProc(cache, &text);
+ joinBoundsProc(*g, bounds, x);
+ x += advance(*g, xyIndex);
+ }
}
}
SkASSERT(text == stop);
@@ -832,17 +857,33 @@ size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
auto cache = SkStrikeCache::FindOrCreateStrikeExclusive(paint);
GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(),
+ paint.isDevKernText(),
false);
const int xyIndex = paint.isVerticalText() ? 1 : 0;
SkScalar width = 0;
- while (text < stop) {
- const char* curr = text;
- SkScalar x = advance(glyphCacheProc(cache.get(), &text), xyIndex);
- if ((width += x) > maxWidth) {
- width -= x;
- text = curr;
- break;
+ if (this->isDevKernText()) {
+ int rsb = 0;
+ while (text < stop) {
+ const char* curr = text;
+ const SkGlyph& g = glyphCacheProc(cache.get(), &text);
+ SkScalar x = SkAutoKern_Adjust(rsb, g.fLsbDelta) + advance(g, xyIndex);
+ if ((width += x) > maxWidth) {
+ width -= x;
+ text = curr;
+ break;
+ }
+ rsb = g.fRsbDelta;
+ }
+ } else {
+ while (text < stop) {
+ const char* curr = text;
+ SkScalar x = advance(glyphCacheProc(cache.get(), &text), xyIndex);
+ if ((width += x) > maxWidth) {
+ width -= x;
+ text = curr;
+ break;
+ }
}
}
@@ -920,6 +961,7 @@ int SkPaint::getTextWidths(const void* textData, size_t byteLength,
auto cache = SkStrikeCache::FindOrCreateStrikeExclusive(paint);
GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(),
+ paint.isDevKernText(),
nullptr != bounds);
const char* text = (const char*)textData;
@@ -927,27 +969,73 @@ int SkPaint::getTextWidths(const void* textData, size_t byteLength,
int count = 0;
const int xyIndex = paint.isVerticalText() ? 1 : 0;
- if (scale) {
- while (text < stop) {
- const SkGlyph& g = glyphCacheProc(cache.get(), &text);
- if (widths) {
- *widths++ = advance(g, xyIndex) * scale;
+ if (this->isDevKernText()) {
+ // we adjust the widths returned here through auto-kerning
+ SkAutoKern autokern;
+ SkScalar prevWidth = 0;
+
+ if (scale) {
+ while (text < stop) {
+ const SkGlyph& g = glyphCacheProc(cache.get(), &text);
+ if (widths) {
+ SkScalar adjust = autokern.adjust(g);
+
+ if (count > 0) {
+ *widths++ = (prevWidth + adjust) * scale;
+ }
+ prevWidth = advance(g, xyIndex);
+ }
+ if (bounds) {
+ set_bounds(g, bounds++, scale);
+ }
+ ++count;
}
- if (bounds) {
- set_bounds(g, bounds++, scale);
+ if (count > 0 && widths) {
+ *widths = prevWidth * scale;
+ }
+ } else {
+ while (text < stop) {
+ const SkGlyph& g = glyphCacheProc(cache.get(), &text);
+ if (widths) {
+ SkScalar adjust = autokern.adjust(g);
+
+ if (count > 0) {
+ *widths++ = prevWidth + adjust;
+ }
+ prevWidth = advance(g, xyIndex);
+ }
+ if (bounds) {
+ set_bounds(g, bounds++);
+ }
+ ++count;
+ }
+ if (count > 0 && widths) {
+ *widths = prevWidth;
}
- ++count;
}
- } else {
- while (text < stop) {
- const SkGlyph& g = glyphCacheProc(cache.get(), &text);
- if (widths) {
- *widths++ = advance(g, xyIndex);
+ } else { // no devkern
+ if (scale) {
+ while (text < stop) {
+ const SkGlyph& g = glyphCacheProc(cache.get(), &text);
+ if (widths) {
+ *widths++ = advance(g, xyIndex) * scale;
+ }
+ if (bounds) {
+ set_bounds(g, bounds++, scale);
+ }
+ ++count;
}
- if (bounds) {
- set_bounds(g, bounds++);
+ } else {
+ while (text < stop) {
+ const SkGlyph& g = glyphCacheProc(cache.get(), &text);
+ if (widths) {
+ *widths++ = advance(g, xyIndex);
+ }
+ if (bounds) {
+ set_bounds(g, bounds++);
+ }
+ ++count;
}
- ++count;
}
}
@@ -1561,6 +1649,7 @@ void SkPaint::toString(SkString* str) const {
SkAddFlagToString(str, this->isFakeBoldText(), "FakeBoldText", &needSeparator);
SkAddFlagToString(str, this->isLinearText(), "LinearText", &needSeparator);
SkAddFlagToString(str, this->isSubpixelText(), "SubpixelText", &needSeparator);
+ SkAddFlagToString(str, this->isDevKernText(), "DevKernText", &needSeparator);
SkAddFlagToString(str, this->isLCDRenderText(), "LCDRenderText", &needSeparator);
SkAddFlagToString(str, this->isEmbeddedBitmapText(),
"EmbeddedBitmapText", &needSeparator);
@@ -1620,7 +1709,9 @@ SkTextBaseIter::SkTextBaseIter(const char text[], size_t length,
const SkPaint& paint,
bool applyStrokeAndPathEffects)
: fPaint(paint) {
- fGlyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(), true);
+ fGlyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(),
+ paint.isDevKernText(),
+ true);
fPaint.setLinearText(true);
fPaint.setMaskFilter(nullptr); // don't want this affecting our path-cache lookup
@@ -1689,7 +1780,7 @@ bool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) {
if (fText < fStop) {
const SkGlyph& glyph = fGlyphCacheProc(fCache.get(), &fText);
- fXPos += fPrevAdvance * fScale;
+ fXPos += (fPrevAdvance + fAutoKern.adjust(glyph)) * fScale;
fPrevAdvance = advance(glyph, fXYIndex); // + fPaint.getTextTracking();
if (glyph.fWidth) {
@@ -1711,7 +1802,7 @@ bool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) {
bool SkTextInterceptsIter::next(SkScalar* array, int* count) {
const SkGlyph& glyph = fGlyphCacheProc(fCache.get(), &fText);
- fXPos += fPrevAdvance * fScale;
+ fXPos += (fPrevAdvance + fAutoKern.adjust(glyph)) * fScale;
fPrevAdvance = advance(glyph, fXYIndex); // + fPaint.getTextTracking();
if (fCache->findPath(glyph)) {
fCache->findIntercepts(fBounds, fScale, fXPos, SkToBool(fXYIndex),
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp
index 57d8bc1ddf..b8cd107bd3 100644
--- a/src/core/SkScalerContext.cpp
+++ b/src/core/SkScalerContext.cpp
@@ -106,6 +106,15 @@ void SkScalerContext::getMetrics(SkGlyph* glyph) {
}
}
+ // for now we have separate cache entries for devkerning on and off
+ // in the future we might share caches, but make our measure/draw
+ // code make the distinction. Thus we zap the values if the caller
+ // has not asked for them.
+ if ((fRec.fFlags & SkScalerContext::kDevKernText_Flag) == 0) {
+ // no devkern, so zap the fields
+ glyph->fLsbDelta = glyph->fRsbDelta = 0;
+ }
+
// if either dimension is empty, zap the image bounds of the glyph
if (0 == glyph->fWidth || 0 == glyph->fHeight) {
glyph->fWidth = 0;
@@ -153,6 +162,8 @@ SK_ERROR:
glyph->fTop = 0;
glyph->fWidth = 0;
glyph->fHeight = 0;
+ glyph->fLsbDelta = 0;
+ glyph->fRsbDelta = 0;
// put a valid value here, in case it was earlier set to
// MASK_FORMAT_JUST_ADVANCE
glyph->fMaskFormat = fRec.fMaskFormat;
@@ -874,6 +885,10 @@ void SkScalerContext::MakeRecAndEffects(const SkPaint& paint,
#endif
}
+ if (paint.isDevKernText()) {
+ flags |= SkScalerContext::kDevKernText_Flag;
+ }
+
if (style != SkPaint::kFill_Style && strokeWidth > 0) {
rec->fFrameWidth = strokeWidth;
rec->fMiterLimit = paint.getStrokeMiter();
diff --git a/src/core/SkScalerContext.h b/src/core/SkScalerContext.h
index 9995fd9292..675e9a0524 100644
--- a/src/core/SkScalerContext.h
+++ b/src/core/SkScalerContext.h
@@ -224,7 +224,7 @@ class SkScalerContext {
public:
enum Flags {
kFrameAndFill_Flag = 0x0001,
- kUnused = 0x0002,
+ kDevKernText_Flag = 0x0002,
kEmbeddedBitmapText_Flag = 0x0004,
kEmbolden_Flag = 0x0008,
kSubpixelPositioning_Flag = 0x0010,
diff --git a/src/core/SkTextBlob.cpp b/src/core/SkTextBlob.cpp
index e2d3be4518..2c29d9d613 100644
--- a/src/core/SkTextBlob.cpp
+++ b/src/core/SkTextBlob.cpp
@@ -67,6 +67,7 @@ private:
SkPaint::kFakeBoldText_Flag |
SkPaint::kLinearText_Flag |
SkPaint::kSubpixelText_Flag |
+ SkPaint::kDevKernText_Flag |
SkPaint::kLCDRenderText_Flag |
SkPaint::kEmbeddedBitmapText_Flag |
SkPaint::kAutoHinting_Flag |
diff --git a/src/core/SkTextToPathIter.h b/src/core/SkTextToPathIter.h
index c135de620b..49564d96af 100644
--- a/src/core/SkTextToPathIter.h
+++ b/src/core/SkTextToPathIter.h
@@ -8,6 +8,7 @@
#ifndef SkTextToPathIter_DEFINED
#define SkTextToPathIter_DEFINED
+#include "SkAutoKern.h"
#include "SkPaint.h"
#include "SkStrikeCache.h"
@@ -26,6 +27,7 @@ protected:
SkPaint::GlyphCacheProc fGlyphCacheProc;
SkScalar fXPos; // accumulated xpos, returned in next
+ SkAutoKern fAutoKern;
int fXYIndex; // cache for horizontal -vs- vertical text
};
diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp
index e99d9df044..27c8dea670 100644
--- a/src/gpu/text/GrAtlasTextContext.cpp
+++ b/src/gpu/text/GrAtlasTextContext.cpp
@@ -498,6 +498,7 @@ void GrAtlasTextContext::DrawBmpPosTextAsPaths(GrAtlasTextBlob* blob, int runInd
pathPaint.setPathEffect(nullptr);
SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(pathPaint.getTextEncoding(),
+ pathPaint.isDevKernText(),
true);
auto cache = SkStrikeCache::FindOrCreateStrikeExclusive(
pathPaint, &props, SkScalerContextFlags::kFakeGammaAndBoostContrast, nullptr);
@@ -678,7 +679,7 @@ void GrAtlasTextContext::drawDFText(GrAtlasTextBlob* blob, int runIndex,
const SkPaint& skPaint = paint.skPaint();
SkPaint::GlyphCacheProc glyphCacheProc =
- SkPaint::GetGlyphCacheProc(skPaint.getTextEncoding(), true);
+ SkPaint::GetGlyphCacheProc(skPaint.getTextEncoding(), skPaint.isDevKernText(), true);
SkTArray<SkScalar> positions;
@@ -704,13 +705,14 @@ void GrAtlasTextContext::drawDFText(GrAtlasTextBlob* blob, int runIndex,
auto origPaintCache =
SkStrikeCache::FindOrCreateStrikeExclusive(*desc.getDesc(), effects, *typeface);
+ SkAutoKern autokern;
const char* stop = text + byteLength;
while (textPtr < stop) {
// don't need x, y here, since all subpixel variants will have the
// same advance
const SkGlyph& glyph = glyphCacheProc(origPaintCache.get(), &textPtr);
- SkScalar width = SkFloatToScalar(glyph.fAdvanceX);
+ SkScalar width = SkFloatToScalar(glyph.fAdvanceX) + autokern.adjust(glyph);
positions.push_back(stopX + origin * width);
SkScalar height = SkFloatToScalar(glyph.fAdvanceY);
@@ -775,7 +777,7 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex,
auto cache = blob->setupCache(runIndex, props, SkScalerContextFlags::kNone, dfPaint,
nullptr);
SkPaint::GlyphCacheProc glyphCacheProc =
- SkPaint::GetGlyphCacheProc(dfPaint.getTextEncoding(), true);
+ SkPaint::GetGlyphCacheProc(dfPaint.getTextEncoding(), dfPaint.isDevKernText(), true);
const char* stop = text + byteLength;
@@ -882,7 +884,8 @@ void GrAtlasTextContext::FallbackTextHelper::drawText(GrAtlasTextBlob* blob, int
SkExclusiveStrikePtr cache;
const SkPaint& skPaint = paint.skPaint();
SkPaint::GlyphCacheProc glyphCacheProc =
- SkPaint::GetGlyphCacheProc(skPaint.getTextEncoding(), true);
+ SkPaint::GetGlyphCacheProc(skPaint.getTextEncoding(),
+ skPaint.isDevKernText(), true);
SkColor textColor = paint.filteredPremulColor();
SkScalar textRatio = SK_Scalar1;
if (fUseScaledFallback) {
diff --git a/src/gpu/text/GrTextUtils.cpp b/src/gpu/text/GrTextUtils.cpp
index ab332e0417..738cfb68be 100644
--- a/src/gpu/text/GrTextUtils.cpp
+++ b/src/gpu/text/GrTextUtils.cpp
@@ -62,7 +62,7 @@ bool GrTextUtils::PathTextIter::next(const SkGlyph** skGlyph, const SkPath** pat
if (fText < fStop) {
const SkGlyph& glyph = fGlyphCacheProc(fCache.get(), &fText);
- fXPos += fPrevAdvance * fScale;
+ fXPos += (fPrevAdvance + fAutoKern.adjust(glyph)) * fScale;
SkASSERT(0 == fXYIndex || 1 == fXYIndex);
fPrevAdvance = SkFloatToScalar((&glyph.fAdvanceX)[fXYIndex]);
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
index c5e8a65733..4c4c6d4f65 100644
--- a/src/ports/SkFontHost_FreeType.cpp
+++ b/src/ports/SkFontHost_FreeType.cpp
@@ -994,6 +994,8 @@ void SkScalerContext_FreeType::generateAdvance(SkGlyph* glyph) {
fLoadGlyphFlags | FT_ADVANCE_FLAG_FAST_ONLY,
&advance );
if (0 == error) {
+ glyph->fRsbDelta = 0;
+ glyph->fLsbDelta = 0;
const SkScalar advanceScalar = SkFT_FixedToScalar(advance);
glyph->fAdvanceX = SkScalarToFloat(fMatrix22Scalar.getScaleX() * advanceScalar);
glyph->fAdvanceY = SkScalarToFloat(fMatrix22Scalar.getSkewY() * advanceScalar);
@@ -1089,6 +1091,9 @@ bool SkScalerContext_FreeType::shouldSubpixelBitmap(const SkGlyph& glyph, const
void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
SkAutoMutexAcquire ac(gFTMutex);
+ glyph->fRsbDelta = 0;
+ glyph->fLsbDelta = 0;
+
FT_Error err;
if (this->setupSize()) {
@@ -1179,6 +1184,11 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
} else {
glyph->fAdvanceX = SkFDot6ToFloat(fFace->glyph->advance.x);
glyph->fAdvanceY = -SkFDot6ToFloat(fFace->glyph->advance.y);
+
+ if (fRec.fFlags & kDevKernText_Flag) {
+ glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta);
+ glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta);
+ }
}
}
diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp
index 8047c4352f..efd74f6f8e 100644
--- a/src/ports/SkFontHost_mac.cpp
+++ b/src/ports/SkFontHost_mac.cpp
@@ -2249,7 +2249,8 @@ void SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const {
rec->setHinting(SkPaint::kNormal_Hinting);
}
- unsigned flagsWeDontSupport = SkScalerContext::kForceAutohinting_Flag |
+ unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
+ SkScalerContext::kForceAutohinting_Flag |
SkScalerContext::kLCD_BGROrder_Flag |
SkScalerContext::kLCD_Vertical_Flag;
diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp
index 35a0a74b22..7bc1e298aa 100644
--- a/src/ports/SkFontHost_win.cpp
+++ b/src/ports/SkFontHost_win.cpp
@@ -943,6 +943,8 @@ void SkScalerContext_GDI::generateMetrics(SkGlyph* glyph) {
// TODO(benjaminwagner): What is the type of gm.gmCellInc[XY]?
glyph->fAdvanceX = (float)((int)gm.gmCellIncX);
glyph->fAdvanceY = (float)((int)gm.gmCellIncY);
+ glyph->fRsbDelta = 0;
+ glyph->fLsbDelta = 0;
if (this->isSubpixel()) {
sk_bzero(&gm, sizeof(gm));
@@ -2263,6 +2265,7 @@ void LogFontTypeface::onFilterRec(SkScalerContextRec* rec) const {
}
unsigned flagsWeDontSupport = SkScalerContext::kVertical_Flag |
+ SkScalerContext::kDevKernText_Flag |
SkScalerContext::kForceAutohinting_Flag |
SkScalerContext::kEmbeddedBitmapText_Flag |
SkScalerContext::kEmbolden_Flag |
diff --git a/src/ports/SkScalerContext_win_dw.cpp b/src/ports/SkScalerContext_win_dw.cpp
index 98d8ca812e..8e73b16047 100644
--- a/src/ports/SkScalerContext_win_dw.cpp
+++ b/src/ports/SkScalerContext_win_dw.cpp
@@ -377,6 +377,12 @@ uint16_t SkScalerContext_DW::generateCharToGlyph(SkUnichar uni) {
}
void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
+ //Delta is the difference between the right/left side bearing metric
+ //and where the right/left side bearing ends up after hinting.
+ //DirectWrite does not provide this information.
+ glyph->fRsbDelta = 0;
+ glyph->fLsbDelta = 0;
+
glyph->fAdvanceX = 0;
glyph->fAdvanceY = 0;
diff --git a/src/ports/SkTypeface_win_dw.cpp b/src/ports/SkTypeface_win_dw.cpp
index 69bf7ff034..69be774612 100644
--- a/src/ports/SkTypeface_win_dw.cpp
+++ b/src/ports/SkTypeface_win_dw.cpp
@@ -258,6 +258,7 @@ void DWriteFontTypeface::onFilterRec(SkScalerContextRec* rec) const {
}
unsigned flagsWeDontSupport = SkScalerContext::kVertical_Flag |
+ SkScalerContext::kDevKernText_Flag |
SkScalerContext::kForceAutohinting_Flag |
SkScalerContext::kEmbolden_Flag |
SkScalerContext::kLCD_Vertical_Flag;
diff --git a/tests/TextBlobTest.cpp b/tests/TextBlobTest.cpp
index 6aabc45a2a..3e51baf534 100644
--- a/tests/TextBlobTest.cpp
+++ b/tests/TextBlobTest.cpp
@@ -207,6 +207,7 @@ public:
REPORTER_ASSERT(reporter, defaultPaint.isFakeBoldText() != font.isFakeBoldText());
REPORTER_ASSERT(reporter, defaultPaint.isLinearText() != font.isLinearText());
REPORTER_ASSERT(reporter, defaultPaint.isSubpixelText() != font.isSubpixelText());
+ REPORTER_ASSERT(reporter, defaultPaint.isDevKernText() != font.isDevKernText());
REPORTER_ASSERT(reporter, defaultPaint.isLCDRenderText() != font.isLCDRenderText());
REPORTER_ASSERT(reporter, defaultPaint.isEmbeddedBitmapText() != font.isEmbeddedBitmapText());
REPORTER_ASSERT(reporter, defaultPaint.isAutohinted() != font.isAutohinted());
@@ -233,6 +234,7 @@ public:
REPORTER_ASSERT(reporter, paint.isFakeBoldText() == font.isFakeBoldText());
REPORTER_ASSERT(reporter, paint.isLinearText() == font.isLinearText());
REPORTER_ASSERT(reporter, paint.isSubpixelText() == font.isSubpixelText());
+ REPORTER_ASSERT(reporter, paint.isDevKernText() == font.isDevKernText());
REPORTER_ASSERT(reporter, paint.isLCDRenderText() == font.isLCDRenderText());
REPORTER_ASSERT(reporter, paint.isEmbeddedBitmapText() == font.isEmbeddedBitmapText());
REPORTER_ASSERT(reporter, paint.isAutohinted() == font.isAutohinted());
diff --git a/tools/debugger/SkDrawCommand.cpp b/tools/debugger/SkDrawCommand.cpp
index ba54c88924..9aab347fdb 100644
--- a/tools/debugger/SkDrawCommand.cpp
+++ b/tools/debugger/SkDrawCommand.cpp
@@ -1268,6 +1268,7 @@ Json::Value SkDrawCommand::MakeJsonPaint(const SkPaint& paint, UrlDataManager& u
store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_FAKEBOLDTEXT, paint.isFakeBoldText(), false);
store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_LINEARTEXT, paint.isLinearText(), false);
store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_SUBPIXELTEXT, paint.isSubpixelText(), false);
+ store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_DEVKERNTEXT, paint.isDevKernText(), false);
store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_LCDRENDERTEXT, paint.isLCDRenderText(), false);
store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_EMBEDDEDBITMAPTEXT, paint.isEmbeddedBitmapText(), false);
store_bool(&result, SKDEBUGCANVAS_ATTRIBUTE_AUTOHINTING, paint.isAutohinted(), false);