Android4.2.2 Gallery2源码分析(5)——GLCanvasImpl.java

GLCanvasImpl.java是接口GLCanvas的唯一实现类,也就是说二者在功能上完全等同。代码中调用GLCanvas对象函数的地方,等效于调用GLCanvasImpl中的该函数,GLCanvasImpl对该函数有具体的实现。

1.构造函数

  1. GLCanvasImpl(GL11 gl) {  
  2.     mGL = gl;  
  3.     mGLState = new GLState(gl);  
  4.     initialize();  
  5. }  
    GLCanvasImpl(GL11 gl) {
        mGL = gl;
        mGLState = new GLState(gl);
        initialize();
    }

1.1.new GLState(gl)

  1. public GLState(GL11 gl) {  
  2.     mGL = gl;  
  3.   
  4.     // Disable unused state   
  5.     gl.glDisable(GL11.GL_LIGHTING);  
  6.   
  7.     // Enable used features   
  8.     gl.glEnable(GL11.GL_DITHER);  
  9.     gl.glEnable(GL11.GL_SCISSOR_TEST);  
  10.   
  11.     gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);  
  12.     gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);  
  13.     gl.glEnable(GL11.GL_TEXTURE_2D);  
  14.   
  15.     gl.glTexEnvf(GL11.GL_TEXTURE_ENV,  
  16.             GL11.GL_TEXTURE_ENV_MODE, GL11.GL_REPLACE);  
  17.   
  18.     // Set the background color   
  19.     /// M: Disable transparent   
  20.     //gl.glClearColor(0f, 0f, 0f, 0f);   
  21.     gl.glClearColor(0f, 0f, 0f, 1f);  
  22.     gl.glClearStencil(0);  
  23.   
  24.     gl.glEnable(GL11.GL_BLEND);  
  25.     gl.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);  
  26.   
  27.     // We use 565 or 8888 format, so set the alignment to 2 bytes/pixel.   
  28.     gl.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 2);  
  29. }  
        public GLState(GL11 gl) {
            mGL = gl;

            // Disable unused state
            gl.glDisable(GL11.GL_LIGHTING);

            // Enable used features
            gl.glEnable(GL11.GL_DITHER);
            gl.glEnable(GL11.GL_SCISSOR_TEST);

            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
            gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            gl.glEnable(GL11.GL_TEXTURE_2D);

            gl.glTexEnvf(GL11.GL_TEXTURE_ENV,
                    GL11.GL_TEXTURE_ENV_MODE, GL11.GL_REPLACE);

            // Set the background color
            /// M: Disable transparent
            //gl.glClearColor(0f, 0f, 0f, 0f);
            gl.glClearColor(0f, 0f, 0f, 1f);
            gl.glClearStencil(0);

            gl.glEnable(GL11.GL_BLEND);
            gl.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);

            // We use 565 or 8888 format, so set the alignment to 2 bytes/pixel.
            gl.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 2);
        }

了解OpenGL的用法,知道上面这部分内容只是做了一些绘图时的属性设置,就像我们利用Canvas绘制2D图形时对画笔的设置一样。

1.2.initialize()

  1. private void initialize() {  
  2.     GL11 gl = mGL;  
  3.   
  4.     // First create an nio buffer, then create a VBO from it.   
  5.     int size = BOX_COORDINATES.length * Float.SIZE / Byte.SIZE;  
  6.     FloatBuffer xyBuffer = allocateDirectNativeOrderBuffer(size).asFloatBuffer();  
  7.     xyBuffer.put(BOX_COORDINATES, 0, BOX_COORDINATES.length).position(0);//Opengl中的常见做法,通常把顶点坐标等数据储存在FloatBuffer,ShortBuffer等Buffer中。   
  8.   
  9.     int[] name = new int[1];  
  10.     GLId.glGenBuffers(1, name, 0);//申请一个int缓冲区   
  11.     mBoxCoords = name[0];  
  12.   
  13.     gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, mBoxCoords);//绑定该缓冲区   
  14.     gl.glBufferData(GL11.GL_ARRAY_BUFFER,  
  15.             xyBuffer.capacity() * (Float.SIZE / Byte.SIZE),//分配数据初始化该缓冲区   
  16.             xyBuffer, GL11.GL_STATIC_DRAW);  
  17.   
  18.     gl.glVertexPointer(2, GL11.GL_FLOAT, 00);  
  19.     gl.glTexCoordPointer(2, GL11.GL_FLOAT, 00);  
  20.   
  21.     // Enable the texture coordinate array for Texture 1   
  22.     gl.glClientActiveTexture(GL11.GL_TEXTURE1);  
  23.     gl.glTexCoordPointer(2, GL11.GL_FLOAT, 00);  
  24.     gl.glClientActiveTexture(GL11.GL_TEXTURE0);  
  25.     gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);  
  26.   
  27.     // mMatrixValues and mAlpha will be initialized in setSize()   
  28. }  
    private void initialize() {
        GL11 gl = mGL;

        // First create an nio buffer, then create a VBO from it.
        int size = BOX_COORDINATES.length * Float.SIZE / Byte.SIZE;
        FloatBuffer xyBuffer = allocateDirectNativeOrderBuffer(size).asFloatBuffer();
        xyBuffer.put(BOX_COORDINATES, 0, BOX_COORDINATES.length).position(0);//Opengl中的常见做法,通常把顶点坐标等数据储存在FloatBuffer,ShortBuffer等Buffer中。

        int[] name = new int[1];
        GLId.glGenBuffers(1, name, 0);//申请一个int缓冲区
        mBoxCoords = name[0];

        gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, mBoxCoords);//绑定该缓冲区
        gl.glBufferData(GL11.GL_ARRAY_BUFFER,
                xyBuffer.capacity() * (Float.SIZE / Byte.SIZE),//分配数据初始化该缓冲区
                xyBuffer, GL11.GL_STATIC_DRAW);

        gl.glVertexPointer(2, GL11.GL_FLOAT, 0, 0);
        gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);

        // Enable the texture coordinate array for Texture 1
        gl.glClientActiveTexture(GL11.GL_TEXTURE1);
        gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);
        gl.glClientActiveTexture(GL11.GL_TEXTURE0);
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        // mMatrixValues and mAlpha will be initialized in setSize()
    }

