Android开机动画,framework修改Bootanimation绘制文字。

文章目录

  • Android开机动画,framework修改Bootanimation动画绘制文字。

Android开机动画,framework修改Bootanimation动画绘制文字。

frameworks/base/cmds/bootanimation/bootanimation.cpp

绘制时间的一个方法

在这里插入图片描述

// We render 12 or 24 hour time.
void BootAnimation::drawClock(const Font& font, const int xPos, const int yPos) {
    static constexpr char TIME_FORMAT_12[] = "%l:%M";
    static constexpr char TIME_FORMAT_24[] = "%H:%M";
    static constexpr int TIME_LENGTH = 6;
获取系统时间
    time_t rawtime;
    time(&rawtime);
    struct tm* timeInfo = localtime(&rawtime);

    char timeBuff[TIME_LENGTH];
    //显示时间的字符串
    const char* timeFormat = mTimeFormat12Hour ? TIME_FORMAT_12 : TIME_FORMAT_24;
    size_t length = strftime(timeBuff, TIME_LENGTH, timeFormat, timeInfo);

    if (length != TIME_LENGTH - 1) {
        SLOGE("Couldn't format time; abandoning boot animation clock");
        mClockEnabled = false;
        return;
    }
	
    char* out = timeBuff[0] == ' ' ? &timeBuff[1] : &timeBuff[0];
    int x = xPos;
    int y = yPos;
    //绘制文本
    drawText(out, font, false, &x, &y);
}

绘制文本

void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* x, int* y) {
    glEnable(GL_BLEND);  // Allow us to draw on top of the animation
    glBindTexture(GL_TEXTURE_2D, font.texture.name);

    const int len = strlen(str);
    const int strWidth = font.char_width * len;

    if (*x == TEXT_CENTER_VALUE) {
        *x = (mWidth - strWidth) / 2;
    } else if (*x < 0) {
        *x = mWidth + *x - strWidth;
    }
    if (*y == TEXT_CENTER_VALUE) {
        *y = (mHeight - font.char_height) / 2;
    } else if (*y < 0) {
        *y = mHeight + *y - font.char_height;
    }

    int cropRect[4] = { 0, 0, font.char_width, -font.char_height };

    for (int i = 0; i < len; i++) {
        char c = str[i];

        if (c < FONT_BEGIN_CHAR || c > FONT_END_CHAR) {
            c = '?';
        }

        // Crop the texture to only the pixels in the current glyph
        const int charPos = (c - FONT_BEGIN_CHAR);  // Position in the list of valid characters
        const int row = charPos / FONT_NUM_COLS;
        const int col = charPos % FONT_NUM_COLS;
        cropRect[0] = col * font.char_width;  // Left of column
        cropRect[1] = row * font.char_height * 2; // Top of row
        // Move down to bottom of regular (one char_heigh) or bold (two char_heigh) line
        cropRect[1] += bold ? 2 * font.char_height : font.char_height;
        glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);

        glDrawTexiOES(*x, *y, 0, font.char_width, font.char_height);

        *x += font.char_width;
    }

    glDisable(GL_BLEND);  // Return to the animation's default behaviour
    glBindTexture(GL_TEXTURE_2D, 0);
}

初始化字体

在这里插入图片描述

声明一个成员变量Font。

在这里插入图片描述

来到android()的initFont()

在这里插入图片描述

这是一个文件名字符串

static const char CLOCK_FONT_ASSET[] = "images/clock_font.png";

opengl只是支持图片纹理,所以文件是一张图片

然后会把这个图片加载进来,设置宽高等等。

在这里插入图片描述

绘制

在这里插入图片描述

对这个图片进行裁剪

在这里插入图片描述

我们新增代码在这里TEXT_CENTER_VALUE居中显示, yc + mAndroid[0].h计算绘制的y坐标系

yc是原本Android动画的一个坐标系,但是我们不能覆盖他,所以要比他高,放到原生Android动画的上边+ mAndroid[0].h

drawClock(mClockFont, TEXT_CENTER_VALUE, yc + mAndroid[0].h);

在这里插入图片描述

