1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/pdf/SkClusterator.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/private/SkTo.h"
11cb93a386Sopenharmony_ci#include "src/core/SkGlyphRun.h"
12cb93a386Sopenharmony_ci#include "src/utils/SkUTF.h"
13cb93a386Sopenharmony_ci
14cb93a386Sopenharmony_cistatic bool is_reversed(const uint32_t* clusters, uint32_t count) {
15cb93a386Sopenharmony_ci    // "ReversedChars" is how PDF deals with RTL text.
16cb93a386Sopenharmony_ci    // return true if more than one cluster and monotonicly decreasing to zero.
17cb93a386Sopenharmony_ci    if (count < 2 || clusters[0] == 0 || clusters[count - 1] != 0) {
18cb93a386Sopenharmony_ci        return false;
19cb93a386Sopenharmony_ci    }
20cb93a386Sopenharmony_ci    for (uint32_t i = 0; i + 1 < count; ++i) {
21cb93a386Sopenharmony_ci        if (clusters[i + 1] > clusters[i]) {
22cb93a386Sopenharmony_ci            return false;
23cb93a386Sopenharmony_ci        }
24cb93a386Sopenharmony_ci    }
25cb93a386Sopenharmony_ci    return true;
26cb93a386Sopenharmony_ci}
27cb93a386Sopenharmony_ci
28cb93a386Sopenharmony_ciSkClusterator::SkClusterator(const SkGlyphRun& run)
29cb93a386Sopenharmony_ci    : fClusters(run.clusters().data())
30cb93a386Sopenharmony_ci    , fUtf8Text(run.text().data())
31cb93a386Sopenharmony_ci    , fGlyphCount(SkToU32(run.glyphsIDs().size()))
32cb93a386Sopenharmony_ci    , fTextByteLength(SkToU32(run.text().size()))
33cb93a386Sopenharmony_ci    , fReversedChars(fClusters ? is_reversed(fClusters, fGlyphCount) : false)
34cb93a386Sopenharmony_ci{
35cb93a386Sopenharmony_ci    if (fClusters) {
36cb93a386Sopenharmony_ci        SkASSERT(fUtf8Text && fTextByteLength > 0 && fGlyphCount > 0);
37cb93a386Sopenharmony_ci    } else {
38cb93a386Sopenharmony_ci        SkASSERT(!fUtf8Text && fTextByteLength == 0);
39cb93a386Sopenharmony_ci    }
40cb93a386Sopenharmony_ci}
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_ciSkClusterator::Cluster SkClusterator::next() {
43cb93a386Sopenharmony_ci    if (fCurrentGlyphIndex >= fGlyphCount) {
44cb93a386Sopenharmony_ci        return Cluster{nullptr, 0, 0, 0};
45cb93a386Sopenharmony_ci    }
46cb93a386Sopenharmony_ci    if (!fClusters || !fUtf8Text) {
47cb93a386Sopenharmony_ci        return Cluster{nullptr, 0, fCurrentGlyphIndex++, 1};
48cb93a386Sopenharmony_ci    }
49cb93a386Sopenharmony_ci    uint32_t clusterGlyphIndex = fCurrentGlyphIndex;
50cb93a386Sopenharmony_ci    uint32_t cluster = fClusters[clusterGlyphIndex];
51cb93a386Sopenharmony_ci    do {
52cb93a386Sopenharmony_ci        ++fCurrentGlyphIndex;
53cb93a386Sopenharmony_ci    } while (fCurrentGlyphIndex < fGlyphCount && cluster == fClusters[fCurrentGlyphIndex]);
54cb93a386Sopenharmony_ci    uint32_t clusterGlyphCount = fCurrentGlyphIndex - clusterGlyphIndex;
55cb93a386Sopenharmony_ci    uint32_t clusterEnd = fTextByteLength;
56cb93a386Sopenharmony_ci    for (unsigned i = 0; i < fGlyphCount; ++i) {
57cb93a386Sopenharmony_ci       uint32_t c = fClusters[i];
58cb93a386Sopenharmony_ci       if (c > cluster && c < clusterEnd) {
59cb93a386Sopenharmony_ci           clusterEnd = c;
60cb93a386Sopenharmony_ci       }
61cb93a386Sopenharmony_ci    }
62cb93a386Sopenharmony_ci    uint32_t clusterLen = clusterEnd - cluster;
63cb93a386Sopenharmony_ci    return Cluster{fUtf8Text + cluster, clusterLen, clusterGlyphIndex, clusterGlyphCount};
64cb93a386Sopenharmony_ci}
65