Revert "[COLRv1] Support retrieving ClipBox."
This reverts commit4f12b4a599
. Reason for revert: MSAN issue Original change's description: > [COLRv1] Support retrieving ClipBox. > > After the discussion in [1] which was filed also in response to feedback > from Ben, the COLRv1 spec moved to not using a bounding box derived from > the `glyf` glyph for a give glyph id, but instead either use a ClipBox > found for a particular glyph id range from a ClipList array in the > COLRv1 table. If such a ClipBox is not found, perform a traversal of the > COLRv1 graph to compute the union of rectangles to compute a bounding > box. > > [1] https://github.com/googlefonts/colr-gradients-spec/issues/251 > > Includes FreeType roll: >47b1a541cb..2c853b38a7
> > Fixed: skia:12297 > Cq-Include-Trybots: luci.skia.skia.primary:Test-Android-Clang-GalaxyS6-GPU-MaliT760-arm64-Release-All-Android_NativeFonts > Change-Id: Iac3677cb1207b953876b106a1e0d754760612955 > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/435116 > Reviewed-by: Ben Wagner <bungeman@google.com> > Commit-Queue: Dominik Röttsches <drott@google.com> TBR=bungeman@google.com,drott@chromium.org,drott@google.com,behdad.esfahbod@gmail.com,skcq-be@skia-corp.google.com.iam.gserviceaccount.com Change-Id: Id041a270bd2e4d4edcaa114c524981bc2c9e5320 No-Presubmit: true No-Tree-Checks: true No-Try: true Cq-Include-Trybots: luci.skia.skia.primary:Test-Android-Clang-GalaxyS6-GPU-MaliT760-arm64-Release-All-Android_NativeFonts Reviewed-on: https://skia-review.googlesource.com/c/skia/+/437738 Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
3176e868c4
commit
df1ba0395f
2
DEPS
2
DEPS
@ -23,7 +23,7 @@ deps = {
|
||||
"third_party/externals/dng_sdk" : "https://android.googlesource.com/platform/external/dng_sdk.git@c8d0c9b1d16bfda56f15165d39e0ffa360a11123",
|
||||
"third_party/externals/egl-registry" : "https://skia.googlesource.com/external/github.com/KhronosGroup/EGL-Registry@a0bca08de07c7d7651047bedc0b653cfaaa4f2ae",
|
||||
"third_party/externals/expat" : "https://chromium.googlesource.com/external/github.com/libexpat/libexpat.git@a28238bdeebc087071777001245df1876a11f5ee",
|
||||
"third_party/externals/freetype" : "https://chromium.googlesource.com/chromium/src/third_party/freetype2.git@2c853b38a717c615d3113a64033fc896e5888fa8",
|
||||
"third_party/externals/freetype" : "https://chromium.googlesource.com/chromium/src/third_party/freetype2.git@47b1a541cb1943d85da3976b93f9a5ed490288e2",
|
||||
"third_party/externals/harfbuzz" : "https://chromium.googlesource.com/external/github.com/harfbuzz/harfbuzz.git@368e9578873798e2d17ed78a0474dec7d4e9d6c0",
|
||||
"third_party/externals/icu" : "https://chromium.googlesource.com/chromium/deps/icu.git@a0718d4f121727e30b8d52c7a189ebf5ab52421f",
|
||||
"third_party/externals/imgui" : "https://skia.googlesource.com/external/github.com/ocornut/imgui.git@9418dcb69355558f70de260483424412c5ca2fce",
|
||||
|
@ -35,8 +35,7 @@ public:
|
||||
kColorFontsRepoExtendMode,
|
||||
kColorFontsRepoRotate,
|
||||
kColorFontsRepoSkew,
|
||||
kColorFontsRepoTransform,
|
||||
kColorFontsRepoClipBox
|
||||
kColorFontsRepoTransform
|
||||
};
|
||||
|
||||
ColrV1GM(ColrV1TestType testType, SkScalar skewX, SkScalar rotateDeg)
|
||||
@ -59,8 +58,6 @@ protected:
|
||||
return SkString("skew");
|
||||
case kColorFontsRepoTransform:
|
||||
return SkString("transform");
|
||||
case kColorFontsRepoClipBox:
|
||||
return SkString("clipbox");
|
||||
}
|
||||
SkASSERT(false); /* not reached */
|
||||
return SkString();
|
||||
@ -103,9 +100,6 @@ protected:
|
||||
case kColorFontsRepoTransform:
|
||||
fEmojiFont.fGlyphs = {31, 32, 33, 34};
|
||||
break;
|
||||
case kColorFontsRepoClipBox:
|
||||
fEmojiFont.fGlyphs = {35, 36, 37, 38, 39};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,7 +166,5 @@ DEF_GM(return new ColrV1GM(ColrV1GM::kColorFontsRepoExtendMode, 0.f, 0.f);)
|
||||
DEF_GM(return new ColrV1GM(ColrV1GM::kColorFontsRepoRotate, 0.f, 0.f);)
|
||||
DEF_GM(return new ColrV1GM(ColrV1GM::kColorFontsRepoSkew, 0.f, 0.f);)
|
||||
DEF_GM(return new ColrV1GM(ColrV1GM::kColorFontsRepoTransform, 0.f, 0.f);)
|
||||
DEF_GM(return new ColrV1GM(ColrV1GM::kColorFontsRepoClipBox, 0.f, 0.f);)
|
||||
DEF_GM(return new ColrV1GM(ColrV1GM::kColorFontsRepoClipBox, -0.5f, 20.f);)
|
||||
|
||||
} // namespace skiagm
|
||||
|
Binary file not shown.
@ -37,7 +37,6 @@
|
||||
|
||||
#include <ft2build.h>
|
||||
#include <freetype/ftadvanc.h>
|
||||
#include <freetype/ftimage.h>
|
||||
#include <freetype/ftbitmap.h>
|
||||
#ifdef FT_COLOR_H // 2.10.0
|
||||
# include <freetype/ftcolor.h>
|
||||
@ -1105,62 +1104,60 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
|
||||
opaqueLayerPaint.p = nullptr;
|
||||
if (FT_Get_Color_Glyph_Paint(fFace, glyph->getGlyphID(),
|
||||
FT_COLOR_INCLUDE_ROOT_TRANSFORM, &opaqueLayerPaint)) {
|
||||
haveLayers = true;
|
||||
haveLayers = true;
|
||||
|
||||
FT_ClipBox colrGlyphBbox;
|
||||
// COLRv1 glyphs define a placeholder glyph in the glyf table that
|
||||
// defines the extrema of the glyph. If this placeholder glyph
|
||||
// contains only two points and FreeType applies the transform first -
|
||||
// as configured by setupSize() - then we get a transformed bounding
|
||||
// box that is too small as it only needs to fit the two points. To
|
||||
// fix that, create a temporary contour consisting of all four corners
|
||||
// of an imaginary rectangle enclosing those two points, then
|
||||
// transform that and perform the bounding box computations on this
|
||||
// one.
|
||||
|
||||
// COLRv1 optionally provides a ClipBox that we can use for allocation.
|
||||
if (FT_Get_Color_Glyph_ClipBox(fFace, glyph->getGlyphID(), &colrGlyphBbox)) {
|
||||
// Find enclosing bounding box of clip box corner points, needed
|
||||
// when clipbox is transformed.
|
||||
bounds.xMin = colrGlyphBbox.bottom_left.x;
|
||||
bounds.xMax = colrGlyphBbox.bottom_left.x;
|
||||
bounds.yMin = colrGlyphBbox.bottom_left.y;
|
||||
bounds.yMax = colrGlyphBbox.bottom_left.y;
|
||||
FT_Set_Transform(fFace, nullptr, nullptr);
|
||||
|
||||
for (auto& corner : {colrGlyphBbox.top_left,
|
||||
colrGlyphBbox.top_right,
|
||||
colrGlyphBbox.bottom_right}) {
|
||||
if (corner.x < bounds.xMin) {
|
||||
bounds.xMin = corner.x;
|
||||
}
|
||||
if (corner.y < bounds.yMin) {
|
||||
bounds.yMin = corner.y;
|
||||
}
|
||||
if (corner.x > bounds.xMax) {
|
||||
bounds.xMax = corner.x;
|
||||
}
|
||||
if (corner.y > bounds.yMax) {
|
||||
bounds.yMax = corner.y;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Otherwise we need to traverse the glyph graph with a focus on measuring the
|
||||
// required bounding box.
|
||||
FT_BBox computed_bounds;
|
||||
if (!computeColrV1GlyphBoundingBox(fFace, glyph->getGlyphID(), &computed_bounds)) {
|
||||
glyph->zeroMetrics();
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset face so the main glyph slot contains information about the
|
||||
// base glyph again, for usage for computing and copying horizontal
|
||||
// metrics from FreeType to Skia below.
|
||||
if (this->setupSize()) {
|
||||
glyph->zeroMetrics();
|
||||
return;
|
||||
}
|
||||
|
||||
FT_Error err;
|
||||
err = FT_Load_Glyph(
|
||||
fFace, glyph->getGlyphID(), fLoadGlyphFlags | FT_LOAD_BITMAP_METRICS_ONLY);
|
||||
if (err != 0) {
|
||||
glyph->zeroMetrics();
|
||||
return;
|
||||
}
|
||||
|
||||
bounds = computed_bounds;
|
||||
err = FT_Load_Glyph(fFace, glyph->getGlyphID(),
|
||||
fLoadGlyphFlags | FT_LOAD_BITMAP_METRICS_ONLY);
|
||||
if (err != 0 || fFace->glyph->outline.n_contours == 0) {
|
||||
glyph->zeroMetrics();
|
||||
return;
|
||||
}
|
||||
emboldenIfNeeded(fFace, fFace->glyph, glyph->getGlyphID());
|
||||
|
||||
FT_BBox bbox_untransformed;
|
||||
FT_Outline_Get_CBox(&fFace->glyph->outline, &bbox_untransformed);
|
||||
|
||||
FT_Outline bboxOutline;
|
||||
err = FT_Outline_New(gFTLibrary->library(), 4, 0, &bboxOutline);
|
||||
if (err != 0) {
|
||||
glyph->zeroMetrics();
|
||||
return;
|
||||
}
|
||||
|
||||
// Compose a rectangle contour by setting the four corners.
|
||||
bboxOutline.points[0].x = bbox_untransformed.xMin;
|
||||
bboxOutline.points[0].y = bbox_untransformed.yMin;
|
||||
|
||||
bboxOutline.points[1].x = bbox_untransformed.xMin;
|
||||
bboxOutline.points[1].y = bbox_untransformed.yMax;
|
||||
|
||||
bboxOutline.points[2].x = bbox_untransformed.xMax;
|
||||
bboxOutline.points[2].y = bbox_untransformed.yMax;
|
||||
|
||||
bboxOutline.points[3].x = bbox_untransformed.xMax;
|
||||
bboxOutline.points[3].y = bbox_untransformed.yMin;
|
||||
|
||||
FT_Outline_Transform(&bboxOutline, &fMatrix22);
|
||||
|
||||
FT_Outline faceOutline = fFace->glyph->outline;
|
||||
fFace->glyph->outline = bboxOutline;
|
||||
// Retrieve from temporarily replaced transformed rectangle outline.
|
||||
getBBoxForCurrentGlyph(glyph, &bounds, true);
|
||||
fFace->glyph->outline = faceOutline;
|
||||
FT_Outline_Done(gFTLibrary->library(), &bboxOutline);
|
||||
|
||||
}
|
||||
#endif // #TT_SUPPORT_COLRV1
|
||||
|
||||
|
@ -756,18 +756,9 @@ void colrv1_draw_glyph_with_path(SkCanvas* canvas, const FT_Color* palette, FT_F
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* In drawing mode, concatenates the transforms directly on SkCanvas. In
|
||||
* bounding box calculation mode, no SkCanvas is specified, but we only want to
|
||||
* retrieve the transform from the FreeType paint object. */
|
||||
void colrv1_transform(FT_Face face,
|
||||
FT_COLR_Paint colrv1_paint,
|
||||
SkCanvas* canvas,
|
||||
SkMatrix* out_transform = 0) {
|
||||
void colrv1_transform(SkCanvas* canvas, FT_Face face, FT_COLR_Paint colrv1_paint) {
|
||||
SkMatrix transform;
|
||||
|
||||
SkASSERT(canvas || out_transform);
|
||||
|
||||
switch (colrv1_paint.format) {
|
||||
case FT_COLR_PAINTFORMAT_TRANSFORM: {
|
||||
transform = ToSkMatrix(colrv1_paint.u.transform.affine);
|
||||
@ -818,14 +809,10 @@ void colrv1_transform(FT_Face face,
|
||||
SkASSERT(false);
|
||||
}
|
||||
}
|
||||
if (canvas) {
|
||||
canvas->concat(transform);
|
||||
}
|
||||
if (out_transform) {
|
||||
*out_transform = transform;
|
||||
}
|
||||
canvas->concat(transform);
|
||||
}
|
||||
|
||||
|
||||
bool colrv1_start_glyph(SkCanvas* canvas,
|
||||
const FT_Color* palette,
|
||||
FT_Face ft_face,
|
||||
@ -890,28 +877,28 @@ bool colrv1_traverse_paint(SkCanvas* canvas,
|
||||
FT_COLOR_NO_ROOT_TRANSFORM);
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_TRANSFORM:
|
||||
colrv1_transform(face, paint, canvas);
|
||||
colrv1_transform(canvas, face, paint);
|
||||
traverse_result = colrv1_traverse_paint(canvas, palette, face,
|
||||
paint.u.transform.paint, visited_set);
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_TRANSLATE:
|
||||
colrv1_transform(face, paint, canvas);
|
||||
colrv1_transform(canvas, face, paint);
|
||||
traverse_result = colrv1_traverse_paint(canvas, palette, face,
|
||||
paint.u.translate.paint, visited_set);
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_SCALE:
|
||||
colrv1_transform(face, paint, canvas);
|
||||
colrv1_transform(canvas, face, paint);
|
||||
traverse_result = colrv1_traverse_paint(canvas, palette, face,
|
||||
paint.u.scale.paint, visited_set);
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_ROTATE:
|
||||
colrv1_transform(face, paint, canvas);
|
||||
colrv1_transform(canvas, face, paint);
|
||||
traverse_result =
|
||||
colrv1_traverse_paint(canvas, palette, face,
|
||||
paint.u.rotate.paint, visited_set);
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_SKEW:
|
||||
colrv1_transform(face, paint, canvas);
|
||||
colrv1_transform(canvas, face, paint);
|
||||
traverse_result =
|
||||
colrv1_traverse_paint(canvas, palette, face,
|
||||
paint.u.skew.paint, visited_set);
|
||||
@ -943,72 +930,6 @@ bool colrv1_traverse_paint(SkCanvas* canvas,
|
||||
return traverse_result;
|
||||
}
|
||||
|
||||
SkPath GetClipBoxPath(FT_Face ft_face, uint16_t glyph_id, bool untransformed) {
|
||||
SkPath resultPath;
|
||||
|
||||
using DoneFTSize = SkFunctionWrapper<decltype(FT_Done_Size), FT_Done_Size>;
|
||||
std::unique_ptr<std::remove_pointer_t<FT_Size>, DoneFTSize> unscaledFtSize = nullptr;
|
||||
|
||||
FT_Size oldSize = ft_face->size;
|
||||
FT_Matrix oldTransform;
|
||||
FT_Vector oldDelta;
|
||||
FT_Error err = 0;
|
||||
|
||||
if (untransformed) {
|
||||
unscaledFtSize.reset(
|
||||
[ft_face]() -> FT_Size {
|
||||
FT_Size size;
|
||||
FT_Error err = FT_New_Size(ft_face, &size);
|
||||
if (err != 0) {
|
||||
SK_TRACEFTR(err,
|
||||
"FT_New_Size(%s) failed in generateFacePathStaticCOLRv1.",
|
||||
ft_face->family_name);
|
||||
return nullptr;
|
||||
}
|
||||
return size;
|
||||
}());
|
||||
if (!unscaledFtSize) {
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
err = FT_Activate_Size(unscaledFtSize.get());
|
||||
if (err != 0) {
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
err = FT_Set_Char_Size(ft_face, SkIntToFDot6(ft_face->units_per_EM), 0, 0, 0);
|
||||
if (err != 0) {
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
FT_Get_Transform(ft_face, &oldTransform, &oldDelta);
|
||||
FT_Set_Transform(ft_face, nullptr, nullptr);
|
||||
}
|
||||
|
||||
FT_ClipBox colrGlyphClipBox;
|
||||
if (FT_Get_Color_Glyph_ClipBox(ft_face, glyph_id, &colrGlyphClipBox)) {
|
||||
resultPath = SkPath::Polygon({{SkFDot6ToScalar(colrGlyphClipBox.bottom_left.x),
|
||||
-SkFDot6ToScalar(colrGlyphClipBox.bottom_left.y)},
|
||||
{SkFDot6ToScalar(colrGlyphClipBox.top_left.x),
|
||||
-SkFDot6ToScalar(colrGlyphClipBox.top_left.y)},
|
||||
{SkFDot6ToScalar(colrGlyphClipBox.top_right.x),
|
||||
-SkFDot6ToScalar(colrGlyphClipBox.top_right.y)},
|
||||
{SkFDot6ToScalar(colrGlyphClipBox.bottom_right.x),
|
||||
-SkFDot6ToScalar(colrGlyphClipBox.bottom_right.y)}},
|
||||
true);
|
||||
}
|
||||
|
||||
if (untransformed) {
|
||||
err = FT_Activate_Size(oldSize);
|
||||
if (err != 0) {
|
||||
return resultPath;
|
||||
}
|
||||
FT_Set_Transform(ft_face, &oldTransform, &oldDelta);
|
||||
}
|
||||
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
bool colrv1_start_glyph(SkCanvas* canvas,
|
||||
const FT_Color* palette,
|
||||
FT_Face ft_face,
|
||||
@ -1019,149 +940,11 @@ bool colrv1_start_glyph(SkCanvas* canvas,
|
||||
bool has_colrv1_layers = false;
|
||||
if (FT_Get_Color_Glyph_Paint(ft_face, glyph_id, root_transform, &opaque_paint)) {
|
||||
has_colrv1_layers = true;
|
||||
|
||||
SkPath clipBoxPath =
|
||||
GetClipBoxPath(ft_face, glyph_id, root_transform == FT_COLOR_NO_ROOT_TRANSFORM);
|
||||
if (!clipBoxPath.isEmpty()) {
|
||||
canvas->clipPath(clipBoxPath, true);
|
||||
}
|
||||
|
||||
VisitedSet visited_set;
|
||||
colrv1_traverse_paint(canvas, palette, ft_face, opaque_paint, &visited_set);
|
||||
}
|
||||
return has_colrv1_layers;
|
||||
}
|
||||
|
||||
bool colrv1_start_glyph_bounds(SkMatrix *ctm,
|
||||
SkRect* bounds,
|
||||
FT_Face ft_face,
|
||||
uint16_t glyph_id,
|
||||
FT_Color_Root_Transform root_transform);
|
||||
|
||||
bool colrv1_traverse_paint_bounds(SkMatrix* ctm,
|
||||
SkRect* bounds,
|
||||
FT_Face face,
|
||||
FT_OpaquePaint opaque_paint,
|
||||
VisitedSet* visited_set) {
|
||||
// Cycle detection, see section "5.7.11.1.9 Color glyphs as a directed acyclic graph".
|
||||
if (visited_set->contains(opaque_paint)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
visited_set->add(opaque_paint);
|
||||
SK_AT_SCOPE_EXIT(visited_set->remove(opaque_paint));
|
||||
|
||||
FT_COLR_Paint paint;
|
||||
if (!FT_Get_Paint(face, opaque_paint, &paint)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Keep track of failures to retrieve the FT_COLR_Paint from FreeType in the
|
||||
// recursion, cancel recursion when a paint retrieval fails.
|
||||
bool traverse_result = true;
|
||||
SkMatrix restore_matrix = *ctm;
|
||||
SK_AT_SCOPE_EXIT(*ctm = restore_matrix);
|
||||
|
||||
switch (paint.format) {
|
||||
case FT_COLR_PAINTFORMAT_COLR_LAYERS: {
|
||||
FT_LayerIterator& layer_iterator = paint.u.colr_layers.layer_iterator;
|
||||
FT_OpaquePaint opaque_paint_fetch;
|
||||
opaque_paint_fetch.p = nullptr;
|
||||
while (FT_Get_Paint_Layers(face, &layer_iterator, &opaque_paint_fetch)) {
|
||||
colrv1_traverse_paint_bounds(ctm, bounds, face, opaque_paint_fetch, visited_set);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FT_COLR_PAINTFORMAT_GLYPH: {
|
||||
FT_UInt glyphID = paint.u.glyph.glyphID;
|
||||
SkPath path;
|
||||
if ((traverse_result = generateFacePathCOLRv1(face, glyphID, &path))) {
|
||||
path.transform(*ctm);
|
||||
bounds->join(path.getBounds());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FT_COLR_PAINTFORMAT_COLR_GLYPH:
|
||||
traverse_result = colrv1_start_glyph_bounds(
|
||||
ctm, bounds, face, paint.u.colr_glyph.glyphID, FT_COLOR_NO_ROOT_TRANSFORM);
|
||||
break;
|
||||
|
||||
case FT_COLR_PAINTFORMAT_TRANSFORM: {
|
||||
SkMatrix transform_matrix;
|
||||
colrv1_transform(face, paint, nullptr, &transform_matrix);
|
||||
ctm->preConcat(transform_matrix);
|
||||
traverse_result = colrv1_traverse_paint_bounds(
|
||||
ctm, bounds, face, paint.u.transform.paint, visited_set);
|
||||
break;
|
||||
}
|
||||
case FT_COLR_PAINTFORMAT_TRANSLATE: {
|
||||
SkMatrix transform_matrix;
|
||||
colrv1_transform(face, paint, nullptr, &transform_matrix);
|
||||
ctm->preConcat(transform_matrix);
|
||||
traverse_result = colrv1_traverse_paint_bounds(
|
||||
ctm, bounds, face, paint.u.translate.paint, visited_set);
|
||||
break;
|
||||
}
|
||||
case FT_COLR_PAINTFORMAT_SCALE: {
|
||||
SkMatrix transform_matrix;
|
||||
colrv1_transform(face, paint, nullptr, &transform_matrix);
|
||||
ctm->preConcat(transform_matrix);
|
||||
traverse_result = colrv1_traverse_paint_bounds(
|
||||
ctm, bounds, face, paint.u.scale.paint, visited_set);
|
||||
break;
|
||||
}
|
||||
case FT_COLR_PAINTFORMAT_ROTATE: {
|
||||
SkMatrix transform_matrix;
|
||||
colrv1_transform(face, paint, nullptr, &transform_matrix);
|
||||
ctm->preConcat(transform_matrix);
|
||||
traverse_result = colrv1_traverse_paint_bounds(
|
||||
ctm, bounds, face, paint.u.rotate.paint, visited_set);
|
||||
break;
|
||||
}
|
||||
case FT_COLR_PAINTFORMAT_SKEW: {
|
||||
SkMatrix transform_matrix;
|
||||
colrv1_transform(face, paint, nullptr, &transform_matrix);
|
||||
ctm->preConcat(transform_matrix);
|
||||
traverse_result = colrv1_traverse_paint_bounds(
|
||||
ctm, bounds, face, paint.u.skew.paint, visited_set);
|
||||
break;
|
||||
}
|
||||
case FT_COLR_PAINTFORMAT_COMPOSITE: {
|
||||
traverse_result = colrv1_traverse_paint_bounds(
|
||||
ctm, bounds, face, paint.u.composite.backdrop_paint, visited_set);
|
||||
traverse_result = colrv1_traverse_paint_bounds(
|
||||
ctm, bounds, face, paint.u.composite.source_paint, visited_set);
|
||||
break;
|
||||
}
|
||||
case FT_COLR_PAINTFORMAT_SOLID:
|
||||
case FT_COLR_PAINTFORMAT_LINEAR_GRADIENT:
|
||||
case FT_COLR_PAINTFORMAT_RADIAL_GRADIENT:
|
||||
case FT_COLR_PAINTFORMAT_SWEEP_GRADIENT: {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SkASSERT(false);
|
||||
break;
|
||||
}
|
||||
return traverse_result;
|
||||
}
|
||||
|
||||
|
||||
bool colrv1_start_glyph_bounds(SkMatrix *ctm,
|
||||
SkRect* bounds,
|
||||
FT_Face ft_face,
|
||||
uint16_t glyph_id,
|
||||
FT_Color_Root_Transform root_transform) {
|
||||
FT_OpaquePaint opaque_paint;
|
||||
opaque_paint.p = nullptr;
|
||||
bool has_colrv1_layers = false;
|
||||
if (FT_Get_Color_Glyph_Paint(ft_face, glyph_id, root_transform, &opaque_paint)) {
|
||||
has_colrv1_layers = true;
|
||||
VisitedSet visited_set;
|
||||
colrv1_traverse_paint_bounds(ctm, bounds, ft_face, opaque_paint, &visited_set);
|
||||
}
|
||||
return has_colrv1_layers;
|
||||
}
|
||||
#endif // TT_SUPPORT_COLRV1
|
||||
|
||||
} // namespace
|
||||
@ -1667,27 +1450,3 @@ bool SkScalerContext_FreeType_Base::generateFacePath(FT_Face face,
|
||||
SkPath* path) {
|
||||
return generateFacePathStatic(face, glyphID, path);
|
||||
}
|
||||
|
||||
bool SkScalerContext_FreeType_Base::computeColrV1GlyphBoundingBox(FT_Face face,
|
||||
SkGlyphID glyphID,
|
||||
FT_BBox* boundingBox) {
|
||||
#ifdef TT_SUPPORT_COLRV1
|
||||
SkMatrix ctm;
|
||||
SkRect bounds;
|
||||
if (!colrv1_start_glyph_bounds(&ctm, &bounds, face, glyphID, FT_COLOR_INCLUDE_ROOT_TRANSFORM)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Convert back to FT_BBox as caller needs it in this format. */
|
||||
bounds.sort();
|
||||
boundingBox->xMin = SkScalarToFDot6(bounds.left());
|
||||
boundingBox->xMax = SkScalarToFDot6(bounds.right());
|
||||
boundingBox->yMin = SkScalarToFDot6(-bounds.bottom());
|
||||
boundingBox->yMax = SkScalarToFDot6(-bounds.top());
|
||||
|
||||
return true;
|
||||
#else
|
||||
SkASSERT(false);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
@ -23,8 +23,6 @@ typedef struct FT_LibraryRec_* FT_Library;
|
||||
typedef struct FT_FaceRec_* FT_Face;
|
||||
typedef struct FT_StreamRec_* FT_Stream;
|
||||
typedef signed long FT_Pos;
|
||||
typedef struct FT_BBox_ FT_BBox;
|
||||
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
const char* SkTraceFtrGetError(int);
|
||||
@ -50,16 +48,6 @@ protected:
|
||||
void generateGlyphImage(FT_Face face, const SkGlyph& glyph, const SkMatrix& bitmapTransform);
|
||||
bool generateGlyphPath(FT_Face face, SkPath* path);
|
||||
bool generateFacePath(FT_Face face, SkGlyphID glyphID, SkPath* path);
|
||||
|
||||
// Computes a bounding box for a COLRv1 glyph id in FT_BBox 26.6 format and FreeType's y-up
|
||||
// coordinate space.
|
||||
// Needed to call into COLRv1 from generateMetrics().
|
||||
//
|
||||
// Note : This method may change the configured size and transforms on FT_Face. Make sure to
|
||||
// configure size, matrix and load glyphs as needed after using this function to restore the
|
||||
// state of FT_Face.
|
||||
bool computeColrV1GlyphBoundingBox(FT_Face face, SkGlyphID glyphID, FT_BBox* boundingBox);
|
||||
|
||||
private:
|
||||
using INHERITED = SkScalerContext;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user