GlyphPage::size
78 static const size_t size = 256;
65 const UChar noBreakSpace = 0x00A0;
75 const UChar softHyphen = 0x00AD;
76 const UChar space = 0x0020;
61 const UChar leftToRightMark = 0x200E;
66 const UChar objectReplacementCharacter = 0xFFFC;
87 const UChar zeroWidthSpace = 0x200B;
88 const UChar zeroWidthNoBreakSpace = 0xFEFF;
106
113 #define U16_LEAD(supplementary) (UChar)(((supplementary)>>10)+0xd7c0)
114
115
122 #define U16_TRAIL(supplementary) (UChar)(((supplementary)&0x3ff)|0xdc00)
169 void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNumber)
170 {
171 ASSERT(!m_page);
172
173
174
175 ASSERT(m_level > 0 && m_parent);
176
177
178
179 GlyphPage* parentPage = m_parent->page();
180
181
182 if (fontData) {
183 if (m_level == 1) {
184
185
186
187 unsigned start = pageNumber * GlyphPage::size; <= pageNumber * 256
<= 0 * 256 = 0
<= 1 * 256 = 256
<= 4 * 256 = 1024
188 UChar buffer[GlyphPage::size * 2 + 2]; <= 256*2+2
189 unsigned bufferLength;
190 unsigned i;
191
192
193 if (start < 0x10000) {
194 bufferLength = GlyphPage::size; <= bufferLength = 256;
195 for (i = 0; i < GlyphPage::size; i++) <= startから順番に値をbufferへ書き込む
196 buffer[i] = start + i;
197
198 if (start == 0) { <=0ページの場合
199
200 for (i = 0; i < 0x20; ++i)
201 buffer[i] = zeroWidthSpace; <=制御コードはゼロスペース
202 for (i = 0x7F; i < 0xA0; i++)
203 buffer[i] = zeroWidthSpace; <=7F〜A0もゼロスペース
204 buffer[softHyphen] = zeroWidthSpace; <=0xAD
205
206
207 buffer[(int)'\n'] = ' ';
208 buffer[(int)'\t'] = ' ';
209 buffer[noBreakSpace] = ' ';
210 } else if (start == (leftToRightMark & ~(GlyphPage::size - 1))) { <== (0x200E & 0xFFFFFF00) 下位1バイト落とす。
211
212 buffer[leftToRightMark - start] = zeroWidthSpace;
213 buffer[rightToLeftMark - start] = zeroWidthSpace;
214 buffer[leftToRightEmbed - start] = zeroWidthSpace;
215 buffer[rightToLeftEmbed - start] = zeroWidthSpace;
216 buffer[leftToRightOverride - start] = zeroWidthSpace;
217 buffer[rightToLeftOverride - start] = zeroWidthSpace;
218 buffer[zeroWidthNonJoiner - start] = zeroWidthSpace;
219 buffer[zeroWidthJoiner - start] = zeroWidthSpace;
220 buffer[popDirectionalFormatting - start] = zeroWidthSpace;
221 } else if (start == (objectReplacementCharacter & ~(GlyphPage::size - 1))) {
222
223 buffer[objectReplacementCharacter - start] = zeroWidthSpace;
224 } else if (start == (zeroWidthNoBreakSpace & ~(GlyphPage::size - 1))) {
225
226 buffer[zeroWidthNoBreakSpace - start] = zeroWidthSpace;
227 }
228 } else {
229 bufferLength = GlyphPage::size * 2; <==0x10000以上
230 for (i = 0; i < GlyphPage::size; i++) {
231 int c = i + start;
232 buffer[i * 2] = U16_LEAD(c);
233 buffer[i * 2 + 1] = U16_TRAIL(c);
234 }
235 }
236
237 m_page = GlyphPage::create(this);
238
239
240
241
242
243
244 bool haveGlyphs;
245 if (fontData->isSegmented()) {
246 haveGlyphs = false;
247
248 const SegmentedFontData* segmentedFontData = static_cast<const SegmentedFontData*>(fontData);
249 unsigned numRanges = segmentedFontData->numRanges();
250 bool zeroFilled = false;
251 RefPtr<GlyphPage> scratchPage;
252 GlyphPage* pageToFill = m_page.get();
253 for (unsigned i = 0; i < numRanges; i++) {
254 const FontDataRange& range = segmentedFontData->rangeAt(i);
255
256
257 int from = max(0, static_cast<int>(range.from()) - static_cast<int>(start));
258 int to = 1 + min(static_cast<int>(range.to()) - static_cast<int>(start),
static_cast<int>(GlyphPage::size) - 1);
259 if (from < static_cast<int>(GlyphPage::size) && to > 0) {
260 if (haveGlyphs && !scratchPage) {
261 scratchPage = GlyphPage::create(this);
262 pageToFill = scratchPage.get();
263 }
264
265 if (!zeroFilled) {
266 if (from > 0 || to < static_cast<int>(GlyphPage::size)) {
267 for (unsigned i = 0; i < GlyphPage::size; i++)
268 pageToFill->setGlyphDataForIndex(i, 0, 0);
269 }
270 zeroFilled = true;
271 }
272 haveGlyphs |= fill(pageToFill,
from,
to - from,
buffer + from * (start < 0x10000 ? 1 : 2),
(to - from) * (start < 0x10000 ? 1 : 2),
range.fontData());
<=====ここ
273 if (scratchPage) {
274 ASSERT(to <= static_cast<int>(GlyphPage::size));
275 for (int j = from; j < to; j++) {
276 if (!m_page->glyphAt(j) && pageToFill->glyphAt(j))
277 m_page->setGlyphDataForIndex(j, pageToFill->glyphDataForIndex(j));
278 }
279 }
280 }
281 }
282 } else
283 haveGlyphs = fill(m_page.get(),
0,
GlyphPage::size,
buffer,
bufferLength,
static_cast<const SimpleFontData*>(fontData));
<=====ここ
284
285 if (!haveGlyphs)
286 m_page = 0;
287 } else if (parentPage && parentPage->owner() != m_parent) {
288
289
290
291
292
293
294
295
296
297
298 m_page = parentPage->owner()->getChild(fontData, pageNumber)->page();
299 } else {
300
301
302
303
304 GlyphPage* fallbackPage = getRootChild(fontData, pageNumber)->page();
305 if (!parentPage) {
306
307
308 m_page = fallbackPage;
309 } else if (!fallbackPage) {
310
311
312 m_page = parentPage;
313 } else {
314
315 m_page = GlyphPage::create(this);
316
317
318
319 bool newGlyphs = false;
320 for (unsigned i = 0; i < GlyphPage::size; i++) {
321 if (parentPage->glyphAt(i))
322 m_page->setGlyphDataForIndex(i, parentPage->glyphDataForIndex(i));
323 else if (fallbackPage->glyphAt(i)) {
324 m_page->setGlyphDataForIndex(i, fallbackPage->glyphDataForIndex(i));
325 newGlyphs = true;
326 } else
327 m_page->setGlyphDataForIndex(i, 0, 0);
328 }
329
330 if (!newGlyphs)
331
332 m_page = parentPage;
333 }
334 }
335 } else {
336 m_page = GlyphPage::create(this);
337
338
339
340
341 if (parentPage)
342 m_page->copyFrom(*parentPage);
343 else
344 m_page->clear();
345 }
346 }
91 bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
92 {
93 if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) {
94 SkDebugf("%s last char is high-surrogate", __FUNCTION__);
95 return false;
96 }
97
98 SkPaint paint;
99 fontData->platformData().setupPaint(&paint);
100 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
101
102 SkAutoSTMalloc <GlyphPage::size, uint16_t> glyphStorage(length);
103 uint16_t* glyphs = glyphStorage.get();
104 UChar *textBuffer = buffer;
105 UChar vTextBuffer[bufferLength];
106
107 if (fontData->platformData().orientation() == Vertical && !fontData->hasVerticalGlyphs()) {
108
109 convertToVerticalForms(buffer, vTextBuffer, bufferLength);
110 textBuffer = vTextBuffer;
111 }
112
113 unsigned count = paint.textToGlyphs(textBuffer, bufferLength << 1, glyphs); <=====
114 if (count != length) {
115 SkDebugf("%s count != length\n", __FUNCTION__);
116 return false;
117 }
118
119 if (fontData->hasVerticalGlyphs()) {
120 bool lookVariants = false;
121 for (unsigned i = 0; i < bufferLength; ++i) {
122 if (!Font::isCJKIdeograph(textBuffer[i])) {
123 lookVariants = true;
124 break;
125 }
126 }
127 if (lookVariants) {
128 if (substituteWithVerticalGlyphs(fontData->platformData(), glyphs, bufferLength)) {
129
130 convertToVerticalForms(buffer, vTextBuffer, bufferLength);
131 textBuffer = vTextBuffer;
132
133 unsigned count = paint.textToGlyphs(textBuffer, bufferLength << 1, glyphs);
134 if (count != length) {
135 SkDebugf("%s count != length\n", __FUNCTION__);
136 return false;
137 }
138 }
139 }
140 }
141
142 unsigned allGlyphs = 0;
143
144
145
146 if (EmojiFont::IsAvailable()) {
147 const UChar* curr = textBuffer;
148 for (unsigned i = 0; i < length; i++) {
149 SkUnichar uni = SkUTF16_NextUnichar(&curr);
150 uint16_t glyphID = glyphs[i];
151
152 if (!glyphID)
153 glyphID = EmojiFont::UnicharToGlyph(uni);
154 setGlyphDataForIndex(offset + i, glyphID, fontData);
155 allGlyphs |= glyphID;
156 }
157 } else {
158 for (unsigned i = 0; i < length; i++) {
159 uint16_t glyphID = glyphs[i];
160 setGlyphDataForIndex(offset + i, glyphID, fontData);
161 allGlyphs |= glyphID;
162 }
163 }
164 return allGlyphs != 0;
165 }
485 int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
486 uint16_t glyphs[]) const {
487 if (byteLength == 0) {
488 return 0;
489 }
490
491 SkASSERT(textData != NULL);
492
493 if (NULL == glyphs) {
494 switch (this->getTextEncoding()) {
495 case kUTF8_TextEncoding:
496 return SkUTF8_CountUnichars((const char*)textData, byteLength);
497 case kUTF16_TextEncoding:
498 return SkUTF16_CountUnichars((const uint16_t*)textData,
499 byteLength >> 1);
500 case kGlyphID_TextEncoding:
501 return byteLength >> 1;
502 default:
503 SkDEBUGFAIL("unknown text encoding");
504 }
505 return 0;
506 }
507
508
509
510
511 if (this->getTextEncoding() == kGlyphID_TextEncoding) {
512
513 memcpy(glyphs, textData, byteLength >> 1 << 1);
514 return byteLength >> 1;
515 }
516
517 SkAutoGlyphCache autoCache(*this, NULL);
518 SkGlyphCache* cache = autoCache.getCache();
519
520 const char* text = (const char*)textData;
521 const char* stop = text + byteLength;
522 uint16_t* gptr = glyphs;
523
524 switch (this->getTextEncoding()) {
525 case SkPaint::kUTF8_TextEncoding:
526 while (text < stop) {
527 *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
528 }
529 break;
530 case SkPaint::kUTF16_TextEncoding: {
531 const uint16_t* text16 = (const uint16_t*)text;
532 const uint16_t* stop16 = (const uint16_t*)stop;
533 while (text16 < stop16) {
534 *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
535 }
536 break;
537 }
538 default:
539 SkDEBUGFAIL("unknown text encoding");
540 }
541 return gptr - glyphs;
542 }
unicharToGlyphへ - のねの日記