blob: 3b0074ec6ad1ba271e0dcd1427beada8d1f631af [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h"
#include <algorithm>
#include <memory>
#include "third_party/blink/renderer/platform/fonts/script_run_iterator.h"
#include "third_party/blink/renderer/platform/fonts/small_caps_iterator.h"
#include "third_party/blink/renderer/platform/fonts/symbols_iterator.h"
#include "third_party/blink/renderer/platform/fonts/utf16_text_iterator.h"
#include "third_party/blink/renderer/platform/text/character.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
RunSegmenter::RunSegmenter(const UChar* buffer,
unsigned buffer_size,
FontOrientation run_orientation,
unsigned start_offset)
: buffer_size_(buffer_size),
start_offset_(start_offset),
candidate_range_(NullRange(start_offset)),
script_run_iterator_(
std::make_unique<ScriptRunIterator>(buffer + start_offset,
buffer_size)),
orientation_iterator_(
run_orientation == FontOrientation::kVerticalMixed
? std::make_unique<OrientationIterator>(buffer + start_offset,
buffer_size,
run_orientation)
: nullptr),
symbols_iterator_(std::make_unique<SymbolsIterator>(buffer + start_offset,
buffer_size)),
last_split_(0),
script_run_iterator_position_(0),
orientation_iterator_position_(
run_orientation == FontOrientation::kVerticalMixed ? 0
: buffer_size_),
symbols_iterator_position_(0),
at_end_(!buffer_size_) {}
template <class Iterator, typename SegmentationCategory>
void RunSegmenter::ConsumeIteratorPastLastSplit(
std::unique_ptr<Iterator>& iterator,
unsigned* iterator_position,
SegmentationCategory* segmentation_category) {
if (*iterator_position <= last_split_ && *iterator_position < buffer_size_) {
while (iterator->Consume(iterator_position, segmentation_category)) {
if (*iterator_position > last_split_)
return;
}
}
}
// Consume the input until the next range. Returns false if no more ranges are
// available.
bool RunSegmenter::Consume(RunSegmenterRange* next_range) {
if (at_end_)
return false;
ConsumeIteratorPastLastSplit(script_run_iterator_,
&script_run_iterator_position_,
&candidate_range_.script);
ConsumeIteratorPastLastSplit(orientation_iterator_,
&orientation_iterator_position_,
&candidate_range_.render_orientation);
ConsumeIteratorPastLastSplit(symbols_iterator_, &symbols_iterator_position_,
&candidate_range_.font_fallback_priority);
unsigned positions[] = {script_run_iterator_position_,
orientation_iterator_position_,
symbols_iterator_position_};
last_split_ = *std::min_element(std::begin(positions), std::end(positions));
candidate_range_.start = candidate_range_.end;
candidate_range_.end = last_split_ + start_offset_;
*next_range = candidate_range_;
at_end_ = (last_split_ == buffer_size_);
return true;
}
} // namespace blink