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 14 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 23 void SkGlyph::zeroMetrics() { 24 fAdvanceX = 0; 25 fAdvanceY = 0; 26 fWidth = 0; 27 fHeight = 0; 28 fTop = 0; 29 fLeft = 0; 30 } 31 32 static size_t bits_to_bytes(size_t bits) { 33 return (bits + 7) >> 3; 34 } 35 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 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 59 size_t SkGlyph::formatAlignment() const { 60 auto format = static_cast<SkMask::Format>(fMaskFormat); 61 return format_alignment(format); 62 } 63 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 72 size_t SkGlyph::rowBytes() const { 73 return format_rowbytes(fWidth, (SkMask::Format)fMaskFormat); 74 } 75 76 size_t SkGlyph::rowBytesUsingFormat(SkMask::Format format) const { 77 return format_rowbytes(fWidth, format); 78 } 79 80 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 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 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