// Cannot use std::make_unique to access non-public ctor. auto result = std::unique_ptr<GRSurface>(new GRSurface(width, height, row_bytes, pixel_bytes));
size_t data_size = row_bytes * height;
result->data_size_ =
(data_size + kSurfaceDataAlignment - 1) / kSurfaceDataAlignment * kSurfaceDataAlignment;
result->data_.reset( static_cast<uint8_t*>(aligned_alloc(kSurfaceDataAlignment, result->data_size_))); if (!result->data_) return nullptr; return result;
}
std::unique_ptr<GRSurface> GRSurface::Clone() const { auto result = GRSurface::Create(width, height, row_bytes, pixel_bytes); if (!result) return nullptr;
memcpy(result->data(), data(), data_size_); return result;
}
PngHandler::PngHandler(const std::string& name) {
std::string res_path = g_resource_dir + "/" + name + ".png";
png_fp_.reset(fopen(res_path.c_str(), "rbe")); // Try to read from |name| if the resource path does not work. if (!png_fp_) {
png_fp_.reset(fopen(name.c_str(), "rbe"));
} if (!png_fp_) {
error_code_ = -1; return;
}
if (bit_depth_ == 8 && channels_ == 3 && color_type_ == PNG_COLOR_TYPE_RGB) { // 8-bit RGB images: great, nothing to do.
} elseif (bit_depth_ <= 8 && channels_ == 1 && color_type_ == PNG_COLOR_TYPE_GRAY) { // 1-, 2-, 4-, or 8-bit gray images: expand to 8-bit gray.
png_set_expand_gray_1_2_4_to_8(png_ptr_);
} elseif (bit_depth_ <= 8 && channels_ == 1 && color_type_ == PNG_COLOR_TYPE_PALETTE) { // paletted images: expand to 8-bit RGB. Note that we DON'T // currently expand the tRNS chunk (if any) to an alpha // channel, because minui doesn't support alpha channels in // general.
png_set_palette_to_rgb(png_ptr_);
channels_ = 3;
} else {
fprintf(stderr, "minui doesn't support PNG depth %d channels %d color_type %d\n", bit_depth_,
channels_, color_type_);
error_code_ = -7;
}
}
PngHandler::~PngHandler() { if (png_ptr_) {
png_destroy_read_struct(&png_ptr_, &info_ptr_, nullptr);
}
}
// "display" surfaces are transformed into the framebuffer's required pixel format (currently only // RGBX is supported) at load time, so gr_blit() can be nothing more than a memcpy() for each row.
// Copies 'input_row' to 'output_row', transforming it to the framebuffer pixel format. The input // format depends on the value of 'channels': // // 1 - input is 8-bit grayscale // 3 - input is 24-bit RGB // 4 - input is 32-bit RGBA/RGBX // // 'width' is the number of pixels in the row. staticvoid TransformRgbToDraw(const uint8_t* input_row, uint8_t* output_row, int channels, int width) { const uint8_t* ip = input_row;
uint8_t* op = output_row;
PixelFormat pixel_format = gr_pixel_format();
// This function tests if a locale string stored in PNG (prefix) matches // the locale string provided by the system (locale). bool matches_locale(const std::string& prefix, const std::string& locale) { // According to the BCP 47 format, A locale string may consists of: // language-{extlang}-{script}-{region}-{variant} // The locale headers in PNG mostly consist of language-{region} except for sr-Latn, and some // android's system locale can have the format language-{script}-{region}.
// Return true if the whole string of prefix matches the top part of locale. Otherwise try to // match the locale string without the {script} section. // For instance, prefix == "en" matches locale == "en-US", prefix == "sr-Latn" matches locale // == "sr-Latn-BA", and prefix == "zh-CN" matches locale == "zh-Hans-CN". if (prefix.empty()) { returnfalse;
}
if (android::base::StartsWith(locale, prefix)) { returntrue;
}
std::vector<std::string> get_locales_in_png(const std::string& png_name) {
PngHandler png_handler(png_name); if (!png_handler) {
printf("Failed to open %s, error: %d\n", png_name.c_str(), png_handler.error_code()); return {};
} if (png_handler.channels() != 1) {
printf("Expect input png to have 1 data channel, this file has %d\n", png_handler.channels()); return {};
}
std::vector<std::string> result;
std::vector<uint8_t> row(png_handler.width()); for (png_uint_32 y = 0; y < png_handler.height(); ++y) {
png_read_row(png_handler.png_ptr(), row.data(), nullptr); int h = (row[3] << 8) | row[2];
std::string loc(reinterpret_cast<char*>(&row[5])); if (!loc.empty()) {
result.push_back(loc);
} for (int i = 0; i < h; ++i, ++y) {
png_read_row(png_handler.png_ptr(), row.data(), nullptr);
}
}
return result;
}
int res_create_localized_alpha_surface(constchar* name, constchar* locale,
GRSurface** pSurface) {
*pSurface = nullptr; if (locale == nullptr) { return0;
}
PngHandler png_handler(name); if (!png_handler) return png_handler.error_code();
for (png_uint_32 y = 0; y < height; ++y) {
std::vector<uint8_t> row(width);
png_read_row(png_ptr, row.data(), nullptr); int w = (row[1] << 8) | row[0]; int h = (row[3] << 8) | row[2];
__unused int len = row[4]; char* loc = reinterpret_cast<char*>(&row[5]);
// We need to include one additional line for the metadata of the localized image. if (y + 1 + h > height) {
printf("Read exceeds the image boundary, y %u, h %d, height %u\n", y, h, height); return -8;
}
if (matches_locale(loc, locale)) {
printf(" %20s: %s (%d x %d @ %d)\n", name, loc, w, h, y);
auto surface = GRSurface::Create(w, h, w, 1); if (!surface) { return -9;
}
for (int i = 0; i < h; ++i, ++y) {
png_read_row(png_ptr, row.data(), nullptr);
memcpy(surface->data() + i * w, row.data(), w);
}
*pSurface = surface.release(); return0;
}
for (int i = 0; i < h; ++i, ++y) {
png_read_row(png_ptr, row.data(), nullptr);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.