bool BootAnimation::android()
{
    SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
            elapsedRealtime());
    initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
    initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");

    mCallbacks->init({});

    // clear screen
    glShadeModel(GL_FLAT);
    //qfh add
    bool hasInitFont = false;
    if (initFont(&mClockFont, CLOCK_FONT_ASSET) == NO_ERROR) {
        hasInitFont = true;
        ALOGD("android init Font ok ,fontname = %u",mClockFont.texture.name);
    }
    //qfh add
    glDisable(GL_DITHER);
    glDisable(GL_SCISSOR_TEST);
    glClearColor(0,0,0,1);
    glClear(GL_COLOR_BUFFER_BIT);
    eglSwapBuffers(mDisplay, mSurface);

    glEnable(GL_TEXTURE_2D);
    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

    const GLint xc = (mWidth  - mAndroid[0].w) / 2;
    const GLint yc = (mHeight - mAndroid[0].h) / 2;
    // const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h);
    //qfh modify
    const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h*2);

    glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
            updateRect.height() * 2);
    //qfh modify
    // Blend state
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

    const nsecs_t startTime = systemTime();
    do {
        nsecs_t now = systemTime();
        double time = now - startTime;
        float t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w;
        GLint offset = (1 - (t - floorf(t))) * mAndroid[1].w;
        GLint x = xc - offset;

        glDisable(GL_SCISSOR_TEST);
        glClear(GL_COLOR_BUFFER_BIT);

        glEnable(GL_SCISSOR_TEST);
        glDisable(GL_BLEND);
        glBindTexture(GL_TEXTURE_2D, mAndroid[1].name);
        glDrawTexiOES(x,                 yc, 0, mAndroid[1].w, mAndroid[1].h);
        glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h);

        glEnable(GL_BLEND);
        glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);
        glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h);
        drawClock(mClockFont, TEXT_CENTER_VALUE, yc + mAndroid[0].h);
        EGLBoolean res = eglSwapBuffers(mDisplay, mSurface);
        if (res == EGL_FALSE)
            break;

        // 12fps: don't animate too fast to preserve CPU
        const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now);
        if (sleepTime > 0)
            usleep(sleepTime);

        checkExit();
    } while (!exitPending());

    glDeleteTextures(1, &mAndroid[0].name);
    glDeleteTextures(1, &mAndroid[1].name);
    //qfh add
        if (hasInitFont)
           glDeleteTextures(1, &mClockFont.texture.name);
    //qfh add
    return false;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/673901.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用Landsat的NDVI和NDWI阈值法土地分类

目录 分类效果源代码分类效果 创建一个包含多个层的影像合成:水体(NDWI > 0.5),植被(NDVI > 0.2),阴影区域的裸地(bare2但不包括bare1),和其他裸地(bare1)。然后,使用mosaic()方法合并这些层,并用clip(hh)方法裁剪到研究区域的范围。 源代码 var hh = ee.…

linux 内核映像差异介绍:vmlinux、zImage、zbImage、image、uImage等

一、背景 Linux内核是整个Linux操作系统的核心部分&#xff0c;它是一个负责与硬件直接交互的软件层&#xff0c;并且提供多种服务和接口&#xff0c;让用户程序能够方便地使用硬件资源。 当我们编译自定义内核时&#xff0c;可以将其生成为以下内核映像之一&#xff1a;vmli…

【Matplotlib作图-3.Ranking】50 Matplotlib Visualizations, Python实现,源码可复现

目录 03 Ranking 3.0 Prerequisite 3.1 有序条形图(Ordered Bar Chart) 3.2 棒棒糖图(Lollipop Chart) 3.3 点图(Dot Plot) 3.4 斜率图(Slope Chart) 3.5 杠铃图(Dumbbell Plot) References 03 Ranking 3.0 Prerequisite Setup.py # !pip install brewer2mpl import n…

短视频拍摄的几个必要手法!

如果说视频脚本是制作视频的基础&#xff0c;那么视频拍摄则是视频制作的关键。有了清晰稳定的视频素材&#xff0c;我们才能创作出清晰完整的视频画面。 那么如何拍摄出一个优质清晰稳定的视频画面呢&#xff1f;接下来带大家来学习下视频拍摄的五大技巧。 一、构图是关键 …

深度学习优化技巧

深度学习优化技巧 导语参数更新SGDMomentumAdaGradAdam方法比较 权重初始化关于置0隐藏层激活值分布ReLU权重初值权重比较 Batch Normalization处理过拟合权值衰减Dropout 超参数验证验证数据最优化和实现 总结参考文献 导语 在深度学习中&#xff0c;除了上一章所涉及到的反向…

Kubernetes Pod控制器

一.Pod控制器基本内容 1.定义 Pod控制器&#xff0c;又称之为工作负载&#xff08;workload&#xff09;&#xff0c;是用于实现管理pod的中间层&#xff0c;确保pod资源符合预期的状态&#xff0c;pod的资源出现故障时&#xff0c;会尝试进行重启&#xff0c;当根据重启策略…

光纤宽带和ADSL宽带(电话线上网时代)

一、ADSL宽带(电话线上网时代) ADSL技术是一种不对称数字用户线实现宽带接入互连网的技术&#xff0c;ADSL作为一种传输层的技术&#xff0c;充分利用现有的铜线资源&#xff0c;在一对双绞线上提供上行640kbps下行8Mbps的带宽&#xff0c;从而克服了传统用户在最后一公里的瓶颈…

鸿蒙卷起来了!什么是ArkTS?ArkUI?

最近消息出来了&#xff01;纯血鸿蒙即将在六月底发布&#xff0c;市场关于鸿蒙应用开发很火&#xff0c;一些公司企业对鸿蒙开发技术人员更是开出惊人的高薪资。 如果你想要学习鸿蒙应用开发&#xff0c;需要从鸿蒙相关的ArkTS语言开始进入。关于鸿蒙的ArkTS语言&#xff0c;我…