这段代码的作用是为顶点坐标BOC_COORDINATES分配了一块缓冲区。

该坐标定义如下:

  1. private static final float[] BOX_COORDINATES = {  
  2.         00100111,  // used for filling a rectangle   
  3.         0011,              // used for drawing a line   
  4.         00011110}; // used for drawing the outline of a rectangle  
    private static final float[] BOX_COORDINATES = {
            0, 0, 1, 0, 0, 1, 1, 1,  // used for filling a rectangle
            0, 0, 1, 1,              // used for drawing a line
            0, 0, 0, 1, 1, 1, 1, 0}; // used for drawing the outline of a rectangle

接下来我们看下在GLCanvas中看到的几个重要函数的实现:

2.drawRect()

  1. public void drawRect(float x, float y, float width, float height, GLPaint paint) {  
  2.     GL11 gl = mGL;  
  3.   
  4.     mGLState.setColorMode(paint.getColor(), mAlpha);  
  5.     mGLState.setLineWidth(paint.getLineWidth());  
  6.   
  7.     saveTransform();  
  8.     translate(x, y);  
  9.     scale(width, height, 1);  
  10.   
  11.     gl.glLoadMatrixf(mMatrixValues, 0);  
  12.     gl.glDrawArrays(GL11.GL_LINE_LOOP, OFFSET_DRAW_RECT, 4);  
  13.   
  14.     restoreTransform();  
  15.     mCountDrawLine++;  
  16. }  
    public void drawRect(float x, float y, float width, float height, GLPaint paint) {
        GL11 gl = mGL;

        mGLState.setColorMode(paint.getColor(), mAlpha);
        mGLState.setLineWidth(paint.getLineWidth());

        saveTransform();
        translate(x, y);
        scale(width, height, 1);

        gl.glLoadMatrixf(mMatrixValues, 0);
        gl.glDrawArrays(GL11.GL_LINE_LOOP, OFFSET_DRAW_RECT, 4);

        restoreTransform();
        mCountDrawLine++;
    }

这里重要的是glDrawArrays这一调用,这是一个真正的绘图函数,参数意义如下:

GL_LINE_LOOP:从第一个顶点到最后一个顶点依次相连,并且第一个顶点和最后一个顶点相连.

OFFSET_DRAW_RECT:从数组缓存中的这一位开始绘制,代码中值为6

4:数组中顶点的数目。

3.drawTexture()

  1. public void drawTexture(BasicTexture texture, float[] mTextureTransform,  
  2.         int x, int y, int w, int h) {  
  3.     mGLState.setBlendEnabled(mBlendEnabled  
  4.             && (!texture.isOpaque() || mAlpha < OPAQUE_ALPHA));  
  5.     if (!bindTexture(texture)) return;  
  6.     setTextureCoords(mTextureTransform);  
  7.     mGLState.setTextureAlpha(mAlpha);  
  8.     textureRect(x, y, w, h);  
  9. }  
    public void drawTexture(BasicTexture texture, float[] mTextureTransform,
            int x, int y, int w, int h) {
        mGLState.setBlendEnabled(mBlendEnabled
                && (!texture.isOpaque() || mAlpha < OPAQUE_ALPHA));
        if (!bindTexture(texture)) return;
        setTextureCoords(mTextureTransform);
        mGLState.setTextureAlpha(mAlpha);
        textureRect(x, y, w, h);
    }

drawTexture()还有另外一个public的复写函数,具体使用到的时候再具体分析,二者中都有比较重要的是textureRect()这个调用:

3.1textureRect()

  1. private void textureRect(float x, float y, float width, float height) {  
  2.     GL11 gl = mGL;  
  3.   
  4.     saveTransform();  
  5.     translate(x, y);  
  6.     scale(width, height, 1);  
  7.   
  8.     gl.glLoadMatrixf(mMatrixValues, 0);  
  9.     gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, OFFSET_FILL_RECT, 4);  
  10.   
  11.     restoreTransform();  
  12.     mCountTextureRect++;  
  13. }  
    private void textureRect(float x, float y, float width, float height) {
        GL11 gl = mGL;

        saveTransform();
        translate(x, y);
        scale(width, height, 1);

        gl.glLoadMatrixf(mMatrixValues, 0);
        gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, OFFSET_FILL_RECT, 4);

        restoreTransform();
        mCountTextureRect++;
    }

这里也有了真正的绘图函数,glDrawArrays。我们分析下它的绘制:

GL_TRIANGLE_STRIP:这个参数解释起来有点复杂,需要设计到OpenGL的绘制单元。可以百度了解。

OFFSET_FILL_RECT:值为0


综上所述,GLCanvas和GLCanvasImpl是实现视图画图布局的地方。至于具体画成什么样则需要查看具体调用的地方传进来的参数的样子。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值