Revert "remove legacy code for text attributes on paint"

This reverts commit 80f4adf98f.

Reason for revert: breaking PaintTest

Original change's description:
> remove legacy code for text attributes on paint
> 
> Bug: skia:2664
> Change-Id: I09f9d1401410d7ca338d7acde5a9660921c74da9
> Reviewed-on: https://skia-review.googlesource.com/c/185460
> Commit-Queue: Mike Reed <reed@google.com>
> Reviewed-by: Florin Malita <fmalita@chromium.org>

TBR=bungeman@google.com,rmistry@google.com,herb@google.com,fmalita@chromium.org,reed@google.com

Change-Id: If9bbb92d6eb064aba30cfa9069051ff60585a269
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:2664
Reviewed-on: https://skia-review.googlesource.com/c/187260
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
Mike Reed 2019-01-28 00:17:56 +00:00 committed by Skia Commit-Bot
parent 80f4adf98f
commit fb0e2aa8fd
13 changed files with 1801 additions and 51 deletions

View File

@ -49,18 +49,31 @@ Constructs Paint with default values.
# Dither # false ##
# Draw_Looper # nullptr ##
# Filter_Quality # kNone_SkFilterQuality ##
# Font_Force_Hinting # false ##
# Font_Embedded_Bitmaps # false ##
# Font_Embolden # false ##
# Font_Hinting # SkFontHinting::kNormal ##
# Font_Hinting_Spacing # false ##
# Font_Anti_Alias # false ##
# Font_Linear # false ##
# Font_Scale_X # 1 ##
# Font_Size # 12 ##
# Font_Skew_X # 0 ##
# Font_Subpixel # false ##
# Image_Filter # nullptr ##
# Miter_Limit # 4 ##
# Mask_Filter # nullptr ##
# Path_Effect # nullptr ##
# Shader # nullptr ##
# Style # kFill_Style ##
# Text_Encoding # kUTF8_SkTextEncoding ##
# Typeface # nullptr ##
# Stroke_Cap # kButt_Cap ##
# Stroke_Join # kMiter_Join ##
# Stroke_Width # 0 ##
#Table ##
The miter limit may be overridden at compile time by defining
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
build system.
@ -270,6 +283,132 @@ $$$# # restore original markup character
##
# ------------------------------------------------------------------------------
#Subtopic Hinting
#Line # glyph outline adjustment ##
##
#Method void setHinting(SkFontHinting hintingLevel)
#In Hinting
#Line # sets Hinting, glyph outline adjustment level ##
#Populate
#Example
SkPaint paint1, paint2;
paint2.setHinting(SkFontHinting::kNormal);
SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : ':');
#StdOut
paint1 == paint2
##
##
##
#Method SkFontHinting getHinting() const
#In Hinting
#Line # returns Hinting, glyph outline adjustment level ##
#Populate
#Example
SkPaint paint;
SkDebugf("SkFontHinting::kNormal %c= paint.getHinting()\n",
SkFontHinting::kNormal == paint.getHinting() ? '=' : ':');
#StdOut
SkFontHinting::kNormal == paint.getHinting()
##
##
##
# ------------------------------------------------------------------------------
#Subtopic Flags
#Line # attributes represented by single bits ##
##
#Enum Flags
#Line # values described by bits and masks ##
#Code
#Populate
##
The bit values stored in Flags.
The default value for Flags, normally zero, can be changed at compile time
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
#Line # mask for setting Anti_Alias ##
##
#Const kDither_Flag 0x0004
#Line # mask for setting Dither ##
##
#Const kFakeBoldText_Flag 0x0020
#Line # mask for setting Font_Embolden ##
##
#Const kLinearText_Flag 0x0040
#Line # mask for setting Font_Linear ##
##
#Const kSubpixelText_Flag 0x0080
#Line # mask for setting Font_Subpixel ##
##
#Const kLCDRenderText_Flag 0x0200
#Line # mask for setting Font_Anti_Alias ##
##
#Const kEmbeddedBitmapText_Flag 0x0400
#Line # mask for setting Font_Embedded_Bitmaps ##
##
#Const kAutoHinting_Flag 0x0800
#Line # mask for setting Font_Force_Hinting ##
##
#Const kAllFlags 0xFFFF
#Line # mask of all Flags ##
mask of all Flags, including private flags and flags reserved for future use
##
Flags default to all flags clear, disabling the associated feature.
#Enum ##
#Method uint32_t getFlags() const
#In Flags
#Line # returns Flags stored in a bit field ##
#Populate
#Example
SkPaint paint;
paint.setAntiAlias(true);
SkDebugf("(SkPaint::kAntiAlias_Flag & paint.getFlags()) %c= 0\n",
SkPaint::kAntiAlias_Flag & paint.getFlags() ? '!' : '=');
#StdOut
(SkPaint::kAntiAlias_Flag & paint.getFlags()) != 0
##
##
##
#Method void setFlags(uint32_t flags)
#In Flags
#Line # sets multiple Flags in a bit field ##
#Populate
#Example
SkPaint paint;
paint.setFlags((uint32_t) (SkPaint::kAntiAlias_Flag | SkPaint::kDither_Flag));
SkDebugf("paint.isAntiAlias()\n", paint.isAntiAlias() ? '!' : '=');
SkDebugf("paint.isDither()\n", paint.isDither() ? '!' : '=');
#StdOut
paint.isAntiAlias()
paint.isDither()
##
##
##
# ------------------------------------------------------------------------------
#Subtopic Anti_Alias
#Alias Anti_Alias
@ -552,6 +691,64 @@ If Font_Linear is set, it has the same effect as setting Hinting to SkFontHintin
If Font_Linear is clear, it is the same as setting Hinting to SkFontHinting::kNone.
#Subtopic Linear_Text ##
#Method bool isLinearText() const
#In Linear_Text
#Line # returns true if text is converted to Path ##
#Populate
#Example
#Height 128
void draw(SkCanvas* canvas) {
SkPaint paint;
paint.setAntiAlias(true);
const char testStr[] = "xxxx xxxx";
for (auto linearText : { false, true } ) {
paint.setLinearText(linearText);
paint.setTextSize(24);
canvas->drawString(paint.isLinearText() ? "linear" : "hinted", 128, 30, paint);
for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
paint.setTextSize(textSize);
canvas->translate(0, textSize);
canvas->drawString(testStr, 10, 0, paint);
}
}
}
##
#SeeAlso setLinearText Hinting
##
#Method void setLinearText(bool linearText)
#In Linear_Text
#Line # converts to Path before draw or measure ##
#Populate
#Example
#Height 128
void draw(SkCanvas* canvas) {
SkPaint paint;
paint.setAntiAlias(true);
const char testStr[] = "abcd efgh";
size_t count = 9;
for (int textSize : { 12, 24 } ) {
SkFont font(nullptr, textSize);
for (auto linearMetrics : { false, true } ) {
font.setLinearMetrics(linearMetrics);
SkString width;
width.appendScalar(font.measureText(testStr, count, SkTextEncoding::kUTF8));
canvas->translate(0, textSize + 4);
canvas->drawSimpleText(testStr, count, SkTextEncoding::kUTF8,
10, 0, font, paint);
canvas->drawSimpleText(width.c_str(), width.size(), SkTextEncoding::kUTF8,
128, 0, font, paint);
}
}
}
##
#SeeAlso isLinearText Hinting
##
#Subtopic Subpixel_Text
#Line # uses pixel transparency to represent fractional offset ##
@ -560,6 +757,45 @@ As the opaqueness
of the color increases, the edge of the glyph appears to move towards the outside of the pixel.
#Subtopic Subpixel_Text ##
#Method bool isSubpixelText() const
#In Subpixel_Text
#Line # returns true if Font_Subpixel is set ##
#Populate
#Example
SkPaint paint;
SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
paint.setSubpixelText(true);
SkDebugf("paint.isSubpixelText() %c= !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)\n",
paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag) ? '=' : '!');
#StdOut
paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
paint.isSubpixelText() == !!(paint.getFlags() & SkPaint::kSubpixelText_Flag)
##
##
##
#Method void setSubpixelText(bool subpixelText)
#In Subpixel_Text
#Line # sets or clears Font_Subpixel ##
#Populate
#Example
SkPaint paint1, paint2;
paint1.setSubpixelText(true);
paint2.setFlags(paint2.getFlags() | SkPaint::kSubpixelText_Flag);
SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
#StdOut
paint1 == paint2
##
##
##
#Subtopic LCD_Text
#Line # text relying on the order of RGB stripes ##
@ -570,6 +806,46 @@ Font_Anti_Alias can be enabled on devices that orient stripes horizontally or ve
the color components as RGB or BGR.
#Subtopic LCD_Text ##
#Method bool isLCDRenderText() const
#In LCD_Text
#Line # returns true if Font_Anti_Alias is set ##
#Populate
#Example
SkPaint paint;
SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
paint.setLCDRenderText(true);
SkDebugf("paint.isLCDRenderText() %c= !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)\n",
paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag) ? '=' : '!');
#StdOut
paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
paint.isLCDRenderText() == !!(paint.getFlags() & SkPaint::kLCDRenderText_Flag)
##
##
##
#Method void setLCDRenderText(bool lcdText)
#In LCD_Text
#Line # sets or clears Font_Anti_Alias ##
#Populate
#Example
SkPaint paint1, paint2;
paint1.setLCDRenderText(true);
paint2.setFlags(paint2.getFlags() | SkPaint::kLCDRenderText_Flag);
SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
#StdOut
paint1 == paint2
##
##
##
# ------------------------------------------------------------------------------
#Subtopic Embedded_Bitmaps
#Line # custom sized bitmap Glyphs ##
@ -617,6 +893,49 @@ kEmbeddedBitmapText_Flag at compile time.
##
#Subtopic Embedded_Bitmaps ##
#Method bool isEmbeddedBitmapText() const
#In Embedded_Bitmaps
#Line # returns true if Font_Embedded_Bitmaps is set ##
#Populate
#Example
SkPaint paint;
SkDebugf("paint.isEmbeddedBitmapText() %c="
" !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
paint.isEmbeddedBitmapText() ==
!!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
paint.setEmbeddedBitmapText(true);
SkDebugf("paint.isEmbeddedBitmapText() %c="
" !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)\n",
paint.isEmbeddedBitmapText() ==
!!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag) ? '=' : '!');
#StdOut
paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
paint.isEmbeddedBitmapText() == !!(paint.getFlags() & SkPaint::kEmbeddedBitmapText_Flag)
##
##
##
#Method void setEmbeddedBitmapText(bool useEmbeddedBitmapText)
#In Embedded_Bitmaps
#Line # sets or clears Font_Embedded_Bitmaps ##
#Populate
#Example
SkPaint paint1, paint2;
paint1.setEmbeddedBitmapText(true);
paint2.setFlags(paint2.getFlags() | SkPaint::kEmbeddedBitmapText_Flag);
SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
#StdOut
paint1 == paint2
##
##
##
# ------------------------------------------------------------------------------
#Subtopic Automatic_Hinting
#Line # always adjust glyph paths ##
@ -629,6 +948,57 @@ SkFontHinting::kSlight.
Font_Force_Hinting only affects platforms that use FreeType as the Font_Manager.
#Subtopic Automatic_Hinting ##
#Method bool isAutohinted() const
#In Automatic_Hinting
#Line # returns true if Glyphs are always hinted ##
#Populate
#Example
SkPaint paint;
for (auto forceAutoHinting : { false, true} ) {
paint.setAutohinted(forceAutoHinting);
SkDebugf("paint.isAutohinted() %c="
" !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)\n",
paint.isAutohinted() ==
!!(paint.getFlags() & SkPaint::kAutoHinting_Flag) ? '=' : '!');
}
#StdOut
paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
paint.isAutohinted() == !!(paint.getFlags() & SkPaint::kAutoHinting_Flag)
##
##
#SeeAlso setAutohinted Hinting
##
#Method void setAutohinted(bool useAutohinter)
#In Automatic_Hinting
#Line # sets Glyphs to always be hinted ##
#Populate
#Example
void draw(SkCanvas* canvas) {
SkPaint paint;
paint.setAntiAlias(true);
const char testStr[] = "xxxx xxxx";
for (auto forceAutoHinting : { false, true} ) {
paint.setAutohinted(forceAutoHinting);
paint.setTextSize(24);
canvas->drawString(paint.isAutohinted() ? "auto-hinted" : "default", 108, 30, paint);
for (SkScalar textSize = 8; textSize < 30; textSize *= 1.22f) {
paint.setTextSize(textSize);
canvas->translate(0, textSize);
canvas->drawString(testStr, 10, 0, paint);
}
}
}
##
#SeeAlso isAutohinted Hinting
##
# ------------------------------------------------------------------------------
#Subtopic Fake_Bold
@ -665,6 +1035,45 @@ void draw(SkCanvas* canvas) {
##
#Subtopic Fake_Bold ##
#Method bool isFakeBoldText() const
#In Fake_Bold
#Line # returns true if Font_Embolden is set ##
#Populate
#Example
SkPaint paint;
SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
paint.setFakeBoldText(true);
SkDebugf("paint.isFakeBoldText() %c= !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)\n",
paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag) ? '=' : '!');
#StdOut
paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
paint.isFakeBoldText() == !!(paint.getFlags() & SkPaint::kFakeBoldText_Flag)
##
##
##
#Method void setFakeBoldText(bool fakeBoldText)
#In Fake_Bold
#Line # sets or clears Font_Embolden ##
#Populate
#Example
SkPaint paint1, paint2;
paint1.setFakeBoldText(true);
paint2.setFlags(paint2.getFlags() | SkPaint::kFakeBoldText_Flag);
SkDebugf("paint1 %c= paint2\n", paint1 == paint2 ? '=' : '!');
#StdOut
paint1 == paint2
##
##
##
# ------------------------------------------------------------------------------
#Subtopic Filter_Quality_Methods
#Line # get and set Filter_Quality ##
@ -2135,6 +2544,74 @@ implementation.
}
##
#Method SkTypeface* getTypeface() const
#In Typeface_Methods
#Line # returns Typeface, font description ##
#Populate
#Example
void draw(SkCanvas* canvas) {
SkPaint paint;
SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
SkDebugf("nullptr %c= typeface\n", paint.getTypeface() ? '!' : '=');
}
#StdOut
nullptr == typeface
nullptr != typeface
##
##
##
#Method sk_sp<SkTypeface> refTypeface() const
#In Typeface_Methods
#Line # references Typeface, font description ##
#Populate
#Example
void draw(SkCanvas* canvas) {
SkPaint paint1, paint2;
paint1.setTypeface(SkTypeface::MakeFromName("monospace",
SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
SkFontStyle::kItalic_Slant)));
SkDebugf("typeface1 %c= typeface2\n",
paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
paint2.setTypeface(paint1.refTypeface());
SkDebugf("typeface1 %c= typeface2\n",
paint1.getTypeface() == paint2.getTypeface() ? '=' : '!');
}
#StdOut
typeface1 != typeface2
typeface1 == typeface2
##
##
##
#Method void setTypeface(sk_sp<SkTypeface> typeface)
#In Typeface_Methods
#Line # sets Typeface, font description ##
#Populate
#Example
#Height 64
void draw(SkCanvas* canvas) {
SkPaint paint;
paint.setTypeface(SkTypeface::MakeFromName("monospace", SkFontStyle()));
canvas->drawString("hamburgerfons", 10, 30, paint);
paint.setTypeface(nullptr);
canvas->drawString("hamburgerfons", 10, 50, paint);
}
##
##
#Subtopic Typeface_Methods ##
# ------------------------------------------------------------------------------
#Subtopic Image_Filter_Methods
@ -2369,6 +2846,34 @@ Set SkPaintDefaults_TextSize at compile time to change the default setting.
}
##
#Method SkScalar getTextSize() const
#In Text_Size
#Line # returns text size in points ##
#Populate
#Example
SkPaint paint;
SkDebugf("12 %c= default text size\n", 12 == paint.getTextSize() ? '=' : '!');
##
##
#Method void setTextSize(SkScalar textSize)
#In Text_Size
#Line # sets text size in points ##
#Populate
#Example
SkPaint paint;
SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
paint.setTextSize(-20);
SkDebugf("12 %c= text size\n", 12 == paint.getTextSize() ? '=' : '!');
##
##
#Subtopic Text_Size ##
# ------------------------------------------------------------------------------
#Subtopic Text_Scale_X
@ -2395,6 +2900,34 @@ Text_Scale_X defaults to 1.
}
##
#Method SkScalar getTextScaleX() const
#In Text_Scale_X
#Line # returns the text horizontal scale; condensed text ##
#Populate
#Example
SkPaint paint;
SkDebugf("1 %c= default text scale x\n", 1 == paint.getTextScaleX() ? '=' : '!');
##
##
#Method void setTextScaleX(SkScalar scaleX)
#In Text_Scale_X
#Line # sets the text horizontal scale; condensed text ##
#Populate
#Example
SkPaint paint;
paint.setTextScaleX(0.f / 0.f);
SkDebugf("text scale %s-a-number\n", SkScalarIsNaN(paint.getTextScaleX()) ? "not" : "is");
##
##
#Subtopic Text_Scale_X ##
#Subtopic Text_Skew_X
@ -2422,6 +2955,33 @@ Text_Skew_X defaults to 0.
}
##
#Method SkScalar getTextSkewX() const
#In Text_Skew_X
#Line # returns the text horizontal skew; oblique text ##
#Populate
#Example
SkPaint paint;
SkDebugf("0 %c= default text skew x\n", 0 == paint.getTextSkewX() ? '=' : '!');
##
##
#Method void setTextSkewX(SkScalar skewX)
#In Text_Skew_X
#Line # sets the text horizontal skew; oblique text ##
#Populate
#Example
SkPaint paint;
paint.setTextScaleX(1.f / 0.f);
SkDebugf("text scale %s-finite\n", SkScalarIsFinite(paint.getTextScaleX()) ? "is" : "not");
##
##
#Subtopic Text_Skew_X ##
# ------------------------------------------------------------------------------
@ -2456,6 +3016,47 @@ void draw(SkCanvas* canvas) {
}
##
#Method SkTextEncoding getTextEncoding() const
#In Text_Encoding
#Line # returns character or glyph encoded size ##
#Populate
#Example
SkPaint paint;
SkDebugf("kUTF8_SkTextEncoding %c= text encoding\n",
kUTF8_SkTextEncoding == paint.getTextEncoding() ? '=' : '!');
paint.setTextEncoding(kGlyphID_SkTextEncoding);
SkDebugf("kGlyphID_SkTextEncoding %c= text encoding\n",
kGlyphID_SkTextEncoding == paint.getTextEncoding() ? '=' : '!');
#StdOut
kUTF8_SkTextEncoding == text encoding
kGlyphID_SkTextEncoding == text encoding
##
##
##
#Method void setTextEncoding(SkTextEncoding encoding)
#In Text_Encoding
#Line # sets character or glyph encoded size ##
#Populate
#Example
SkPaint paint;
paint.setTextEncoding((SkTextEncoding) 4);
SkDebugf("4 %c= text encoding\n", (SkTextEncoding) 4 == paint.getTextEncoding() ? '=' : '!');
#StdOut
4 != text encoding
##
##
##
#Subtopic Text_Encoding ##
# ------------------------------------------------------------------------------

