1 /*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkGlyph.h"
9
10 #include "SkArenaAlloc.h"
11 #include "SkMakeUnique.h"
12 #include "SkScalerContext.h"
13
toMask(SkMask * mask) const14 void SkGlyph::toMask(SkMask* mask) const {
15 SkASSERT(mask);
16
17 mask->fImage = (uint8_t*)fImage;
18 mask->fBounds.set(fLeft, fTop, fLeft + fWidth, fTop + fHeight);
19 mask->fRowBytes = this->rowBytes();
20 mask->fFormat = static_cast<SkMask::Format>(fMaskFormat);
21 }
22
zeroMetrics()23 void SkGlyph::zeroMetrics() {
24 fAdvanceX = 0;
25 fAdvanceY = 0;
26 fWidth = 0;
27 fHeight = 0;
28 fTop = 0;
29 fLeft = 0;
30 }
31
bits_to_bytes(size_t bits)32 static size_t bits_to_bytes(size_t bits) {
33 return (bits + 7) >> 3;
34 }
35
format_alignment(SkMask::Format format)36 static size_t format_alignment(SkMask::Format format) {
37 switch (format) {
38 case SkMask::kBW_Format:
39 case SkMask::kA8_Format:
40 case SkMask::k3D_Format:
41 case SkMask::kSDF_Format:
42 return alignof(uint8_t);
43 case SkMask::kARGB32_Format:
44 return alignof(uint32_t);
45 case SkMask::kLCD16_Format:
46 return alignof(uint16_t);
47 default:
48 SK_ABORT("Unknown mask format.");
49 break;
50 }
51 return 0;
52 }
53
format_rowbytes(int width,SkMask::Format format)54 static size_t format_rowbytes(int width, SkMask::Format format) {
55 return format == SkMask::kBW_Format ? bits_to_bytes(width)
56 : width * format_alignment(format);
57 }
58
formatAlignment() const59 size_t SkGlyph::formatAlignment() const {
60 auto format = static_cast<SkMask::Format>(fMaskFormat);
61 return format_alignment(format);
62 }
63
allocImage(SkArenaAlloc * alloc)64 size_t SkGlyph::allocImage(SkArenaAlloc* alloc) {
65 auto size = this->computeImageSize();
66 auto format = static_cast<SkMask::Format>(fMaskFormat);
67 fImage = alloc->makeBytesAlignedTo(size, format_alignment(format));
68
69 return size;
70 }
71
rowBytes() const72 size_t SkGlyph::rowBytes() const {
73 return format_rowbytes(fWidth, (SkMask::Format)fMaskFormat);
74 }
75
rowBytesUsingFormat(SkMask::Format format) const76 size_t SkGlyph::rowBytesUsingFormat(SkMask::Format format) const {
77 return format_rowbytes(fWidth, format);
78 }
79
computeImageSize() const80 size_t SkGlyph::computeImageSize() const {
81 size_t size = this->rowBytes() * fHeight;
82
83 if (fMaskFormat == SkMask::k3D_Format) {
84 size *= 3;
85 }
86
87 return size;
88 }
89
copyImageData(const SkGlyph & from,SkArenaAlloc * alloc)90 size_t SkGlyph::copyImageData(const SkGlyph& from, SkArenaAlloc* alloc) {
91 fMaskFormat = from.fMaskFormat;
92 fWidth = from.fWidth;
93 fHeight = from.fHeight;
94 fLeft = from.fLeft;
95 fTop = from.fTop;
96 fForceBW = from.fForceBW;
97
98 if (from.fImage != nullptr) {
99 auto imageSize = this->allocImage(alloc);
100 SkASSERT(imageSize == from.computeImageSize());
101
102 memcpy(fImage, from.fImage, imageSize);
103 return imageSize;
104 }
105
106 return 0u;
107 }
108
addPath(SkScalerContext * scalerContext,SkArenaAlloc * alloc)109 SkPath* SkGlyph::addPath(SkScalerContext* scalerContext, SkArenaAlloc* alloc) {
110 if (!this->isEmpty()) {
111 if (fPathData == nullptr) {
112 fPathData = alloc->make<SkGlyph::PathData>();
113 if (scalerContext->getPath(this->getPackedID(), &fPathData->fPath)) {
114 fPathData->fPath.updateBoundsCache();
115 fPathData->fPath.getGenerationID();
116 fPathData->fHasPath = true;
117 }
118 }
119 }
120 return this->path();
121 }
122
123