static void TestUTF(skiatest::Reporter* reporter) { static const struct { const char* fUtf8; SkUnichar fUni; } gTest[] = { { "a", 'a' }, { "\x7f", 0x7f }, { "\xC2\x80", 0x80 }, { "\xC3\x83", (3 << 6) | 3 }, { "\xDF\xBF", 0x7ff }, { "\xE0\xA0\x80", 0x800 }, { "\xE0\xB0\xB8", 0xC38 }, { "\xE3\x83\x83", (3 << 12) | (3 << 6) | 3 }, { "\xEF\xBF\xBF", 0xFFFF }, { "\xF0\x90\x80\x80", 0x10000 }, { "\xF3\x83\x83\x83", (3 << 18) | (3 << 12) | (3 << 6) | 3 } }; for (size_t i = 0; i < SK_ARRAY_COUNT(gTest); i++) { const char* p = gTest[i].fUtf8; int n = SkUTF8_CountUnichars(p); SkUnichar u0 = SkUTF8_ToUnichar(gTest[i].fUtf8); SkUnichar u1 = SkUTF8_NextUnichar(&p); REPORTER_ASSERT(reporter, n == 1); REPORTER_ASSERT(reporter, u0 == u1); REPORTER_ASSERT(reporter, u0 == gTest[i].fUni); REPORTER_ASSERT(reporter, p - gTest[i].fUtf8 == (int)strlen(gTest[i].fUtf8)); } test_utf16(reporter); test_search(reporter); test_refptr(reporter); }
bool SkDisplayEvent::setProperty(int index, SkScriptValue& value) { SkASSERT(index == SK_PROPERTY(key) || index == SK_PROPERTY(keys)); SkASSERT(value.fType == SkType_String); SkString* string = value.fOperand.fString; const char* chars = string->c_str(); int count = SkUTF8_CountUnichars(chars); SkASSERT(count >= 1); code = (SkKey) SkUTF8_NextUnichar(&chars); fMax = code; SkASSERT(count == 1 || index == SK_PROPERTY(keys)); if (--count > 0) { SkASSERT(*chars == '-'); chars++; fMax = (SkKey) SkUTF8_NextUnichar(&chars); SkASSERT(fMax >= code); } return true; }
static size_t linebreak(const char text[], const char stop[], const SkPaint& paint, SkScalar margin) { const char* start = text; SkAutoGlyphCache ac(paint, NULL); SkGlyphCache* cache = ac.getCache(); SkFixed w = 0; SkFixed limit = SkScalarToFixed(margin); SkAutoKern autokern; const char* word_start = text; int prevWS = true; while (text < stop) { const char* prevText = text; SkUnichar uni = SkUTF8_NextUnichar(&text); int currWS = is_ws(uni); const SkGlyph& glyph = cache->getUnicharMetrics(uni); if (!currWS && prevWS) word_start = prevText; prevWS = currWS; w += autokern.adjust(glyph) + glyph.fAdvanceX; if (w > limit) { if (currWS) // eat the rest of the whitespace { while (text < stop && is_ws(SkUTF8_ToUnichar(text))) text += SkUTF8_CountUTF8Bytes(text); } else // backup until a whitespace (or 1 char) { if (word_start == start) { if (prevText > start) text = prevText; } else text = word_start; } break; } } return text - start; }
int SkTestTypeface::onCharsToGlyphs(const void* chars, Encoding encoding, uint16_t glyphs[], int glyphCount) const { auto utf8 = (const char*)chars; auto utf16 = (const uint16_t*)chars; auto utf32 = (const SkUnichar*)chars; for (int i = 0; i < glyphCount; i++) { SkUnichar ch; switch (encoding) { case kUTF8_Encoding: ch = SkUTF8_NextUnichar(&utf8 ); break; case kUTF16_Encoding: ch = SkUTF16_NextUnichar(&utf16); break; case kUTF32_Encoding: ch = *utf32++; break; } if (glyphs) { glyphs[i] = fTestFont->codeToIndex(ch); } } return glyphCount; }
static void output_path_data(const SkPaint& paint, const char* used, int emSize, SkString* ptsOut, SkTDArray<SkPath::Verb>* verbs, SkTDArray<unsigned>* charCodes, SkTDArray<SkScalar>* widths) { while (*used) { SkUnichar index = SkUTF8_NextUnichar(&used); SkPath path; paint.getTextPath((const void*) &index, 2, 0, 0, &path); SkPath::RawIter iter(path); SkPath::Verb verb; SkPoint pts[4]; while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { *verbs->append() = verb; switch (verb) { case SkPath::kMove_Verb: output_points(&pts[0], emSize, 1, ptsOut); break; case SkPath::kLine_Verb: output_points(&pts[1], emSize, 1, ptsOut); break; case SkPath::kQuad_Verb: output_points(&pts[1], emSize, 2, ptsOut); break; case SkPath::kCubic_Verb: output_points(&pts[1], emSize, 3, ptsOut); break; case SkPath::kClose_Verb: break; default: SkDEBUGFAIL("bad verb"); SkASSERT(0); } } *verbs->append() = SkPath::kDone_Verb; *charCodes->append() = index; SkScalar width; SkDEBUGCODE(int charCount =) paint.getTextWidths((const void*) &index, 2, &width); SkASSERT(charCount == 1); // SkASSERT(floor(width) == width); // not true for Hiragino Maru Gothic Pro *widths->append() = width; } }
static SkUnichar next_utf8(const void** chars) { return SkUTF8_NextUnichar((const char**)chars); }
static size_t linebreak(const char text[], const char stop[], const SkPaint& paint, SkScalar margin, size_t* trailing = nullptr) { size_t lengthBreak = paint.breakText(text, stop - text, margin); //Check for white space or line breakers before the lengthBreak const char* start = text; const char* word_start = text; int prevWS = true; if (trailing) { *trailing = 0; } while (text < stop) { const char* prevText = text; SkUnichar uni = SkUTF8_NextUnichar(&text); int currWS = is_ws(uni); if (!currWS && prevWS) { word_start = prevText; } prevWS = currWS; if (text > start + lengthBreak) { if (currWS) { // eat the rest of the whitespace while (text < stop && is_ws(SkUTF8_ToUnichar(text))) { text += SkUTF8_CountUTF8Bytes(text); } if (trailing) { *trailing = text - prevText; } } else { // backup until a whitespace (or 1 char) if (word_start == start) { if (prevText > start) { text = prevText; } } else { text = word_start; } } break; } if ('\n' == uni) { size_t ret = text - start; size_t lineBreakSize = 1; if (text < stop) { uni = SkUTF8_NextUnichar(&text); if ('\r' == uni) { ret = text - start; ++lineBreakSize; } } if (trailing) { *trailing = lineBreakSize; } return ret; } if ('\r' == uni) { size_t ret = text - start; size_t lineBreakSize = 1; if (text < stop) { uni = SkUTF8_NextUnichar(&text); if ('\n' == uni) { ret = text - start; ++lineBreakSize; } } if (trailing) { *trailing = lineBreakSize; } return ret; } } return text - start; }
bool Window_mac::handleEvent(const SDL_Event& event) { switch (event.type) { case SDL_WINDOWEVENT: if (SDL_WINDOWEVENT_EXPOSED == event.window.event) { this->onPaint(); } else if (SDL_WINDOWEVENT_RESIZED == event.window.event) { this->onResize(event.window.data1, event.window.data2); } break; case SDL_MOUSEBUTTONDOWN: if (event.button.button == SDL_BUTTON_LEFT) { this->onMouse(event.button.x, event.button.y, Window::kDown_InputState, get_modifiers(event)); } break; case SDL_MOUSEBUTTONUP: if (event.button.button == SDL_BUTTON_LEFT) { this->onMouse(event.button.x, event.button.y, Window::kUp_InputState, get_modifiers(event)); } break; case SDL_MOUSEMOTION: this->onMouse(event.motion.x, event.motion.y, Window::kMove_InputState, get_modifiers(event)); break; case SDL_MOUSEWHEEL: this->onMouseWheel(event.wheel.y, get_modifiers(event)); break; case SDL_KEYDOWN: { Window::Key key = get_key(event.key.keysym); if (key != Window::Key::kNONE) { if (!this->onKey(key, Window::kDown_InputState, get_modifiers(event))) { if (event.key.keysym.sym == SDLK_ESCAPE) { return true; } } } } break; case SDL_KEYUP: { Window::Key key = get_key(event.key.keysym); if (key != Window::Key::kNONE) { (void) this->onKey(key, Window::kUp_InputState, get_modifiers(event)); } } break; case SDL_TEXTINPUT: { const char* textIter = &event.text.text[0]; while (SkUnichar c = SkUTF8_NextUnichar(&textIter)) { (void) this->onChar(c, get_modifiers(event)); } } break; default: break; } return false; }