Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/gl/DecomposeIntoNoRepeatTriangles.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "DecomposeIntoNoRepeatTriangles.h"
8
#include "gfxMatrix.h"
9
10
namespace mozilla {
11
namespace gl {
12
13
void
14
RectTriangles::AppendRectToCoordArray(InfallibleTArray<coord>& array,
15
                                      GLfloat x0, GLfloat y0,
16
                                      GLfloat x1, GLfloat y1)
17
0
{
18
0
    coord* v = array.AppendElements(6);
19
0
20
0
    v[0].x = x0; v[0].y = y0;
21
0
    v[1].x = x1; v[1].y = y0;
22
0
    v[2].x = x0; v[2].y = y1;
23
0
    v[3].x = x0; v[3].y = y1;
24
0
    v[4].x = x1; v[4].y = y0;
25
0
    v[5].x = x1; v[5].y = y1;
26
0
}
27
28
void
29
RectTriangles::addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
30
                       GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1,
31
                       bool flip_y /* = false */)
32
0
{
33
0
    if (flip_y) {
34
0
        std::swap(ty0, ty1);
35
0
    }
36
0
    AppendRectToCoordArray(mVertexCoords, x0, y0, x1, y1);
37
0
    AppendRectToCoordArray(mTexCoords, tx0, ty0, tx1, ty1);
38
0
}
39
40
static GLfloat
41
WrapTexCoord(GLfloat v)
42
0
{
43
0
    // This should return values in range [0, 1.0)
44
0
    return v - floorf(v);
45
0
}
46
47
void
48
DecomposeIntoNoRepeatTriangles(const gfx::IntRect& aTexCoordRect,
49
                               const gfx::IntSize& aTexSize,
50
                               RectTriangles& aRects,
51
                               bool aFlipY /* = false */)
52
0
{
53
0
    // normalize this
54
0
    gfx::IntRect tcr(aTexCoordRect);
55
0
    while (tcr.X() >= aTexSize.width)
56
0
        tcr.MoveByX(-aTexSize.width);
57
0
    while (tcr.Y() >= aTexSize.height)
58
0
        tcr.MoveByY(-aTexSize.height);
59
0
60
0
    // Compute top left and bottom right tex coordinates
61
0
    GLfloat tl[2] =
62
0
        { GLfloat(tcr.X()) / GLfloat(aTexSize.width),
63
0
          GLfloat(tcr.Y()) / GLfloat(aTexSize.height) };
64
0
    GLfloat br[2] =
65
0
        { GLfloat(tcr.XMost()) / GLfloat(aTexSize.width),
66
0
          GLfloat(tcr.YMost()) / GLfloat(aTexSize.height) };
67
0
68
0
    // then check if we wrap in either the x or y axis; if we do,
69
0
    // then also use fmod to figure out the "true" non-wrapping
70
0
    // texture coordinates.
71
0
72
0
    bool xwrap = false, ywrap = false;
73
0
    if (tcr.X() < 0 || tcr.X() > aTexSize.width ||
74
0
        tcr.XMost() < 0 || tcr.XMost() > aTexSize.width)
75
0
    {
76
0
        xwrap = true;
77
0
        tl[0] = WrapTexCoord(tl[0]);
78
0
        br[0] = WrapTexCoord(br[0]);
79
0
    }
80
0
81
0
    if (tcr.Y() < 0 || tcr.Y() > aTexSize.height ||
82
0
        tcr.YMost() < 0 || tcr.YMost() > aTexSize.height)
83
0
    {
84
0
        ywrap = true;
85
0
        tl[1] = WrapTexCoord(tl[1]);
86
0
        br[1] = WrapTexCoord(br[1]);
87
0
    }
88
0
89
0
    NS_ASSERTION(tl[0] >= 0.0f && tl[0] <= 1.0f &&
90
0
                 tl[1] >= 0.0f && tl[1] <= 1.0f &&
91
0
                 br[0] >= 0.0f && br[0] <= 1.0f &&
92
0
                 br[1] >= 0.0f && br[1] <= 1.0f,
93
0
                 "Somehow generated invalid texture coordinates");
94
0
95
0
    // If xwrap is false, the texture will be sampled from tl[0]
96
0
    // .. br[0].  If xwrap is true, then it will be split into tl[0]
97
0
    // .. 1.0, and 0.0 .. br[0].  Same for the Y axis.  The
98
0
    // destination rectangle is also split appropriately, according
99
0
    // to the calculated xmid/ymid values.
100
0
101
0
    // There isn't a 1:1 mapping between tex coords and destination coords;
102
0
    // when computing midpoints, we have to take that into account.  We
103
0
    // need to map the texture coords, which are (in the wrap case):
104
0
    // |tl->1| and |0->br| to the |0->1| range of the vertex coords.  So
105
0
    // we have the length (1-tl)+(br) that needs to map into 0->1.
106
0
    // These are only valid if there is wrap involved, they won't be used
107
0
    // otherwise.
108
0
    GLfloat xlen = (1.0f - tl[0]) + br[0];
109
0
    GLfloat ylen = (1.0f - tl[1]) + br[1];
110
0
111
0
    NS_ASSERTION(!xwrap || xlen > 0.0f, "xlen isn't > 0, what's going on?");
112
0
    NS_ASSERTION(!ywrap || ylen > 0.0f, "ylen isn't > 0, what's going on?");
113
0
    NS_ASSERTION(aTexCoordRect.Width() <= aTexSize.width &&
114
0
                 aTexCoordRect.Height() <= aTexSize.height, "tex coord rect would cause tiling!");
115
0
116
0
    if (!xwrap && !ywrap) {
117
0
        aRects.addRect(0.0f, 0.0f,
118
0
                       1.0f, 1.0f,
119
0
                       tl[0], tl[1],
120
0
                       br[0], br[1],
121
0
                       aFlipY);
122
0
    } else if (!xwrap && ywrap) {
123
0
        GLfloat ymid = (1.0f - tl[1]) / ylen;
124
0
        aRects.addRect(0.0f, 0.0f,
125
0
                       1.0f, ymid,
126
0
                       tl[0], tl[1],
127
0
                       br[0], 1.0f,
128
0
                       aFlipY);
129
0
        aRects.addRect(0.0f, ymid,
130
0
                       1.0f, 1.0f,
131
0
                       tl[0], 0.0f,
132
0
                       br[0], br[1],
133
0
                       aFlipY);
134
0
    } else if (xwrap && !ywrap) {
135
0
        GLfloat xmid = (1.0f - tl[0]) / xlen;
136
0
        aRects.addRect(0.0f, 0.0f,
137
0
                       xmid, 1.0f,
138
0
                       tl[0], tl[1],
139
0
                       1.0f, br[1],
140
0
                       aFlipY);
141
0
        aRects.addRect(xmid, 0.0f,
142
0
                       1.0f, 1.0f,
143
0
                       0.0f, tl[1],
144
0
                       br[0], br[1],
145
0
                       aFlipY);
146
0
    } else {
147
0
        GLfloat xmid = (1.0f - tl[0]) / xlen;
148
0
        GLfloat ymid = (1.0f - tl[1]) / ylen;
149
0
        aRects.addRect(0.0f, 0.0f,
150
0
                       xmid, ymid,
151
0
                       tl[0], tl[1],
152
0
                       1.0f, 1.0f,
153
0
                       aFlipY);
154
0
        aRects.addRect(xmid, 0.0f,
155
0
                       1.0f, ymid,
156
0
                       0.0f, tl[1],
157
0
                       br[0], 1.0f,
158
0
                       aFlipY);
159
0
        aRects.addRect(0.0f, ymid,
160
0
                       xmid, 1.0f,
161
0
                       tl[0], 0.0f,
162
0
                       1.0f, br[1],
163
0
                       aFlipY);
164
0
        aRects.addRect(xmid, ymid,
165
0
                       1.0f, 1.0f,
166
0
                       0.0f, 0.0f,
167
0
                       br[0], br[1],
168
0
                       aFlipY);
169
0
    }
170
0
}
171
172
} // namespace gl
173
} // namespace mozilla