blob: 9d2e6dbbe117b8c01395c53441318c6993114e55 [file] [log] [blame]
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "cobalt/loader/font/typeface_decoder.h"
namespace cobalt {
namespace loader {
namespace font {
TypefaceDecoder::TypefaceDecoder(
render_tree::ResourceProvider* resource_provider,
const SuccessCallback& success_callback,
const FailureCallback& failure_callback,
const ErrorCallback& error_callback)
: resource_provider_(resource_provider),
success_callback_(success_callback),
error_callback_(error_callback),
is_raw_data_too_large_(false),
suspended_(false) {
UNREFERENCED_PARAMETER(failure_callback);
DCHECK(resource_provider_);
DCHECK(!success_callback_.is_null());
DCHECK(!error_callback_.is_null());
}
void TypefaceDecoder::DecodeChunk(const char* data, size_t size) {
if (suspended_) {
DLOG(WARNING) << __FUNCTION__ << "[" << this << "] while suspended.";
return;
}
// If the data was already too large, then there's no need to process this
// chunk. Just early out.
if (is_raw_data_too_large_) {
return;
}
if (!raw_data_) {
raw_data_ = make_scoped_ptr(
new render_tree::ResourceProvider::RawTypefaceDataVector());
}
size_t start_size = raw_data_->size();
// Verify that adding this chunk to the raw data won't cause it to become
// larger than the max allowed size. If it will, then set the flag indicating
// that the data was too large and release the data.
if (start_size + size > render_tree::ResourceProvider::kMaxTypefaceDataSize) {
is_raw_data_too_large_ = true;
ReleaseRawData();
return;
}
raw_data_->resize(start_size + size);
memcpy(&((*raw_data_)[start_size]), data, size);
}
void TypefaceDecoder::Finish() {
if (suspended_) {
DLOG(WARNING) << __FUNCTION__ << "[" << this << "] while suspended.";
return;
}
if (is_raw_data_too_large_) {
error_callback_.Run("Raw typeface data size too large");
return;
}
if (!resource_provider_) {
error_callback_.Run(
"No resource provider was passed to the TypefaceDecoder.");
return;
}
std::string error_string;
scoped_refptr<render_tree::Typeface> decoded_typeface =
resource_provider_->CreateTypefaceFromRawData(raw_data_.Pass(),
&error_string);
if (decoded_typeface) {
success_callback_.Run(decoded_typeface);
} else {
error_callback_.Run(error_string);
}
}
void TypefaceDecoder::ReleaseRawData() { raw_data_.reset(); }
bool TypefaceDecoder::Suspend() {
DCHECK(!suspended_);
suspended_ = true;
is_raw_data_too_large_ = false;
resource_provider_ = NULL;
ReleaseRawData();
return true;
}
void TypefaceDecoder::Resume(render_tree::ResourceProvider* resource_provider) {
if (!suspended_) {
DCHECK_EQ(resource_provider_, resource_provider);
return;
}
suspended_ = false;
resource_provider_ = resource_provider;
}
} // namespace font
} // namespace loader
} // namespace cobalt