| /* |
| * Copyright 2019 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "src/core/SkGlyphBuffer.h" |
| #include "src/core/SkGlyphRunPainter.h" |
| #include "src/text/StrikeForGPU.h" |
| |
| void SkSourceGlyphBuffer::reset() { |
| fRejectedGlyphIDs.clear(); |
| fRejectedPositions.clear(); |
| } |
| |
| void SkDrawableGlyphBuffer::ensureSize(int size) { |
| if (size > fMaxSize) { |
| fMultiBuffer.reset(size); |
| fPositions.reset(size); |
| fFormats.reset(size); |
| fMaxSize = size; |
| } |
| |
| fInputSize = 0; |
| fAcceptedSize = 0; |
| } |
| |
| void SkDrawableGlyphBuffer::startSource(const SkZip<const SkGlyphID, const SkPoint>& source) { |
| fInputSize = source.size(); |
| fAcceptedSize = 0; |
| |
| auto positions = source.get<1>(); |
| memcpy(fPositions, positions.data(), positions.size() * sizeof(SkPoint)); |
| |
| // Convert from SkGlyphIDs to SkPackedGlyphIDs. |
| SkGlyphVariant* packedIDCursor = fMultiBuffer.get(); |
| for (auto t : source) { |
| *packedIDCursor++ = SkPackedGlyphID{std::get<0>(t)}; |
| } |
| SkDEBUGCODE(fPhase = kInput); |
| } |
| |
| void SkDrawableGlyphBuffer::startSourceWithMatrixAdjustment( |
| const SkZip<const SkGlyphID, const SkPoint>& source, const SkMatrix& creationMatrix) { |
| fInputSize = source.size(); |
| fAcceptedSize = 0; |
| |
| auto positions = source.get<1>(); |
| creationMatrix.mapPoints(fPositions, positions.data(), positions.size()); |
| |
| // Convert from SkGlyphIDs to SkPackedGlyphIDs. |
| SkGlyphVariant* packedIDCursor = fMultiBuffer.get(); |
| for (auto t : source) { |
| *packedIDCursor++ = SkPackedGlyphID{std::get<0>(t)}; |
| } |
| SkDEBUGCODE(fPhase = kInput); |
| } |
| |
| void SkDrawableGlyphBuffer::startDevicePositioning( |
| const SkZip<const SkGlyphID, const SkPoint>& source, |
| const SkMatrix& positionMatrix, |
| const SkGlyphPositionRoundingSpec& roundingSpec) { |
| fInputSize = source.size(); |
| fAcceptedSize = 0; |
| |
| // Build up the mapping from source space to device space. Add the rounding constant |
| // halfSampleFreq, so we just need to floor to get the device result. |
| SkMatrix positionMatrixWithRounding = positionMatrix; |
| SkPoint halfSampleFreq = roundingSpec.halfAxisSampleFreq; |
| positionMatrixWithRounding.postTranslate(halfSampleFreq.x(), halfSampleFreq.y()); |
| |
| auto positions = source.get<1>(); |
| positionMatrixWithRounding.mapPoints(fPositions, positions.data(), positions.size()); |
| |
| auto floor = [](SkPoint pt) -> SkPoint { |
| return {SkScalarFloorToScalar(pt.x()), SkScalarFloorToScalar(pt.y())}; |
| }; |
| |
| for (auto [packedGlyphID, glyphID, pos] |
| : SkMakeZip(fMultiBuffer.get(), source.get<0>(), fPositions.get())) { |
| packedGlyphID = SkPackedGlyphID{glyphID, pos, roundingSpec.ignorePositionFieldMask}; |
| // Store rounded device coords back in pos. |
| pos = floor(pos); |
| } |
| |
| SkDEBUGCODE(fPhase = kInput); |
| } |
| |
| SkString SkDrawableGlyphBuffer::dumpInput() const { |
| SkASSERT(fPhase == kInput); |
| |
| SkString msg; |
| for (auto [packedGlyphID, pos] |
| : SkZip<SkGlyphVariant, SkPoint>{ |
| SkToSizeT(fInputSize), fMultiBuffer.get(), fPositions.get()}) { |
| msg.appendf("%s:(%a,%a), ", packedGlyphID.packedID().shortDump().c_str(), pos.x(), pos.y()); |
| } |
| return msg; |
| } |
| |
| void SkDrawableGlyphBuffer::reset() { |
| SkDEBUGCODE(fPhase = kReset); |
| if (fMaxSize > 200) { |
| fMultiBuffer.reset(); |
| fPositions.reset(); |
| fFormats.reset(); |
| fMaxSize = 0; |
| } |
| fInputSize = 0; |
| fAcceptedSize = 0; |
| } |
| |