78 float x=0, y=0; |
78 float x=0, y=0; |
79 float startX, startY; |
79 float startX, startY; |
80 float scale = 1.0f/64.0f; |
80 float scale = 1.0f/64.0f; |
81 unsigned int* glyphs; |
81 unsigned int* glyphs; |
82 float* positions; |
82 float* positions; |
|
83 int initialCount, glyphArrayLen, posArrayLen, maxGlyphs, storeadv; |
|
84 unsigned int* indices; |
|
85 jarray glyphArray, posArray, inxArray; |
83 |
86 |
84 if (!init_JNI_IDs(env)) { |
87 if (!init_JNI_IDs(env)) { |
85 return 0; |
88 return 0; |
86 } |
89 } |
87 |
90 |
88 int initialCount = (*env)->GetIntField(env, gvdata, gvdCountFID); |
91 initialCount = (*env)->GetIntField(env, gvdata, gvdCountFID); |
89 jarray glyphArray = |
92 glyphArray = |
90 (jarray)(*env)->GetObjectField(env, gvdata, gvdGlyphsFID); |
93 (jarray)(*env)->GetObjectField(env, gvdata, gvdGlyphsFID); |
91 jarray posArray = |
94 posArray = |
92 (jarray)(*env)->GetObjectField(env, gvdata, gvdPositionsFID); |
95 (jarray)(*env)->GetObjectField(env, gvdata, gvdPositionsFID); |
93 |
96 |
94 if (glyphArray == NULL || posArray == NULL) |
97 if (glyphArray == NULL || posArray == NULL) |
95 { |
98 { |
96 JNU_ThrowArrayIndexOutOfBoundsException(env, ""); |
99 JNU_ThrowArrayIndexOutOfBoundsException(env, ""); |
99 |
102 |
100 // The Java code catches the IIOBE and expands the storage |
103 // The Java code catches the IIOBE and expands the storage |
101 // and re-invokes layout. I suppose this is expected to be rare |
104 // and re-invokes layout. I suppose this is expected to be rare |
102 // because at least in a single threaded case there should be |
105 // because at least in a single threaded case there should be |
103 // re-use of the same container, but it is a little wasteful/distateful. |
106 // re-use of the same container, but it is a little wasteful/distateful. |
104 int glyphArrayLen = (*env)->GetArrayLength(env, glyphArray); |
107 glyphArrayLen = (*env)->GetArrayLength(env, glyphArray); |
105 int posArrayLen = (*env)->GetArrayLength(env, posArray); |
108 posArrayLen = (*env)->GetArrayLength(env, posArray); |
106 int maxGlyphs = glyphCount + initialCount; |
109 maxGlyphs = glyphCount + initialCount; |
107 if ((maxGlyphs > glyphArrayLen) || |
110 if ((maxGlyphs > glyphArrayLen) || |
108 (maxGlyphs * 2 + 2 > posArrayLen)) |
111 (maxGlyphs * 2 + 2 > posArrayLen)) |
109 { |
112 { |
110 JNU_ThrowArrayIndexOutOfBoundsException(env, ""); |
113 JNU_ThrowArrayIndexOutOfBoundsException(env, ""); |
111 return 0; |
114 return 0; |
123 positions[(storei*2)] = startX + x + glyphPos[i].x_offset * scale; |
126 positions[(storei*2)] = startX + x + glyphPos[i].x_offset * scale; |
124 positions[(storei*2)+1] = startY + y - glyphPos[i].y_offset * scale; |
127 positions[(storei*2)+1] = startY + y - glyphPos[i].y_offset * scale; |
125 x += glyphPos[i].x_advance * scale; |
128 x += glyphPos[i].x_advance * scale; |
126 y += glyphPos[i].y_advance * scale; |
129 y += glyphPos[i].y_advance * scale; |
127 } |
130 } |
128 int storeadv = initialCount+glyphCount; |
131 storeadv = initialCount+glyphCount; |
129 // The final slot in the positions array is important |
132 // The final slot in the positions array is important |
130 // because when the GlyphVector is created from this |
133 // because when the GlyphVector is created from this |
131 // data it determines the overall advance of the glyphvector |
134 // data it determines the overall advance of the glyphvector |
132 // and this is used in positioning the next glyphvector |
135 // and this is used in positioning the next glyphvector |
133 // during rendering where text is broken into runs. |
136 // during rendering where text is broken into runs. |
136 positions[(storeadv*2)] = startX + x; |
139 positions[(storeadv*2)] = startX + x; |
137 positions[(storeadv*2)+1] = startY + y; |
140 positions[(storeadv*2)+1] = startY + y; |
138 (*env)->ReleasePrimitiveArrayCritical(env, glyphArray, glyphs, 0); |
141 (*env)->ReleasePrimitiveArrayCritical(env, glyphArray, glyphs, 0); |
139 (*env)->ReleasePrimitiveArrayCritical(env, posArray, positions, 0); |
142 (*env)->ReleasePrimitiveArrayCritical(env, posArray, positions, 0); |
140 putFloat(env, startPt,positions[(storeadv*2)],positions[(storeadv*2)+1] ); |
143 putFloat(env, startPt,positions[(storeadv*2)],positions[(storeadv*2)+1] ); |
141 jarray inxArray = |
144 inxArray = |
142 (jarray)(*env)->GetObjectField(env, gvdata, gvdIndicesFID); |
145 (jarray)(*env)->GetObjectField(env, gvdata, gvdIndicesFID); |
143 unsigned int* indices = |
146 indices = |
144 (unsigned int*)(*env)->GetPrimitiveArrayCritical(env, inxArray, NULL); |
147 (unsigned int*)(*env)->GetPrimitiveArrayCritical(env, inxArray, NULL); |
145 int prevCluster = -1; |
|
146 for (i = 0; i < glyphCount; i++) { |
148 for (i = 0; i < glyphCount; i++) { |
147 int cluster = glyphInfo[i].cluster; |
149 int cluster = glyphInfo[i].cluster; |
148 if (direction == HB_DIRECTION_LTR) { |
150 if (direction == HB_DIRECTION_LTR) { |
149 // I need to understand what hb does when processing a substring |
151 // I need to understand what hb does when processing a substring |
150 // I expected the cluster index to be from the start of the text |
152 // I expected the cluster index to be from the start of the text |