View File

@ -80,6 +80,7 @@ tests_sources = [
"$_tests/FontMgrFontConfigTest.cpp",
"$_tests/FontMgrTest.cpp",
"$_tests/FontNamesTest.cpp",
"$_tests/FontObjTest.cpp",
"$_tests/FrontBufferedStreamTest.cpp",
"$_tests/GeometryTest.cpp",
"$_tests/GifTest.cpp",

View File

@ -514,6 +514,18 @@ public:
*/
SkScalar getSpacing() const { return this->getMetrics(nullptr); }
#ifdef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
/** Deprecated.
*/
void LEGACY_applyToPaint(SkPaint* paint) const;
/** Deprecated.
*/
void LEGACY_applyPaintFlags(uint32_t paintFlags);
/** Deprecated.
*/
static SkFont LEGACY_ExtractFromPaint(const SkPaint& paint);
#endif
/** Experimental.
* Dumps fields of the font to SkDebugf. May change its output over time, so clients should
* not rely on this for anything specific. Used to aid in debugging.

View File

@ -22,36 +22,62 @@
#include "SkBlendMode.h"
#include "SkColor.h"
#include "SkFilterQuality.h"
#include "SkFontMetrics.h"
#include "SkFontTypes.h"
#include "SkMatrix.h"
#include "SkRefCnt.h"
// TODO: remove after updating android sites to IWYU
#include "SkFontMetrics.h"
class GrTextBlob;
class SkAutoDescriptor;
class SkColorFilter;
class SkColorSpace;
class SkData;
class SkDescriptor;
class SkDrawLooper;
class SkGlyph;
class SkGlyphRunBuilder;
class SkGlyphRun;
class SkGlyphRunListPainter;
struct SkRect;
class SkStrike;
class SkImageFilter;
class SkMaskFilter;
class SkPath;
class SkPathEffect;
struct SkPoint;
class SkFont;
class SkShader;
class SkSurfaceProps;
class SkTextBlob;
class SkTextBlobRunIterator;
class SkTypeface;
/** \class SkPaint
SkPaint controls options applied when drawing. SkPaint collects all
SkPaint controls options applied when drawing and measuring. SkPaint collects all
options outside of the SkCanvas clip and SkCanvas matrix.
Various options apply to 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 SkCanvas
functionality; for instance, text size is identical to matrix scale.
SkPaint options are rarely exclusive; each option modifies a stage of the drawing
pipeline and multiple pipeline stages may be affected by a single SkPaint.
SkPaint collects effects and filters that describe single-pass and multiple-pass
algorithms that alter the drawing geometry, color, and transparency. For instance,
SkPaint does not directly implement dashing or blur, but contains the objects that do so.
The objects contained by SkPaint are opaque, and cannot be edited outside of the SkPaint
to affect it. The implementation is free to defer computations associated with the
SkPaint, or ignore them altogether. For instance, some GPU implementations draw all
SkPath geometries with anti-aliasing, regardless of how SkPaint::kAntiAlias_Flag
is set in SkPaint.
SkPaint describes a single color, a single font, a single image quality, and so on.
Multiple colors are drawn either by using multiple paints or with objects like
SkShader attached to SkPaint.
*/
class SK_API SkPaint {
public:
@ -62,7 +88,7 @@ public:
*/
SkPaint();
/** Makes a shallow copy of SkPaint. SkPathEffect, SkShader,
/** Makes a shallow copy of SkPaint. SkTypeface, SkPathEffect, SkShader,
SkMaskFilter, SkColorFilter, SkDrawLooper, and SkImageFilter are shared
between the original paint and the copy. Objects containing SkRefCnt increment
their references by one.
@ -86,13 +112,13 @@ public:
*/
SkPaint(SkPaint&& paint);
/** Decreases SkPaint SkRefCnt of owned objects: SkPathEffect, SkShader,
/** Decreases SkPaint SkRefCnt of owned objects: SkTypeface, SkPathEffect, SkShader,
SkMaskFilter, SkColorFilter, SkDrawLooper, and SkImageFilter. If the
objects containing SkRefCnt go to zero, they are deleted.
*/
~SkPaint();
/** Makes a shallow copy of SkPaint. SkPathEffect, SkShader,
/** Makes a shallow copy of SkPaint. SkTypeface, SkPathEffect, SkShader,
SkMaskFilter, SkColorFilter, SkDrawLooper, and SkImageFilter are shared
between the original paint and the copy. Objects containing SkRefCnt in the
prior destination are decreased by one, and the referenced objects are deleted if the
@ -117,7 +143,7 @@ public:
SkPaint& operator=(SkPaint&& paint);
/** Compares a and b, and returns true if a and b are equivalent. May return false
if SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
if SkTypeface, SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
SkDrawLooper, or SkImageFilter have identical contents but different pointers.
@param a SkPaint to compare
@ -127,7 +153,7 @@ public:
SK_API friend bool operator==(const SkPaint& a, const SkPaint& b);
/** Compares a and b, and returns true if a and b are not equivalent. May return true
if SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
if SkTypeface, SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
SkDrawLooper, or SkImageFilter have identical contents but different pointers.
@param a SkPaint to compare
@ -157,30 +183,231 @@ public:
*/
void reset();
/** Sets level of glyph outline adjustment.
Does not check for valid values of hintingLevel.
@param hintingLevel one of: SkFontHinting::kNone, SkFontHinting::kSlight,
SkFontHinting::kNormal, SkFontHinting::kFull
*/
void setHinting(SkFontHinting hintingLevel);
/** Returns level of glyph outline adjustment.
@return one of: SkFontHinting::kNone, SkFontHinting::kSlight, SkFontHinting::kNormal,
SkFontHinting::kFull
*/
SkFontHinting getHinting() const { return (SkFontHinting)fBitfields.fHinting; }
/** \enum SkPaint::Flags
The bit values stored in Flags.
The default value for Flags, normally zero, can be changed at compile time
with a custom definition of SkPaintDefaults_Flags.
All flags can be read and written explicitly; Flags allows manipulating
multiple settings at once.
*/
enum Flags {
kAntiAlias_Flag = 0x01, //!< mask for setting anti-alias
kDither_Flag = 0x04, //!< mask for setting dither
kFakeBoldText_Flag = 0x20, //!< mask for setting fake bold
kLinearText_Flag = 0x40, //!< mask for setting linear text
kSubpixelText_Flag = 0x80, //!< mask for setting subpixel text
kLCDRenderText_Flag = 0x200, //!< mask for setting LCD text
kEmbeddedBitmapText_Flag = 0x400, //!< mask for setting font embedded bitmaps
kAutoHinting_Flag = 0x800, //!< mask for setting force hinting
// 0x1000 used to be kVertical
kAllFlags = 0xFFFF, //!< mask of all Flags
};
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
/** Private.
*/
enum ReserveFlags {
kUnderlineText_ReserveFlag = 0x08, //!< to be deprecated soon
kStrikeThruText_ReserveFlag = 0x10, //!< to be deprecated soon
};
#endif
#ifdef SK_SUPPORT_LEGACY_PAINT_FLAGS
/** Returns paint settings described by SkPaint::Flags. Each setting uses one
bit, and can be tested with SkPaint::Flags members.
@return zero, one, or more bits described by SkPaint::Flags
*/
uint32_t getFlags() const { return fBitfields.fFlags; }
/** Replaces SkPaint::Flags with flags, the union of the SkPaint::Flags members.
All SkPaint::Flags members may be cleared, or one or more may be set.
@param flags union of SkPaint::Flags for SkPaint
*/
void setFlags(uint32_t flags);
#endif
/** Returns true if pixels on the active edges of SkPath may be drawn with partial transparency.
@return antialiasing state
Equivalent to getFlags() masked with kAntiAlias_Flag.
@return kAntiAlias_Flag state
*/
bool isAntiAlias() const {
return SkToBool(fBitfields.fAntiAlias);
return SkToBool(this->internal_getFlags() & kAntiAlias_Flag);
}
/** Requests, but does not require, that edge pixels draw opaque or with
partial transparency.
@param aa setting for antialiasing
Sets kAntiAlias_Flag if aa is true.
Clears kAntiAlias_Flag if aa is false.
@param aa setting for kAntiAlias_Flag
*/
void setAntiAlias(bool aa) { fBitfields.fAntiAlias = static_cast<unsigned>(aa); }
void setAntiAlias(bool aa);
/** Returns true if color error may be distributed to smooth color transition.
@return dithering state
Equivalent to getFlags() masked with kDither_Flag.
@return kDither_Flag state
*/
bool isDither() const {
return SkToBool(fBitfields.fDither);
return SkToBool(this->internal_getFlags() & kDither_Flag);
}
/** Requests, but does not require, to distribute color error.
@param dither setting for ditering
Sets kDither_Flag if dither is true.
Clears kDither_Flag if dither is false.
@param dither setting for kDither_Flag
*/
void setDither(bool dither) { fBitfields.fDither = static_cast<unsigned>(dither); }
void setDither(bool dither);
#ifdef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
/** Returns true if text is converted to SkPath before drawing and measuring.
Equivalent to getFlags() masked with kLinearText_Flag.
@return kLinearText_Flag state
*/
bool isLinearText() const {
return SkToBool(this->internal_getFlags() & kLinearText_Flag);
}
/** Requests, but does not require, that glyphs are converted to SkPath
before drawing and measuring.
By default, kLinearText_Flag is clear.
Sets kLinearText_Flag if linearText is true.
Clears kLinearText_Flag if linearText is false.
@param linearText setting for kLinearText_Flag
*/
void setLinearText(bool linearText);
/** Returns true if glyphs at different sub-pixel positions may differ on pixel edge coverage.
Equivalent to getFlags() masked with kSubpixelText_Flag.
@return kSubpixelText_Flag state
*/
bool isSubpixelText() const {
return SkToBool(this->internal_getFlags() & kSubpixelText_Flag);
}
/** Requests, but does not require, that glyphs respect sub-pixel positioning.
Sets kSubpixelText_Flag if subpixelText is true.
Clears kSubpixelText_Flag if subpixelText is false.
@param subpixelText setting for kSubpixelText_Flag
*/
void setSubpixelText(bool subpixelText);
/** Returns true if glyphs may use LCD striping to improve glyph edges.
Returns true if SkPaint::Flags kLCDRenderText_Flag is set.
@return kLCDRenderText_Flag state
*/
bool isLCDRenderText() const {
return SkToBool(this->internal_getFlags() & kLCDRenderText_Flag);
}
/** Requests, but does not require, that glyphs use LCD striping for glyph edges.
Sets kLCDRenderText_Flag if lcdText is true.
Clears kLCDRenderText_Flag if lcdText is false.
@param lcdText setting for kLCDRenderText_Flag
*/
void setLCDRenderText(bool lcdText);
/** Returns true if font engine may return glyphs from font bitmaps instead of from outlines.
Equivalent to getFlags() masked with kEmbeddedBitmapText_Flag.
@return kEmbeddedBitmapText_Flag state
*/
bool isEmbeddedBitmapText() const {
return SkToBool(this->internal_getFlags() & kEmbeddedBitmapText_Flag);
}
/** Requests, but does not require, to use bitmaps in fonts instead of outlines.
Sets kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is true.
Clears kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is false.
@param useEmbeddedBitmapText setting for kEmbeddedBitmapText_Flag
*/
void setEmbeddedBitmapText(bool useEmbeddedBitmapText);
/** Returns true if SkPaint::Hinting is set to SkFontHinting::kNormal or
SkFontHinting::kFull, and if platform uses FreeType as the font manager.
If true, instructs the font manager to always hint glyphs.
Equivalent to getFlags() masked with kAutoHinting_Flag.
@return kAutoHinting_Flag state
*/
bool isAutohinted() const {
return SkToBool(this->internal_getFlags() & kAutoHinting_Flag);
}
/** Sets whether to always hint glyphs.
If SkPaint::Hinting is set to SkFontHinting::kNormal or SkFontHinting::kFull
and useAutohinter is set, instructs the font manager to always hint glyphs.
useAutohinter has no effect if SkPaint::Hinting is set to SkFontHinting::kNone or
SkFontHinting::kSlight.
Only affects platforms that use FreeType as the font manager.
Sets kAutoHinting_Flag if useAutohinter is true.
Clears kAutoHinting_Flag if useAutohinter is false.
@param useAutohinter setting for kAutoHinting_Flag
*/
void setAutohinted(bool useAutohinter);
/** Returns true if approximate bold by increasing the stroke width when creating glyph bitmaps
from outlines.
Equivalent to getFlags() masked with kFakeBoldText_Flag.
@return kFakeBoldText_Flag state
*/
bool isFakeBoldText() const {
return SkToBool(this->internal_getFlags() & kFakeBoldText_Flag);
}
/** Increases stroke width when creating glyph bitmaps to approximate a bold typeface.
Sets kFakeBoldText_Flag if fakeBoldText is true.
Clears kFakeBoldText_Flag if fakeBoldText is false.
@param fakeBoldText setting for kFakeBoldText_Flag
*/
void setFakeBoldText(bool fakeBoldText);
#endif
/** Returns SkFilterQuality, the image filtering level. A lower setting
draws faster; a higher setting looks better when the image is scaled.
@ -463,20 +690,20 @@ public:
@return mode used to combine source color with destination color
*/
SkBlendMode getBlendMode() const { return (SkBlendMode)fBitfields.fBlendMode; }
SkBlendMode getBlendMode() const { return (SkBlendMode)fBlendMode; }
/** Returns true if SkBlendMode is SkBlendMode::kSrcOver, the default.
@return true if SkBlendMode is SkBlendMode::kSrcOver
*/
bool isSrcOver() const { return (SkBlendMode)fBitfields.fBlendMode == SkBlendMode::kSrcOver; }
bool isSrcOver() const { return (SkBlendMode)fBlendMode == SkBlendMode::kSrcOver; }
/** Sets SkBlendMode to mode.
Does not check for valid input.
@param mode SkBlendMode used to combine source color and destination
*/
void setBlendMode(SkBlendMode mode) { fBitfields.fBlendMode = (unsigned)mode; }
void setBlendMode(SkBlendMode mode) { fBlendMode = (unsigned)mode; }
/** Returns SkPathEffect if set, or nullptr.
Does not alter SkPathEffect SkRefCnt.
@ -526,6 +753,33 @@ public:
*/
void setMaskFilter(sk_sp<SkMaskFilter> maskFilter);
#ifndef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
private:
#endif
/** Returns SkTypeface if set, or nullptr.
Does not alter SkTypeface SkRefCnt.
@return SkTypeface if previously set, nullptr otherwise
*/
SkTypeface* getTypeface() const { return fTypeface.get(); }
/** Increases SkTypeface SkRefCnt by one.
@return SkTypeface if previously set, nullptr otherwise
*/
sk_sp<SkTypeface> refTypeface() const;
/** Sets SkTypeface to typeface, decreasing SkRefCnt of the previous SkTypeface.
Pass nullptr to clear SkTypeface and use the default typeface. Increments
typeface SkRefCnt by one.
@param typeface font and style used to draw text
*/
void setTypeface(sk_sp<SkTypeface> typeface);
#ifndef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
public:
#endif
/** Returns SkImageFilter if set, or nullptr.
Does not alter SkImageFilter SkRefCnt.
@ -584,11 +838,130 @@ public:
*/
void setLooper(sk_sp<SkDrawLooper> drawLooper);
#ifndef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
private:
#endif
/** Returns text size in points.
@return typographic height of text
*/
SkScalar getTextSize() const { return fTextSize; }
/** Sets text size in points.
Has no effect if textSize is not greater than or equal to zero.
@param textSize typographic height of text
*/
void setTextSize(SkScalar textSize);
/** Returns text scale on x-axis.
Default value is 1.
@return text horizontal scale
*/
SkScalar getTextScaleX() const { return fTextScaleX; }
/** Sets text scale on x-axis.
Default value is 1.
@param scaleX text horizontal scale
*/
void setTextScaleX(SkScalar scaleX);
/** Returns text skew on x-axis.
Default value is zero.
@return additional shear on x-axis relative to y-axis
*/
SkScalar getTextSkewX() const { return fTextSkewX; }
/** Sets text skew on x-axis.
Default value is zero.
@param skewX additional shear on x-axis relative to y-axis
*/
void setTextSkewX(SkScalar skewX);
#ifdef SK_SUPPORT_LEGACY_PAINTTEXTENCODING
/**
* Returns the text encoding. Text encoding describes how to interpret the text bytes pass
* to methods like SkFont::measureText() and SkCanvas::drawText().
* @return the text encoding
*/
SkTextEncoding getTextEncoding() const {
return (SkTextEncoding)fBitfields.fTextEncoding;
}
/**
* Sets the text encoding. Text encoding describes how to interpret the text bytes pass
* to methods like SkFont::measureText() and SkCanvas::drawText().
* @param encoding the new text encoding
*/
void setTextEncoding(SkTextEncoding encoding);
#endif
#ifndef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
public:
#endif
#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
/** Deprecated; use SkFont::getMetrics instead
*/
SkScalar getFontMetrics(SkFontMetrics* metrics) const;
/** Deprecated; use SkFont::getSpacing instead
*/
SkScalar getFontSpacing() const { return this->getFontMetrics(nullptr); }
/** Deprecated; use SkFont::textToGlyphs instead
*/
int textToGlyphs(const void* text, size_t byteLength,
SkGlyphID glyphs[]) const;
/** Deprecated; use SkFont::containsText instead
*/
bool containsText(const void* text, size_t byteLength) const;
#endif
#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
/** Deprecated; use SkFont::countText instead
*/
int countText(const void* text, size_t byteLength) const;
/** Deprecated; use SkFont::measureText instead
*/
SkScalar measureText(const void* text, size_t length, SkRect* bounds) const;
/** Deprecated; use SkFont::measureText instead
*/
SkScalar measureText(const void* text, size_t length) const {
return this->measureText(text, length, nullptr);
}
/** Deprecated; use SkFont::getWidthsBounds instead
*/
int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
SkRect bounds[] = nullptr) const;
/** Deprecated; use SkFont::getPath instead
*/
void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
SkPath* path) const;
/** Deprecated; use SkFont::getPath instead
*/
void getPosTextPath(const void* text, size_t length,
const SkPoint pos[], SkPath* path) const;
#endif
/** DEPRECATED -- call method on SkTextBlob
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.
Uses SkTypeface to get the glyph paths,
and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
Uses run array to position intervals.
SkTextEncoding must be set to kGlyphID_SkTextEncoding.
@ -690,6 +1063,7 @@ public:
Style style) const;
private:
sk_sp<SkTypeface> fTypeface;
sk_sp<SkPathEffect> fPathEffect;
sk_sp<SkShader> fShader;
sk_sp<SkMaskFilter> fMaskFilter;
@ -697,22 +1071,44 @@ private:
sk_sp<SkDrawLooper> fDrawLooper;
sk_sp<SkImageFilter> fImageFilter;
SkScalar fTextSize;
SkScalar fTextScaleX;
SkScalar fTextSkewX;
SkColor4f fColor4f;
SkScalar fWidth;
SkScalar fMiterLimit;
uint32_t fBlendMode; // just need 5-6 bits
union {
struct {
unsigned fAntiAlias : 1;
unsigned fDither : 1;
unsigned fCapType : 2;
unsigned fJoinType : 2;
unsigned fStyle : 2;
unsigned fFilterQuality : 2;
unsigned fBlendMode : 8; // only need 5-6?
// all of these bitfields should add up to 32
unsigned fFlags : 16;
unsigned fCapType : 2;
unsigned fJoinType : 2;
unsigned fStyle : 2;
unsigned fTextEncoding : 2; // 3 values
unsigned fHinting : 2;
unsigned fFilterQuality : 2;
//unsigned fFreeBits : 4;
} fBitfields;
uint32_t fBitfieldsUInt;
};
uint32_t internal_getFlags() const { return fBitfields.fFlags; }
void internal_setFlags(uint32_t flags) {
fBitfields.fFlags = flags;
}
SkTextEncoding private_internal_getTextEncoding() const {
return (SkTextEncoding)fBitfields.fTextEncoding;
}
void private_internal_setTextEncoding(SkTextEncoding e) {
fBitfields.fTextEncoding = (unsigned)e;
}
SkScalar measure_text(SkStrike*, const char* text, size_t length,
int* count, SkRect* bounds) const;
/*
* The luminance color is used to determine which Gamma Canonical color to map to. This is
* really only used by backends which want to cache glyph masks, and need some way to know if
@ -720,6 +1116,31 @@ private:
*/
SkColor computeLuminanceColor() const;
/* This is the size we use when we ask for a glyph's path. We then
* post-transform it as we draw to match the request.
* This is done to try to re-use cache entries for the path.
*
* This value is somewhat arbitrary. In theory, it could be 1, since
* we store paths as floats. However, we get the path from the font
* scaler, and it may represent its paths as fixed-point (or 26.6),
* so we shouldn't ask for something too big (might overflow 16.16)
* or too small (underflow 26.6).
*
* This value could track kMaxSizeForGlyphCache, assuming the above
* constraints, but since we ask for unhinted paths, the two values
* need not match per-se.
*/
static constexpr int kCanonicalTextSizeForPaths = 64;
static bool TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM, SkScalar maxLimit);
// Set flags/hinting/textSize up to use for drawing text as paths.
// Returns scale factor to restore the original textSize, since will will
// have change it to kCanonicalTextSizeForPaths.
SkScalar setupForAsPaths();
static SkScalar MaxCacheSize2(SkScalar maxLimit);
friend class GrTextBlob;
friend class GrTextContext;
friend class GrGLPathRendering;
@ -728,6 +1149,7 @@ private:
friend class SkCanonicalizePaint;
friend class SkCanvas;
friend class SkDraw;
friend class SkFont;
friend class SkGlyphRunListPainter;
friend class SkPaintPriv;
friend class SkPicturePlayback;