微服务:Rabbitmq的WorkQueue模型的使用、默认消费方式(消息队列中间件)

文章目录 WorkQueue模型控制预取消息个数 WorkQueue模型 当然&#xff0c;一个队列&#xff0c;可以由多个消费者去监听。 来实现一下. 生产者&#xff1a; Testpublic void testWorkQueue() throws InterruptedException {// 队列名称String queueName "simple.queue…

UUID 的用户体验

UUID 的用户体验 唯一标识符&#xff08;UUID&#xff09;在所有应用程序中都起着至关重要的作用&#xff0c;从用户认证到资源管理。虽然使用标准的 UUID 可以满足所有的安全需求&#xff0c;但我们可以为用户做很多改进。 基础知识&#xff1a;确保全局唯一性 唯一标识符对…

UR机器人通信汇总

文章目录 一、概述二、UR机器人通信2.1UR通信协议2.2 UR通信端口 三、UR机器人通信端口类型3.1 Modbus TCP端口&#xff08;502端口&#xff09;3.2 Dashboard端口&#xff08;29999端口&#xff09;3.3 上位机编程端口&#xff08;30001/30002/30003端口&#xff09;3.3.1 URS…

C基础-标准库上

下:http://t.csdnimg.cn/LXa0J C 标准库是一组 C 内置函数、常量和头文件&#xff0c;比如 <stdio.h>、<stdlib.h>、<math.h>&#xff0c;等等。 目录 一. assert.h 二. ctype.h 三. errno.h 四. float.h 五.limits.h 六. locale.h 一. assert.h 源码…

Go语言垃圾回收(GC原理)

1. GC回收机制 1.1 V1.3标记清除法 (1)概述 1.STW暂停 STW(暂停业务逻辑,找出可达和不可达对象) 2.对可达对象做上标记 标记完成之后,对象5和对象6不可达,被GC清除.之后STW结束. (2).缺点 STW :让程序暂停,程序出现卡顿.标记需要扫描整个heap.清除数据会产生heap碎片. 1.…

【linux软件基础知识】与调度相关的进程描述符

进程描述符 每个进程描述符都包括几个与调度相关的字段,如下代码所示: struct thread_struct {unsigned long rsp0;unsigned long rsp;unsigned long userrsp; /* Copy from PDA */ unsigned long fs;unsigned

SprigBoot中的配置优先级 Bean管理

黑马程序员JavaWeb开发教程 文章目录 一、配置优先级1.1 SpringBoot 中支持三种格式的配置文件1.2 Java系统属性 & 命令行参数1.3 总结 二、Bean管理2.1 获取bean2.1.1 在默认情况下 2.2 bean 作用域&#xff08;实际开发中一般不需要考虑&#xff09;2.2.1 bean的作用域2.…

XML 相关漏洞风险研究

前言 经常看到有关 XXE 的漏洞分析&#xff0c;大概知道原理&#xff0c;但是对 XML 中相关的定义却一知半解。XEE 全称为 XML External Entity 即 XML 外部实体&#xff0c;但除了常见的 EXP 还有哪些触发方法&#xff1f;XML 相关的漏洞除了 XXE 还有什么其他攻击面&#xf…

已办理劳务资质,为何无法在全国建筑市场网查询到企业?

已办理劳务资质的企业无法在全国建筑市场网&#xff08;四库一平台&#xff09;查询到&#xff0c;可能的原因如下&#xff1a; 数据更新延迟&#xff1a; 全国建筑市场监管公共服务平台&#xff08;四库一平台&#xff09;的数据更新可能存在延迟。新获得的劳务资质信息在平台…

系统架构设计师【第14章】: 云原生架构设计理论与实践 (核心总结)

文章目录 14.1 云原生架构产生背景14.2 云原生架构内涵14.2.1 云原生架构定义14.2.2 云原生架构原则14.2.3 主要架构模式14.2.4 典型的云原生架构反模式 14.3 云原生架构相关技术14.3.1 容器技术14.3.2 云原生微服务14.3.3 无服务器技术14.3.4 服务网格 14.4 云原生…

Arthas使用教程——JVM常用命令

JVM相关命令 dashboard——当前系统的实时数据面板 显示当前 tomcat 的实时信息。 使用方式&#xff1a;dashboard 数据说明 ID: Java 级别的线程 ID&#xff0c;注意这个 ID 不能跟 jstack 中的 nativeID 一一对应。 NAME: 线程名 GROUP: 线程组名 PRIORITY: 线程优先级…

网站入门:Flask用法讲解

Flask是一个使用Python编写的轻量级Web服务框架&#xff0c;旨在帮助开发人员快速构建和部署Web应用程序。下面将对Flask进行更为详细的解释说明&#xff0c;并展示其使用示例与注意事项&#xff1a; 1.解释说明 定义及特点: Flask以其简洁和灵活著称&#xff0c;允许开发者以…