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 ...
随机推荐
- vuex如何管理需要即时更新的全局变量
自己在使用vue练习开发的时候遇到全局变量无法即时更新的问题,查了资料之后得出结论使用vuex能够快速解决该问题,但是看了好多人讲解vuex的教程自己跟着去做都没解决自己想要的,最后找到一个比较容易理 ...
- 样例GeoQuiz应用开发 第2章
先介绍一下MVC,Model View Controller,是软件架构中最常见的一种框架. 简单来说就是通过 controller 的控制去操作 model 层的数据,并且返回给 view 层展示, ...
- centos6 文件管理
一.文件属性 权限位: - 表示文件 d 表示目录 l 表示软连接 b 表示接口存储设备文件 c 表示串行端口设备 文件的时间属性 [root@web02 ~]# ll /etc/passwd ### ...
- Python中的数据类型之字符串
字符串的定义,可是使用类似下面的方式 name = "hello python" Python 中字符串自带了一些常用的方法,比如: title() #用来将每个单词首字母大写up ...
- 集训第六周 数学概念与方法 数论 线性方程 I题
Description The Sky is Sprite. The Birds is Fly in the Sky. The Wind is Wonderful. Blew Throw the Tr ...
- Python数据结构--链表
class Node(): def __init__(self, dataval=None): self.dataval = dataval self.nextval = None class SLi ...
- Numpy第一课
import numpy as np a = np.array([1,2,3]) print(a) # [1 2 3] a2 = np.array([[1, 2], [3, 4]]) print('a ...
- Leetcode 188.买卖股票的最佳时机IV
买卖股票的最佳时机IV 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你最多可以完成 k 笔交易. 注意: 你不能同时参与多笔交易(你必 ...
- Excel表格如何设置密码 Excel2003/2007/2010设置密码教程
http://www.wordlm.com/special/2/ 经常使用Excel表格制作报表和一些数据后,我们会给Excel表格设置密码,这样可以很有效的防止数据被盗取.目前Office版本众多, ...
- LOJ#541. 「LibreOJ NOIP Round #1」七曜圣贤
有一辆车一开始装了编号0-a的奶茶,现有m次操作,每次操作Pi在[-1,b),若Pi为一个未出现过编号的奶茶,就把他买了并装上车:若Pi为一个在车上的奶茶,则把他丢下车:否则,此次操作为捡起最早丢下去 ...