最近在Swing中使用.9图片,用到了NinePatchChunk.java文件,但是发现有时会出现无法完美展示的情况,决定修复一下这个问题,顺便研究一些.9的绘制过程

通过分析发现draw函数先是计算出固定宽高大小,再计算出拉升区域大小,最后遍历固定大小和拉伸大小的矩形,进行拉升的覆盖。

在分析的时候发现,我所遇到的bug是通过计算固定高得到拉伸高度时,如果有一边被填满就无法计算准确这个值引起的。

这里:

        int remainderHorizontal = 0;
int remainderVertical = 0; if (mFixed.size() > 0) {
int start = mFixed.get(0).y;
for (Rectangle rect : mFixed) {
if (rect.y > start) {
endRow = true;
measuredWidth = true;
}
if (!measuredWidth) {
remainderHorizontal += rect.width;
}
if (endRow) {
remainderVertical += rect.height;
endRow = false;
start = rect.y;
}
}
} data.mRemainderHorizontal = scaledWidth - remainderHorizontal;
data.mRemainderVertical = scaledHeight - remainderVertical;

解决方法之一就是不使用填满边的.9图。当然也可以修改代码来解决。

绘制的代码:

    private void draw(BufferedImage image, Graphics2D graphics2D, int x, int y, int scaledWidth,
int scaledHeight) {
if (scaledWidth <= 1 || scaledHeight <= 1) {
return;
} Graphics2D g = (Graphics2D)graphics2D.create();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR); try {
if (mPatches.size() == 0) {
g.drawImage(image, x, y, scaledWidth, scaledHeight, null);
return;
} g.translate(x, y);
x = y = 0; DrawingData data = computePatches(scaledWidth, scaledHeight); int fixedIndex = 0;
int horizontalIndex = 0;
int verticalIndex = 0;
int patchIndex = 0; boolean hStretch;
boolean vStretch; float vWeightSum = 1.0f;
float vRemainder = data.mRemainderVertical; vStretch = mVerticalStartWithPatch;
while (y < scaledHeight - 1) {
hStretch = mHorizontalStartWithPatch; int height = 0;
float vExtra = 0.0f; float hWeightSum = 1.0f;
float hRemainder = data.mRemainderHorizontal; while (x < scaledWidth - 1) {
Rectangle r;
if (!vStretch) {
if (hStretch) {
r = mHorizontalPatches.get(horizontalIndex++);
float extra = r.width / data.mHorizontalPatchesSum;
int width = (int) (extra * hRemainder / hWeightSum);
hWeightSum -= extra;
hRemainder -= width;
g.drawImage(image, x, y, x + width, y + r.height, r.x, r.y,
r.x + r.width, r.y + r.height, null);
x += width;
} else {
r = mFixed.get(fixedIndex++);
g.drawImage(image, x, y, x + r.width, y + r.height, r.x, r.y,
r.x + r.width, r.y + r.height, null);
x += r.width;
}
height = r.height;
} else {
if (hStretch) {
r = mPatches.get(patchIndex++);
vExtra = r.height / data.mVerticalPatchesSum;
height = (int) (vExtra * vRemainder / vWeightSum);
float extra = r.width / data.mHorizontalPatchesSum;
int width = (int) (extra * hRemainder / hWeightSum);
hWeightSum -= extra;
hRemainder -= width;
g.drawImage(image, x, y, x + width, y + height, r.x, r.y,
r.x + r.width, r.y + r.height, null);
x += width;
} else {
r = mVerticalPatches.get(verticalIndex++);
vExtra = r.height / data.mVerticalPatchesSum;
height = (int) (vExtra * vRemainder / vWeightSum);
g.drawImage(image, x, y, x + r.width, y + height, r.x, r.y,
r.x + r.width, r.y + r.height, null);
x += r.width;
} }
hStretch = !hStretch;
}
x = 0;
y += height;
if (vStretch) {
vWeightSum -= vExtra;
vRemainder -= height;
}
vStretch = !vStretch;
} } finally {
g.dispose();
}
}

计算patch长度和固定长度的remainder的代码

    private DrawingData computePatches(int scaledWidth, int scaledHeight) {
DrawingData data = new DrawingData();
boolean measuredWidth = false;
boolean endRow = true; int remainderHorizontal = 0;
int remainderVertical = 0; if (mFixed.size() > 0) {
int start = mFixed.get(0).y;
for (Rectangle rect : mFixed) {
if (rect.y > start) {
endRow = true;
measuredWidth = true;
}
if (!measuredWidth) {
remainderHorizontal += rect.width;
}
if (endRow) {
remainderVertical += rect.height;
endRow = false;
start = rect.y;
}
}
} data.mRemainderHorizontal = scaledWidth - remainderHorizontal;
data.mRemainderVertical = scaledHeight - remainderVertical; data.mHorizontalPatchesSum = 0;
if (mHorizontalPatches.size() > 0) {
int start = -1;
for (Rectangle rect : mHorizontalPatches) {
if (rect.x > start) {
data.mHorizontalPatchesSum += rect.width;
start = rect.x;
}
}
} else {
int start = -1;
for (Rectangle rect : mPatches) {
if (rect.x > start) {
data.mHorizontalPatchesSum += rect.width;
start = rect.x;
}
}
} data.mVerticalPatchesSum = 0;
if (mVerticalPatches.size() > 0) {
int start = -1;
for (Rectangle rect : mVerticalPatches) {
if (rect.y > start) {
data.mVerticalPatchesSum += rect.height;
start = rect.y;
}
}
} else {
int start = -1;
for (Rectangle rect : mPatches) {
if (rect.y > start) {
data.mVerticalPatchesSum += rect.height;
start = rect.y;
}
}
} return data;
}

