NinePatchChunk.java分析
最近在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分析的更多相关文章
- java分析源码-ReentrantLock
一.前言 在分析了 AbstractQueuedSynchronier 源码后,接着分析ReentrantLock源码,其实在 AbstractQueuedSynchronizer 的分析中,已经提到 ...
- JAVA分析html算法(JAVA网页蜘蛛算法)
近来有些朋友在做蜘蛛算法,或者在网页上面做深度的数据挖掘.但是遇到复杂而繁琐的html页面大家都望而却步.因为很难获取到相应的数据. 最古老的办法的是尝试用正则表达式,估计那么繁琐的东西得不偿失,浪费 ...
- Java 分析工具汇总
http://blog.csdn.net/fenglibing/article/details/6411999 jps jps -mlvV jmap jmap -heap <pid> ...
- hello.java分析
如下图源码所示: 该段代码声明了一个entity实体类,该类有一个变量name,对该变量写了对应的get和set方法.类中还有一个空的构造方法hello(). @RequestScoped用于指定一个 ...
- Week4——Hello.java分析
如下图源码所示: 该段代码声明了一个entity实体类,该类有一个变量name,对该变量写了对应的get和set方法.类中还有一个空的构造方法hello(). @RequestScoped用于指定一个 ...
- 启动入口Start.java分析
框架的启动器在包:org.ofbiz.base.start 入口为:Start.java的main方法 Start.java启动器内容: 步骤 详情 入参校验 help/status/shutdown ...
- Intent.java分析
代码位于frameworks/base/core/java/anroid/Content/Intent.java Intent是对要进行操作的一种抽象描述.用action抽象操作,用data(andr ...
- java分析工具arthas
wget https://alibaba.github.io/arthas/arthas-boot.jar java -jar arthas-boot.jar --target-ip 0.0.0.0
- java 分析方法调用过程
StackTraceElement[] s = new Exception().getStackTrace(); for(int i=0;i<s.length;i++) System.out.p ...
随机推荐
- 诊断:ORA-00376 & ORA-01110
现象: Errors in file /path/of/diag/rdbms/prod/PROD/trace/PROD_ora_13447.trc: ORA-00376: 此时无法读取文件 61 OR ...
- 51nod 1021 石子归并 - 区间dp(经典)
题目地址:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1021 经典区间dp,dp[i][j] 表示将从 i 到 j 堆 ...
- 81-Gator Oscillator,加多摆动指标.(2015.7.1)
Gator Oscillator 加多摆动指标 Oscillator,加多摆动指标.(2015.7.1)" title="81-Gator Oscillator,加多摆动指标.(2 ...
- ICE CAVE(BFS搜索(模拟))
Description You play a computer game. Your character stands on some level of a multilevel ice cave. ...
- Vue如何mock数据模拟Ajax请求
我们在做一个项目时前期可能没有后端提供接口模拟数据,那么作为前端就需要自己写json文件模拟数据加载.网上往往参考的都是不全面的,比如get请求没问题但是post请求就报错了.在Vue中只需要vue- ...
- 立方体 反射 CubeMap
立方体反射(CubeMap) 在虚拟环境中,我们需要模拟材质球反射周围的环境,立方体反射正是让材质球反射出天空盒的背景的方法之一. 原理 当我们观察物体时,物体表面足够光滑,再视线方向和物体相交的点上 ...
- 添物不花钱学JavaEE(基础篇)- Java
Java Java是一面向对象语言 Write Once Run Anywhere Designed for easy Web/Internet applications, Mobile Widesp ...
- HDU-3790最短路径问题,第十遍终于过了~
最短路径问题 Time Limit: 2000/1000 MS (J ...
- 【莫比乌斯反演+树状数组+分块求和】GCD Array
https://www.bnuoj.com/v3/contest_show.php?cid=9149#problem/I [题意] 给定长度为l的一个数组,初始值为0:规定了两种操作: [思路] 找到 ...
- httpClient使用总结
前记 最近有个需求,需要根据商品id获取商品详情: 首先想到的是在浏览器里输入url按回车就可以了:或者在linux中使用curl+url来发起一个http请求; 但如果是要在java程序中发出htt ...