View File

@ -494,6 +494,74 @@ sk_sp<SkTypeface> SkFont::refTypefaceOrDefault() const {
return fTypeface ? fTypeface : SkTypeface::MakeDefault();
}
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "SkPaint.h"
#ifdef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
void SkFont::LEGACY_applyToPaint(SkPaint* paint) const {
paint->setTypeface(fTypeface);
paint->setTextSize(fSize);
paint->setTextScaleX(fScaleX);
paint->setTextSkewX(fSkewX);
paint->setEmbeddedBitmapText(SkToBool(fFlags & kEmbeddedBitmaps_PrivFlag));
paint->setFakeBoldText(SkToBool(fFlags & kEmbolden_PrivFlag));
paint->setAutohinted(SkToBool(fFlags & kForceAutoHinting_PrivFlag));
paint->setSubpixelText(SkToBool(fFlags & kSubpixel_PrivFlag));
paint->setLinearText(SkToBool(fFlags & kLinearMetrics_PrivFlag));
bool doAA = false,
doLCD = false;
switch (this->getEdging()) {
case Edging::kAlias: break;
case Edging::kAntiAlias: doAA = true; break;
case Edging::kSubpixelAntiAlias: doAA = true; doLCD = true; break;
}
paint->setAntiAlias(doAA);
paint->setLCDRenderText(doLCD);
paint->setHinting((SkFontHinting)this->getHinting());
}
SkFont SkFont::LEGACY_ExtractFromPaint(const SkPaint& paint) {
SkFont font(sk_ref_sp(paint.getTypeface()), paint.getTextSize(), paint.getTextScaleX(),
paint.getTextSkewX());
font.LEGACY_applyPaintFlags(paint.getFlags());
font.setHinting((SkFontHinting)paint.getHinting());
return font;
}
void SkFont::LEGACY_applyPaintFlags(uint32_t paintFlags) {
uint32_t flags = 0;
if (paintFlags & SkPaint::kEmbeddedBitmapText_Flag) {
flags |= kEmbeddedBitmaps_PrivFlag;
}
if (paintFlags & SkPaint::kFakeBoldText_Flag) {
flags |= kEmbolden_PrivFlag;
}
if (paintFlags & SkPaint::kAutoHinting_Flag) {
flags |= kForceAutoHinting_PrivFlag;
}
if (paintFlags & SkPaint::kSubpixelText_Flag) {
flags |= kSubpixel_PrivFlag;
}
if (paintFlags & SkPaint::kLinearText_Flag) {
flags |= kLinearMetrics_PrivFlag;
}
fFlags = flags;
Edging edging = Edging::kAlias;
if (paintFlags & SkPaint::kAntiAlias_Flag) {
edging = Edging::kAntiAlias;
if (paintFlags & SkPaint::kLCDRenderText_Flag) {
edging = Edging::kSubpixelAntiAlias;
}
}
this->setEdging(edging);
}
#endif
//////////////////////////////////////////////////////////////////////////////////////////////////
int SkFontPriv::ValidCountText(const void* text, size_t length, SkTextEncoding encoding) {

View File

@ -35,49 +35,69 @@
#include "SkTypeface.h"
#include "SkWriteBuffer.h"
static inline uint32_t set_clear_mask(uint32_t bits, bool cond, uint32_t mask) {
return cond ? bits | mask : bits & ~mask;
}
// define this to get a printf for out-of-range parameter in setters
// e.g. setTextSize(-1)
//#define SK_REPORT_API_RANGE_CHECK
SkPaint::SkPaint() {
fTextSize = SkPaintDefaults_TextSize;
fTextScaleX = SK_Scalar1;
fTextSkewX = 0;
fColor4f = { 0, 0, 0, 1 }; // opaque black
fWidth = 0;
fMiterLimit = SkPaintDefaults_MiterLimit;
fBlendMode = (unsigned)SkBlendMode::kSrcOver;
// Zero all bitfields, then set some non-zero defaults.
fBitfieldsUInt = 0;
fBitfields.fFlags = SkPaintDefaults_Flags;
fBitfields.fCapType = kDefault_Cap;
fBitfields.fJoinType = kDefault_Join;
fBitfields.fStyle = kFill_Style;
fBitfields.fBlendMode = (unsigned)SkBlendMode::kSrcOver;
fBitfields.fTextEncoding = static_cast<unsigned>(kUTF8_SkTextEncoding);
fBitfields.fHinting = static_cast<unsigned>(SkPaintDefaults_Hinting);
}
SkPaint::SkPaint(const SkPaint& src)
#define COPY(field) field(src.field)
: COPY(fPathEffect)
: COPY(fTypeface)
, COPY(fPathEffect)
, COPY(fShader)
, COPY(fMaskFilter)
, COPY(fColorFilter)
, COPY(fDrawLooper)
, COPY(fImageFilter)
, COPY(fTextSize)
, COPY(fTextScaleX)
, COPY(fTextSkewX)
, COPY(fColor4f)
, COPY(fWidth)
, COPY(fMiterLimit)
, COPY(fBlendMode)
, COPY(fBitfields)
#undef COPY
{}
SkPaint::SkPaint(SkPaint&& src) {
#define MOVE(field) field = std::move(src.field)
MOVE(fTypeface);
MOVE(fPathEffect);
MOVE(fShader);
MOVE(fMaskFilter);
MOVE(fColorFilter);
MOVE(fDrawLooper);
MOVE(fImageFilter);
MOVE(fTextSize);
MOVE(fTextScaleX);
MOVE(fTextSkewX);
MOVE(fColor4f);
MOVE(fWidth);
MOVE(fMiterLimit);
MOVE(fBlendMode);
MOVE(fBitfields);
#undef MOVE
}
@ -90,15 +110,20 @@ SkPaint& SkPaint::operator=(const SkPaint& src) {
}
#define ASSIGN(field) field = src.field
ASSIGN(fTypeface);
ASSIGN(fPathEffect);
ASSIGN(fShader);
ASSIGN(fMaskFilter);
ASSIGN(fColorFilter);
ASSIGN(fDrawLooper);
ASSIGN(fImageFilter);
ASSIGN(fTextSize);
ASSIGN(fTextScaleX);
ASSIGN(fTextSkewX);
ASSIGN(fColor4f);
ASSIGN(fWidth);
ASSIGN(fMiterLimit);
ASSIGN(fBlendMode);
ASSIGN(fBitfields);
#undef ASSIGN
@ -111,15 +136,20 @@ SkPaint& SkPaint::operator=(SkPaint&& src) {
}
#define MOVE(field) field = std::move(src.field)
MOVE(fTypeface);
MOVE(fPathEffect);
MOVE(fShader);
MOVE(fMaskFilter);
MOVE(fColorFilter);
MOVE(fDrawLooper);
MOVE(fImageFilter);
MOVE(fTextSize);
MOVE(fTextScaleX);
MOVE(fTextSkewX);
MOVE(fColor4f);
MOVE(fWidth);
MOVE(fMiterLimit);
MOVE(fBlendMode);
MOVE(fBitfields);
#undef MOVE
@ -128,15 +158,20 @@ SkPaint& SkPaint::operator=(SkPaint&& src) {
bool operator==(const SkPaint& a, const SkPaint& b) {
#define EQUAL(field) (a.field == b.field)
return EQUAL(fPathEffect)
return EQUAL(fTypeface)
&& EQUAL(fPathEffect)
&& EQUAL(fShader)
&& EQUAL(fMaskFilter)
&& EQUAL(fColorFilter)
&& EQUAL(fDrawLooper)
&& EQUAL(fImageFilter)
&& EQUAL(fTextSize)
&& EQUAL(fTextScaleX)
&& EQUAL(fTextSkewX)
&& EQUAL(fColor4f)
&& EQUAL(fWidth)
&& EQUAL(fMiterLimit)
&& EQUAL(fBlendMode)
&& EQUAL(fBitfieldsUInt)
;
#undef EQUAL
@ -149,6 +184,7 @@ DEFINE_REF_FOO(ImageFilter)
DEFINE_REF_FOO(MaskFilter)
DEFINE_REF_FOO(PathEffect)
DEFINE_REF_FOO(Shader)
DEFINE_REF_FOO(Typeface)
#undef DEFINE_REF_FOO
void SkPaint::reset() {
@ -160,6 +196,50 @@ void SkPaint::setFilterQuality(SkFilterQuality quality) {
fBitfields.fFilterQuality = quality;
}
void SkPaint::setHinting(SkFontHinting hintingLevel) {
fBitfields.fHinting = static_cast<unsigned>(hintingLevel);
}
#ifdef SK_SUPPORT_LEGACY_PAINT_FLAGS
void SkPaint::setFlags(uint32_t flags) {
fBitfields.fFlags = flags;
}
#endif
void SkPaint::setAntiAlias(bool doAA) {
this->internal_setFlags(set_clear_mask(fBitfields.fFlags, doAA, kAntiAlias_Flag));
}
void SkPaint::setDither(bool doDither) {
this->internal_setFlags(set_clear_mask(fBitfields.fFlags, doDither, kDither_Flag));
}
#ifdef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
void SkPaint::setSubpixelText(bool doSubpixel) {
this->internal_setFlags(set_clear_mask(fBitfields.fFlags, doSubpixel, kSubpixelText_Flag));
}
void SkPaint::setLCDRenderText(bool doLCDRender) {
this->internal_setFlags(set_clear_mask(fBitfields.fFlags, doLCDRender, kLCDRenderText_Flag));
}
void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
this->internal_setFlags(set_clear_mask(fBitfields.fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
}
void SkPaint::setAutohinted(bool useAutohinter) {
this->internal_setFlags(set_clear_mask(fBitfields.fFlags, useAutohinter, kAutoHinting_Flag));
}
void SkPaint::setLinearText(bool doLinearText) {
this->internal_setFlags(set_clear_mask(fBitfields.fFlags, doLinearText, kLinearText_Flag));
}
void SkPaint::setFakeBoldText(bool doFakeBold) {
this->internal_setFlags(set_clear_mask(fBitfields.fFlags, doFakeBold, kFakeBoldText_Flag));
}
#endif
void SkPaint::setStyle(Style style) {
if ((unsigned)style < kStyleCount) {
fBitfields.fStyle = style;
@ -232,7 +312,40 @@ void SkPaint::setStrokeJoin(Join jt) {
///////////////////////////////////////////////////////////////////////////////
void SkPaint::setTextSize(SkScalar ts) {
if (ts >= 0) {
fTextSize = ts;
} else {
#ifdef SK_REPORT_API_RANGE_CHECK
SkDebugf("SkPaint::setTextSize() called with negative value\n");
#endif
}
}
void SkPaint::setTextScaleX(SkScalar scaleX) {
fTextScaleX = scaleX;
}
void SkPaint::setTextSkewX(SkScalar skewX) {
fTextSkewX = skewX;
}
#ifdef SK_SUPPORT_LEGACY_PAINTTEXTENCODING
void SkPaint::setTextEncoding(SkTextEncoding encoding) {
if ((unsigned)encoding <= (unsigned)kGlyphID_SkTextEncoding) {
fBitfields.fTextEncoding = (unsigned)encoding;
} else {
#ifdef SK_REPORT_API_RANGE_CHECK
SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
#endif
}
}
#endif
///////////////////////////////////////////////////////////////////////////////
#define MOVE_FIELD(Field) void SkPaint::set##Field(sk_sp<Sk##Field> f) { f##Field = std::move(f); }
MOVE_FIELD(Typeface)
MOVE_FIELD(ImageFilter)
MOVE_FIELD(Shader)
MOVE_FIELD(ColorFilter)
@ -294,8 +407,12 @@ enum PaintFlagsForFont {
static FlatFlags unpack_paint_flags(SkPaint* paint, uint32_t packed, SkFont* font) {
uint32_t f = packed >> 16;
#ifdef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
paint->setFlags(f);
#else
paint->setAntiAlias((f & kAA_PaintFlagForPaint) != 0);
paint->setDither((f & kDither_PaintFlagForPaint) != 0);
#endif
if (font) {
font->setEmbolden((f & kFakeBold_PaintFlagForFont) != 0);
font->setLinearMetrics((f & kLinear_PaintFlagForFont) != 0);
@ -316,6 +433,7 @@ static FlatFlags unpack_paint_flags(SkPaint* paint, uint32_t packed, SkFont* fon
}
}
paint->setHinting((SkFontHinting)((packed >> 14) & BPF_Mask(kHint_BPF)));
paint->setFilterQuality((SkFilterQuality)((packed >> 10) & BPF_Mask(kFilter_BPF)));
return (FlatFlags)(packed & kFlatFlagMask);
}
@ -405,6 +523,11 @@ SkReadPaintResult SkPaintPriv::Unflatten_PreV68(SkPaint* paint, SkReadBuffer& bu
SkScalar sz = buffer.readScalar();
SkScalar sx = buffer.readScalar();
SkScalar kx = buffer.readScalar();
#ifdef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
paint->setTextSize(sz);
paint->setTextScaleX(sx);
paint->setTextSkewX(kx);
#endif
if (font) {
font->setSize(sz);
font->setScaleX(sx);
@ -428,12 +551,16 @@ SkReadPaintResult SkPaintPriv::Unflatten_PreV68(SkPaint* paint, SkReadBuffer& bu
paint->setStrokeCap(safe.checkLE((tmp >> 24) & 0xFF, SkPaint::kLast_Cap));
paint->setStrokeJoin(safe.checkLE((tmp >> 16) & 0xFF, SkPaint::kLast_Join));
paint->setStyle(safe.checkLE((tmp >> 12) & 0xF, SkPaint::kStrokeAndFill_Style));
paint->private_internal_setTextEncoding(safe.checkLE((tmp >> 8) & 0xF, kGlyphID_SkTextEncoding));
paint->setBlendMode(safe.checkLE(tmp & 0xFF, SkBlendMode::kLastMode));
sk_sp<SkTypeface> tf;
if (flatFlags & kHasTypeface_FlatFlag) {
tf = buffer.readTypeface();
}
#ifdef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
paint->setTypeface(tf);
#endif
if (font) {
font->setTypeface(tf);
}
@ -600,7 +727,7 @@ bool SkPaint::nothingToDraw() const {
if (fDrawLooper) {
return false;
}
switch (this->getBlendMode()) {
switch ((SkBlendMode)fBlendMode) {
case SkBlendMode::kSrcOver:
case SkBlendMode::kSrcATop:
case SkBlendMode::kDstOut:
@ -619,9 +746,9 @@ bool SkPaint::nothingToDraw() const {
}
uint32_t SkPaint::getHash() const {
// We're going to hash 6 pointers and 6 32-bit values, finishing up with fBitfields,
// so fBitfields should be 6 pointers and 6 32-bit values from the start.
static_assert(offsetof(SkPaint, fBitfields) == 6 * sizeof(void*) + 6 * sizeof(uint32_t),
// We're going to hash 7 pointers and 11 32-bit values, finishing up with fBitfields,
// so fBitfields should be 7 pointers and 10 32-bit values from the start.
static_assert(offsetof(SkPaint, fBitfields) == 7 * sizeof(void*) + 10 * sizeof(uint32_t),
"SkPaint_notPackedTightly");
return SkOpts::hash(reinterpret_cast<const uint32_t*>(this),
offsetof(SkPaint, fBitfields) + sizeof(fBitfields));

View File

@ -14,7 +14,6 @@
#include "SkTypeface.h"
class SkBitmap;
class SkFont;
class SkImage;
class SkReadBuffer;
class SkWriteBuffer;
@ -59,6 +58,10 @@ public:
static bool ShouldDither(const SkPaint&, SkColorType);
static SkTextEncoding GetEncoding(const SkPaint& paint) {
return paint.private_internal_getTextEncoding();
}
/** Serializes SkPaint into a buffer. A companion unflatten() call
can reconstitute the paint at a later time.

View File

@ -60,6 +60,25 @@ SkScalar SkFontPriv::MaxCacheSize2(SkScalar maxLimit) {
#include "SkUtils.h"
#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
int SkPaint::countText(const void* text, size_t length) const {
return SkFont::LEGACY_ExtractFromPaint(*this).countText(text, length, this->getTextEncoding());
}
int SkPaint::textToGlyphs(const void* text, size_t length, uint16_t glyphs[]) const {
return SkFont::LEGACY_ExtractFromPaint(*this).textToGlyphs(text, length,
this->getTextEncoding(),
glyphs, length);
}
bool SkPaint::containsText(const void* text, size_t length) const {
return SkFont::LEGACY_ExtractFromPaint(*this).containsText(text, length,
this->getTextEncoding());
}
#endif
///////////////////////////////////////////////////////////////////////////////
static const SkGlyph& sk_getMetrics_utf8_next(SkStrike* cache,
const char** text,
const char* stop) {
@ -168,13 +187,205 @@ SkFontPriv::GlyphCacheProc SkFontPriv::GetGlyphCacheProc(SkTextEncoding encoding
///////////////////////////////////////////////////////////////////////////////
#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
SkScalar SkPaint::setupForAsPaths() {
constexpr uint32_t flagsToIgnore = SkPaint::kLinearText_Flag |
SkPaint::kLCDRenderText_Flag |
SkPaint::kEmbeddedBitmapText_Flag |
SkPaint::kAutoHinting_Flag;
uint32_t flags = this->getFlags();
// clear the flags we don't care about
flags &= ~flagsToIgnore;
// set the flags we do care about
flags |= SkPaint::kSubpixelText_Flag;
this->setFlags(flags);
this->setHinting(kNo_SkFontHinting);
this->setStyle(SkPaint::kFill_Style);
this->setPathEffect(nullptr);
SkScalar textSize = fTextSize;
this->setTextSize(kCanonicalTextSizeForPaths);
return textSize / kCanonicalTextSizeForPaths;
}
class SkCanonicalizePaint {
public:
SkCanonicalizePaint(const SkPaint& paint) : fPaint(&paint), fScale(0) {
const SkFont font = SkFont::LEGACY_ExtractFromPaint(paint);
if (paint.isLinearText() || SkDraw::ShouldDrawTextAsPaths(font, paint, SkMatrix::I())) {
SkPaint* p = fLazy.set(paint);
fScale = p->setupForAsPaths();
fPaint = p;
}
}
const SkPaint& getPaint() const { return *fPaint; }
/**
* Returns 0 if the paint was unmodified, or the scale factor need to
* the original textSize
*/
SkScalar getScale() const { return fScale; }
private:
const SkPaint* fPaint;
SkScalar fScale;
SkTLazy<SkPaint> fLazy;
};
#endif
static void set_bounds(const SkGlyph& g, SkRect* bounds) {
bounds->set(SkIntToScalar(g.fLeft),
SkIntToScalar(g.fTop),
SkIntToScalar(g.fLeft + g.fWidth),
SkIntToScalar(g.fTop + g.fHeight));
}
static void join_bounds_x(const SkGlyph& g, SkRect* bounds, SkScalar dx) {
bounds->join(SkIntToScalar(g.fLeft) + dx,
SkIntToScalar(g.fTop),
SkIntToScalar(g.fLeft + g.fWidth) + dx,
SkIntToScalar(g.fTop + g.fHeight));
}
// xyIndex is 0 for fAdvanceX or 1 for fAdvanceY
static SkScalar advance(const SkGlyph& glyph) {
return SkFloatToScalar(glyph.fAdvanceX);
}
SkScalar SkPaint::measure_text(SkStrike* cache,
const char* text, size_t byteLength,
int* count, SkRect* bounds) const {
SkASSERT(count);
if (byteLength == 0) {
*count = 0;
if (bounds) {
bounds->setEmpty();
}
return 0;
}
SkFontPriv::GlyphCacheProc glyphCacheProc = SkFontPriv::GetGlyphCacheProc(
this->private_internal_getTextEncoding(), nullptr != bounds);
int n = 1;
const char* stop = (const char*)text + byteLength;
const SkGlyph* g = &glyphCacheProc(cache, &text, stop);
SkScalar x = advance(*g);
if (nullptr == bounds) {
for (; text < stop; n++) {
x += advance(glyphCacheProc(cache, &text, stop));
}
} else {
set_bounds(*g, bounds);
for (; text < stop; n++) {
g = &glyphCacheProc(cache, &text, stop);
join_bounds_x(*g, bounds, x);
x += advance(*g);
}
}
SkASSERT(text == stop);
*count = n;
return x;
}
#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
SkScalar SkPaint::measureText(const void* textData, size_t length, SkRect* bounds) const {
const char* text = (const char*)textData;
SkASSERT(text != nullptr || length == 0);
SkCanonicalizePaint canon(*this);
const SkPaint& paint = canon.getPaint();
SkScalar scale = canon.getScale();
const SkFont font = SkFont::LEGACY_ExtractFromPaint(paint);
auto cache = SkStrikeCache::FindOrCreateStrikeWithNoDeviceExclusive(font, paint);
SkScalar width = 0;
if (length > 0) {
int tempCount;
width = paint.measure_text(cache.get(), text, length, &tempCount, bounds);
if (scale) {
width *= scale;
if (bounds) {
bounds->fLeft *= scale;
bounds->fTop *= scale;
bounds->fRight *= scale;
bounds->fBottom *= scale;
}
}
} else if (bounds) {
// ensure that even if we don't measure_text we still update the bounds
bounds->setEmpty();
}
return width;
}
SkScalar SkPaint::getFontMetrics(SkFontMetrics* metrics) const {
return SkFont::LEGACY_ExtractFromPaint(*this).getMetrics(metrics);
}
int SkPaint::getTextWidths(const void* text, size_t len, SkScalar widths[], SkRect bounds[]) const {
const SkFont font = SkFont::LEGACY_ExtractFromPaint(*this);
SkAutoToGlyphs gly(font, text, len, this->getTextEncoding());
font.getWidthsBounds(gly.glyphs(), gly.count(), widths, bounds, this);
return gly.count();
}
#endif
///////////////////////////////////////////////////////////////////////////////
#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
#include "SkDraw.h"
struct PathPosRec {
SkPath* fDst;
const SkPoint* fPos;
};
static void PathPosProc(const SkPath* src, const SkMatrix& mx, void* ctx) {
PathPosRec* rec = static_cast<PathPosRec*>(ctx);
if (src) {
SkMatrix m(mx);
m.postTranslate(rec->fPos->fX, rec->fPos->fY);
rec->fDst->addPath(*src, m);
}
rec->fPos += 1;
}
void SkPaint::getTextPath(const void* text, size_t length,
SkScalar x, SkScalar y, SkPath* path) const {
SkFont font = SkFont::LEGACY_ExtractFromPaint(*this);
SkAutoToGlyphs gly(font, text, length, this->getTextEncoding());
SkAutoSTArray<32, SkPoint> fPos(gly.count());
font.getPos(gly.glyphs(), gly.count(), fPos.get(), {x, y});
path->reset();
PathPosRec rec = { path, fPos.get() };
font.getPaths(gly.glyphs(), gly.count(), PathPosProc, &rec);
}
void SkPaint::getPosTextPath(const void* text, size_t length,
const SkPoint pos[], SkPath* path) const {
SkFont font = SkFont::LEGACY_ExtractFromPaint(*this);
SkAutoToGlyphs gly(font, text, length, this->getTextEncoding());
path->reset();
PathPosRec rec = { path, pos };
font.getPaths(gly.glyphs(), gly.count(), PathPosProc, &rec);
}
#endif
int SkPaint::getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
SkScalar* intervals) const {
return blob->getIntercepts(bounds, intervals, this);

View File

@ -41,16 +41,16 @@ enum DrawType {
DRAW_PATH,
DRAW_PICTURE,
DRAW_POINTS,
DRAW_POS_TEXT_REMOVED_1_2019,
DRAW_POS_TEXT_TOP_BOTTOM_REMOVED_1_2019,
DRAW_POS_TEXT_H_REMOVED_1_2019,
DRAW_POS_TEXT_H_TOP_BOTTOM_REMOVED_1_2019,
DRAW_POS_TEXT,
DRAW_POS_TEXT_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT
DRAW_POS_TEXT_H,
DRAW_POS_TEXT_H_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT_H
DRAW_RECT,
DRAW_RRECT,
DRAW_SPRITE_RETIRED_2015_REMOVED_2018,
DRAW_TEXT_REMOVED_1_2019,
DRAW_TEXT,
DRAW_TEXT_ON_PATH_RETIRED_08_2018_REMOVED_10_2018,
DRAW_TEXT_TOP_BOTTOM_REMOVED_1_2019,
DRAW_TEXT_TOP_BOTTOM, // fast variant of DRAW_TEXT
DRAW_VERTICES_RETIRED_03_2017_REMOVED_01_2018,
RESTORE,
ROTATE,

View File

@ -68,6 +68,36 @@ static const SkRect* get_rect_ptr(SkReadBuffer* reader, SkRect* storage) {
}
}
class TextContainer {
public:
TextContainer(SkReadBuffer* reader, const SkPaint* paint) {
if (reader->validate(paint != nullptr)) {
fByteLength = reader->readInt();
fText = (const char*)reader->skip(fByteLength);
if (reader->isValid()) {
if (fByteLength == 0) {
fCount = 0;
} else {
fCount = SkFontPriv::ValidCountText(fText, fByteLength,
SkPaintPriv::GetEncoding(*paint));
reader->validate(fCount > 0);
}
}
}
}
operator bool() const { return fCount >= 0; }
size_t length() const { return fByteLength; }
const void* text() const { return (const void*)fText; }
unsigned count() const { return fCount; }
private:
size_t fByteLength = 0;
const char* fText = nullptr;
int fCount = -1;
};
void SkPicturePlayback::draw(SkCanvas* canvas,
SkPicture::AbortCallback* callback,
SkReadBuffer* buffer) {
@ -431,6 +461,77 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader,
canvas->drawPoints(mode, count, pts, *paint);
}
} break;
#ifdef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
case DRAW_POS_TEXT: {
const SkPaint* paint = fPictureData->getPaint(reader);
TextContainer text(reader, paint);
size_t points = reader->readInt();
reader->validate(points == text.count());
const SkPoint* pos = (const SkPoint*)reader->skip(points, sizeof(SkPoint));
BREAK_ON_READ_ERROR(reader);
if (paint && text.text()) {
SkFont font = SkFont::LEGACY_ExtractFromPaint(*paint);
auto blob = SkTextBlob::MakeFromPosText(text.text(), text.length(), pos, font,
SkPaintPriv::GetEncoding(*paint));
canvas->drawTextBlob(blob, 0, 0, *paint);
}
} break;
case DRAW_POS_TEXT_TOP_BOTTOM: {
const SkPaint* paint = fPictureData->getPaint(reader);
TextContainer text(reader, paint);
size_t points = reader->readInt();
reader->validate(points == text.count());
const SkPoint* pos = (const SkPoint*)reader->skip(points, sizeof(SkPoint));
const SkScalar top = reader->readScalar();
const SkScalar bottom = reader->readScalar();
BREAK_ON_READ_ERROR(reader);
SkRect clip = canvas->getLocalClipBounds();
if (top < clip.fBottom && bottom > clip.fTop && paint && text.text()) {
SkFont font = SkFont::LEGACY_ExtractFromPaint(*paint);
auto blob = SkTextBlob::MakeFromPosText(text.text(), text.length(), pos, font,
SkPaintPriv::GetEncoding(*paint));
canvas->drawTextBlob(blob, 0, 0, *paint);
}
} break;
case DRAW_POS_TEXT_H: {
const SkPaint* paint = fPictureData->getPaint(reader);
TextContainer text(reader, paint);
size_t xCount = reader->readInt();
reader->validate(xCount == text.count());
const SkScalar constY = reader->readScalar();
const SkScalar* xpos = (const SkScalar*)reader->skip(xCount, sizeof(SkScalar));
BREAK_ON_READ_ERROR(reader);
if (paint && text.text()) {
SkFont font = SkFont::LEGACY_ExtractFromPaint(*paint);
auto blob = SkTextBlob::MakeFromPosTextH(text.text(), text.length(), xpos, constY,
font, SkPaintPriv::GetEncoding(*paint));
canvas->drawTextBlob(blob, 0, 0, *paint);
}
} break;
case DRAW_POS_TEXT_H_TOP_BOTTOM: {
const SkPaint* paint = fPictureData->getPaint(reader);
TextContainer text(reader, paint);
size_t xCount = reader->readInt();
reader->validate(xCount == text.count());
const SkScalar* xpos = (const SkScalar*)reader->skip(SkSafeMath::Add(3, xCount),
sizeof(SkScalar));
BREAK_ON_READ_ERROR(reader);
const SkScalar top = *xpos++;
const SkScalar bottom = *xpos++;
const SkScalar constY = *xpos++;
SkRect clip = canvas->getLocalClipBounds();
if (top < clip.fBottom && bottom > clip.fTop && paint && text.text()) {
SkFont font = SkFont::LEGACY_ExtractFromPaint(*paint);
auto blob = SkTextBlob::MakeFromPosTextH(text.text(), text.length(), xpos, constY,
font, SkPaintPriv::GetEncoding(*paint));
canvas->drawTextBlob(blob, 0, 0, *paint);
}
} break;
#endif
case DRAW_RECT: {
const SkPaint* paint = fPictureData->getPaint(reader);
SkRect rect;
@ -482,6 +583,21 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader,
canvas->private_draw_shadow_rec(path, rec);
} break;
#ifdef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
case DRAW_TEXT: {
const SkPaint* paint = fPictureData->getPaint(reader);
TextContainer text(reader, paint);
SkScalar x = reader->readScalar();
SkScalar y = reader->readScalar();
BREAK_ON_READ_ERROR(reader);
if (paint && text.text()) {
canvas->drawSimpleText(text.text(), text.length(),
paint->private_internal_getTextEncoding(),
x, y, SkFont::LEGACY_ExtractFromPaint(*paint), *paint);
}
} break;
#endif
case DRAW_TEXT_BLOB: {
const SkPaint* paint = fPictureData->getPaint(reader);
const SkTextBlob* blob = fPictureData->getTextBlob(reader);
@ -493,6 +609,56 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader,
canvas->drawTextBlob(blob, x, y, *paint);
}
} break;
#ifdef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
case DRAW_TEXT_TOP_BOTTOM: {
const SkPaint* paint = fPictureData->getPaint(reader);
TextContainer text(reader, paint);
const SkScalar* ptr = (const SkScalar*)reader->skip(4 * sizeof(SkScalar));
BREAK_ON_READ_ERROR(reader);
// ptr[0] == x
// ptr[1] == y
// ptr[2] == top
// ptr[3] == bottom
SkRect clip = canvas->getLocalClipBounds();
float top = ptr[2];
float bottom = ptr[3];
if (top < clip.fBottom && bottom > clip.fTop && paint && text.text()) {
canvas->drawSimpleText(text.text(), text.length(),
paint->private_internal_getTextEncoding(), ptr[0], ptr[1],
SkFont::LEGACY_ExtractFromPaint(*paint), *paint);
}
} break;
case DRAW_TEXT_ON_PATH_RETIRED_08_2018_REMOVED_10_2018: {
const SkPaint* paint = fPictureData->getPaint(reader);
TextContainer text(reader, paint);
/* ignored */ fPictureData->getPath(reader);
SkMatrix matrix;
reader->readMatrix(&matrix);
BREAK_ON_READ_ERROR(reader);
// no longer supported, so we draw nothing
} break;
case DRAW_TEXT_RSXFORM_DEPRECATED_DEC_2018: {
const SkPaint* paint = fPictureData->getPaint(reader);
uint32_t count = reader->readUInt();
uint32_t flags = reader->readUInt();
TextContainer text(reader, paint);
const SkRSXform* xform = (const SkRSXform*)reader->skip(count, sizeof(SkRSXform));
if (flags & DRAW_TEXT_RSXFORM_HAS_CULL) {
// skip past cull rect
(void)reader->skip(sizeof(SkRect));
}
reader->validate(count == text.count());
BREAK_ON_READ_ERROR(reader);
if (text.text()) {
SkFont font = SkFont::LEGACY_ExtractFromPaint(*paint);
auto blob = SkTextBlob::MakeFromRSXform(text.text(), text.length(), xform, font,
SkPaintPriv::GetEncoding(*paint));
canvas->drawTextBlob(blob, 0, 0, *paint);
}
} break;
#endif
case DRAW_VERTICES_OBJECT: {
const SkPaint* paint = fPictureData->getPaint(reader);
const SkVertices* vertices = fPictureData->getVertices(reader);

View File

@ -16,7 +16,6 @@
#include "SkColorFilter.h"
#include "SkData.h"
#include "SkFont.h"
#include "SkFontMetrics.h"
#include "SkFontStyle.h"
#include "SkGradientShader.h"
#include "SkImage.h"
@ -557,8 +556,7 @@ static int lcanvas_drawText(lua_State* L) {
return 0;
}
// TODO: restore this logic based on SkFont instead of SkPaint
#if 0
#ifdef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
if (lua_isstring(L, 2) && lua_isnumber(L, 3) && lua_isnumber(L, 4)) {
size_t len;
const char* text = lua_tolstring(L, 2, &len);
@ -1875,8 +1873,7 @@ static int lsk_newTextBlob(lua_State* L) {
SkShaper shaper(nullptr);
// TODO: restore this logic based on SkFont instead of SkPaint
#if 0
#ifdef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
const SkPaint& paint = *get_obj<SkPaint>(L, 3);
SkFont font = SkFont::LEGACY_ExtractFromPaint(paint);
#else

93
tests/FontObjTest.cpp Normal file
View File

@ -0,0 +1,93 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkFont.h"
#include "SkPaint.h"
#include "SkTypeface.h"
#include "Test.h"
#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
static void test_fontmetrics(skiatest::Reporter* reporter,
const SkPaint& paint, const SkFont& font) {
SkFontMetrics fm0, fm1;
SkScalar h0 = paint.getFontMetrics(&fm0);
SkScalar h1 = font.getMetrics(&fm1);
REPORTER_ASSERT(reporter, h0 == h1);
#define CMP(field) REPORTER_ASSERT(reporter, fm0.field == fm1.field)
CMP(fFlags);
CMP(fTop);
CMP(fAscent);
CMP(fDescent);
CMP(fBottom);
CMP(fLeading);
#undef CMP
}
DEF_TEST(FontObj_test_cachedfont, reporter) {
SkPaint paint;
char txt[] = "long .text .with .lots .of.dots.";
unsigned mask = SkPaint::kAntiAlias_Flag |
SkPaint::kFakeBoldText_Flag |
SkPaint::kLinearText_Flag |
SkPaint::kSubpixelText_Flag |
SkPaint::kLCDRenderText_Flag |
SkPaint::kEmbeddedBitmapText_Flag |
SkPaint::kAutoHinting_Flag;
paint.setStrokeWidth(2);
{
for (unsigned flags = 0; flags <= 0xFFF; ++flags) {
if (flags & ~mask) {
continue;
}
paint.setFlags(flags);
for (int hint = 0; hint <= 3; ++hint) {
paint.setHinting((SkFontHinting)hint);
{
for (auto style : { SkPaint::kFill_Style, SkPaint::kStroke_Style}) {
paint.setStyle(style);
const SkFont font(SkFont::LEGACY_ExtractFromPaint(paint));
test_fontmetrics(reporter, paint, font);
SkRect pbounds, fbounds;
// Requesting the bounds forces a generateMetrics call.
SkScalar pwidth = paint.measureText(txt, strlen(txt), &pbounds);
SkScalar fwidth = font.measureText(txt, strlen(txt), kUTF8_SkTextEncoding,
&fbounds, &paint);
REPORTER_ASSERT(reporter, pwidth == fwidth);
REPORTER_ASSERT(reporter, pbounds == fbounds);
}
}
}
}
}
}
#endif // SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
#ifdef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
DEF_TEST(FontObj_test_aa_hinting, reporter) {
SkPaint paint;
for (bool aa : {false, true}) {
paint.setAntiAlias(aa);
for (int hint = 0; hint <= 3; ++hint) {
paint.setHinting((SkFontHinting)hint);
SkFont font = SkFont::LEGACY_ExtractFromPaint(paint);
SkPaint p2;
font.LEGACY_applyToPaint(&p2);
REPORTER_ASSERT(reporter, paint.isAntiAlias() == p2.isAntiAlias());
REPORTER_ASSERT(reporter, paint.getHinting() == p2.getHinting());
}
}
}
#endif
// need tests for SkStrSearch

View File

@ -267,6 +267,10 @@ DEF_TEST(Paint_regression_measureText, reporter) {
DEF_TEST(Paint_MoreFlattening, r) {
SkPaint paint;
paint.setColor(0x00AABBCC);
#ifdef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
paint.setTextScaleX(1.0f); // Default value, ignored.
paint.setTextSize(19);
#endif
paint.setBlendMode(SkBlendMode::kModulate);
paint.setLooper(nullptr); // Default value, ignored.
@ -300,10 +304,18 @@ DEF_TEST(Paint_getHash, r) {
paint.setColor(SK_ColorBLACK); // Reset to default value.
REPORTER_ASSERT(r, paint.getHash() == defaultHash);
// This is part of fBitfields, the last field we hash.
paint.setBlendMode(SkBlendMode::kSrc);
#ifdef SK_SUPPORT_LEGACY_PAINT_FONT_FIELDS
// SkTypeface is the first field we hash, so test it specially.
paint.setTypeface(SkTypeface::MakeDefault());
REPORTER_ASSERT(r, paint.getHash() != defaultHash);
paint.setBlendMode(SkBlendMode::kSrcOver);
paint.setTypeface(nullptr);
REPORTER_ASSERT(r, paint.getHash() == defaultHash);
#endif
// This is part of fBitfields, the last field we hash.
paint.setHinting(kSlight_SkFontHinting);
REPORTER_ASSERT(r, paint.getHash() != defaultHash);
paint.setHinting(kNormal_SkFontHinting);
REPORTER_ASSERT(r, paint.getHash() == defaultHash);
}
@ -333,6 +345,43 @@ DEF_TEST(Paint_nothingToDraw, r) {
REPORTER_ASSERT(r, !paint.nothingToDraw());
}
#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
DEF_TEST(Paint_getwidths, r) {
SkPaint paint;
const char text[] = "Hamburgefons!@#!#23425,./;'[]";
int count = paint.countText(text, strlen(text));
SkAutoTArray<uint16_t> glyphStorage(count * 2);
uint16_t* glyphs = glyphStorage.get();
(void)paint.textToGlyphs(text, strlen(text), glyphs);
paint.setTextEncoding(kGlyphID_SkTextEncoding);
SkAutoTArray<SkScalar> widthStorage(count * 2);
SkScalar* widths = widthStorage.get();
SkAutoTArray<SkRect> rectStorage(count * 2);
SkRect* bounds = rectStorage.get();
for (bool subpix : { false, true }) {
paint.setSubpixelText(subpix);
for (auto hint : { kNo_SkFontHinting, kSlight_SkFontHinting, kNormal_SkFontHinting, kFull_SkFontHinting}) {
paint.setHinting(hint);
for (auto size : { 1.0f, 12.0f, 100.0f }) {
paint.setTextSize(size);
paint.getTextWidths(glyphs, count * 2, widths, bounds);
SkFont font = SkFont::LEGACY_ExtractFromPaint(paint);
font.getWidths(glyphs, count, widths + count, bounds + count);
for (int i = 0; i < count; ++i) {
REPORTER_ASSERT(r, widths[i] == widths[i + count]);
REPORTER_ASSERT(r, bounds[i] == bounds[i + count]);
}
}
}
}
}
#endif
DEF_TEST(Font_getpos, r) {
SkFont font;
const char text[] = "Hamburgefons!@#!#23425,./;'[]";