NinePatchChunk.java分析的更多相关文章

  1. java分析源码-ReentrantLock

    一.前言 在分析了 AbstractQueuedSynchronier 源码后,接着分析ReentrantLock源码,其实在 AbstractQueuedSynchronizer 的分析中,已经提到 ...

  2. JAVA分析html算法(JAVA网页蜘蛛算法)

    近来有些朋友在做蜘蛛算法,或者在网页上面做深度的数据挖掘.但是遇到复杂而繁琐的html页面大家都望而却步.因为很难获取到相应的数据. 最古老的办法的是尝试用正则表达式,估计那么繁琐的东西得不偿失,浪费 ...

  3. Java 分析工具汇总

    http://blog.csdn.net/fenglibing/article/details/6411999 jps  jps -mlvV jmap jmap -heap <pid>   ...

  4. hello.java分析

    如下图源码所示: 该段代码声明了一个entity实体类,该类有一个变量name,对该变量写了对应的get和set方法.类中还有一个空的构造方法hello(). @RequestScoped用于指定一个 ...

  5. Week4——Hello.java分析

    如下图源码所示: 该段代码声明了一个entity实体类,该类有一个变量name,对该变量写了对应的get和set方法.类中还有一个空的构造方法hello(). @RequestScoped用于指定一个 ...

  6. 启动入口Start.java分析

    框架的启动器在包:org.ofbiz.base.start 入口为:Start.java的main方法 Start.java启动器内容: 步骤 详情 入参校验 help/status/shutdown ...

  7. Intent.java分析

    代码位于frameworks/base/core/java/anroid/Content/Intent.java Intent是对要进行操作的一种抽象描述.用action抽象操作,用data(andr ...

  8. java分析工具arthas

    wget https://alibaba.github.io/arthas/arthas-boot.jar java -jar arthas-boot.jar --target-ip 0.0.0.0

  9. java 分析方法调用过程

    StackTraceElement[] s = new Exception().getStackTrace(); for(int i=0;i<s.length;i++) System.out.p ...

随机推荐

  1. 全国绿色计算大赛 模拟赛第一阶段(Python)

    第1关求和 class Task: def getSum(self, num1, num2): sum = 0 for i in range(num1, num2 + 1): while (i != ...

  2. PHP—通过HTML网页请求,PHP页面显示源码不能解析

    对于初学者来说,可能会碰到这样一个问题,那就是我们通过html网页,在表单的action中填入后台处理的php文件后,虽然可以跳转到php网页上,但是却显示一大堆php源码而不是处理请求.像这样:   ...

  3. db2事务日志已满解决办法

    查看事务日志配置(MICRO_11为数据库名称): db2 get db cfg for MICRO_11 运行结果: 日志文件大小(4KB)                         (LOG ...

  4. FreeRTOS--疑难杂症

    花了3个晚上,把这个章节看完,受益匪浅. 最有用的应该是与中断相关的错误,优先排查中断优先级设置. 堆栈溢出检查,可能用到,一般先把堆栈设置的足够大,只要没有溢出就是好事,溢出了,掌握了栈溢出钩子函数 ...

  5. NOR flash and NAND flash

    (1)读写的基本单位 应用程序对NOR芯片操作以"字"为基本单位.为了方便对大容量NOR闪存的管理,通常将NOR闪存分成大小为128KB或者64KB的逻辑块,有时候块内还分成扇区. ...

  6. jquery给span赋值

    span是最简单的容器,可以当作一个形式标签,其取值赋值方法有别于一般的页面元素. //赋值 $("#spanid").html(value) //取值 $("#span ...

  7. JavaEE JDBC 了解JNDI

    了解JNDI @author ixenos Web与企业应用中的连接管理 1. 数据库连接方式: (1)使用配置文件 (2)使用JNDI 2. 在Web或企业环境中部署 JDBC应用时,数据库连接管理 ...

  8. bzoj1007 [HNOI2008]水平可见直线 - 几何 - hzwer.com

    Description Input 第一行为N(0 < N < 50000),接下来的N行输入Ai,Bi Output 从小到大输出可见直线的编号,两两中间用空格隔开,最后一个数字后面也必 ...

  9. CSU - 1333 1333: Funny Car Racing(spfa)

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1333 这题多了一个限制条件是每一条路都会规律的开放a时间关闭b时间,车子必须在开放的时候进入,在关 ...

  10. 1、Java并发性和多线程-并发性和多线程介绍

    以下内容转自http://ifeve.com/java-concurrency-thread/: 在过去单CPU时代,单任务在一个时间点只能执行单一程序.之后发展到多任务阶段,计算机能在同一时间点并行 ...