int generic_pgf_draw_text(vita2d_pgf *font, int draw, int *height, int x, int y, unsigned int color, float scale, const char *text) { unsigned int character; bp2d_rectangle rect; texture_atlas_entry_data data; vita2d_texture *tex = font->atlas->texture; int start_x = x; int max_x = 0; int pen_x = x; int pen_y = y; while (*text) { character = utf8_character(&text); if (character == '\n') { if (pen_x > max_x) max_x = pen_x; pen_x = start_x; pen_y += font->vsize * scale; continue; } if (!texture_atlas_get(font->atlas, character, &rect, &data)) { if (!atlas_add_glyph(font, character)) { continue; } if (!texture_atlas_get(font->atlas, character, &rect, &data)) continue; } if (draw) { vita2d_draw_texture_tint_part_scale(tex, pen_x + data.bitmap_left * scale, pen_y - data.bitmap_top * scale, rect.x, rect.y, rect.w, rect.h, scale, scale, color); } pen_x += (data.advance_x >> 6) * scale; } if (pen_x > max_x) max_x = pen_x; if (height) *height = pen_y + font->vsize * scale - y; return max_x - x; }
//////////////////////////////////////////////////////////////////////////////// // Lexer::Type::string // '|" // [ U+XXXX | \uXXXX | \" | \' | \\ | \/ | \b | \f | \n | \r | \t | . ] // '|" bool Lexer::isString (std::string& token, Lexer::Type& type, int quote) { std::size_t marker = _cursor; if (_text[marker] == quote) { token = _text.substr (marker++, 1); int c; while ((c = _text[marker])) { // EOS. if (c == quote) break; // Unicode U+XXXX or \uXXXX codepoint. else if (_eos - marker >= 6 && ((_text[marker + 0] == 'U' && _text[marker + 1] == '+') || (_text[marker + 0] == '\\' && _text[marker + 1] == 'u')) && isHexDigit (_text[marker + 2]) && isHexDigit (_text[marker + 3]) && isHexDigit (_text[marker + 4]) && isHexDigit (_text[marker + 5])) { token += utf8_character ( hexToInt ( _text[marker + 2], _text[marker + 3], _text[marker + 4], _text[marker + 5])); marker += 6; } // An escaped thing. else if (c == '\\') { c = _text[++marker]; switch (c) { case '"': token += (char) 0x22; ++marker; break; case '\'': token += (char) 0x27; ++marker; break; case '\\': token += (char) 0x5C; ++marker; break; case 'b': token += (char) 0x08; ++marker; break; case 'f': token += (char) 0x0C; ++marker; break; case 'n': token += (char) 0x0A; ++marker; break; case 'r': token += (char) 0x0D; ++marker; break; case 't': token += (char) 0x09; ++marker; break; case 'v': token += (char) 0x0B; ++marker; break; // This pass-through default case means that anythign can be escaped // harmlessly. In particular 'quote' is included, if it not one of the // above characters. default: token += (char) c; ++marker; break; } } // Ordinary character. else token += utf8_character (utf8_next_char (_text, marker)); } if (_text[marker] == quote) { token += _text.substr (marker++, 1); type = Lexer::Type::string; _cursor = marker; return true; } } return false; }
//////////////////////////////////////////////////////////////////////////////// // Full implementation of an unquoted word. Includes: // one\ two // abcU+0020def // abc\u0020def // a\tb // // Ends at: // Lexer::isEOS // Lexer::isWhitespace // Lexer::isHardBoundary bool Lexer::readWord ( const std::string& text, std::string::size_type& cursor, std::string& word) { std::string::size_type eos = text.length (); word = ""; int c; int prev = 0; while ((c = text[cursor])) // Handles EOS. { // Unquoted word ends on white space. if (Lexer::isWhitespace (c)) break; // Parentheses mostly. if (prev && Lexer::isHardBoundary (prev, c)) break; // Unicode U+XXXX or \uXXXX codepoint. else if (eos - cursor >= 6 && ((text[cursor + 0] == 'U' && text[cursor + 1] == '+') || (text[cursor + 0] == '\\' && text[cursor + 1] == 'u')) && isHexDigit (text[cursor + 2]) && isHexDigit (text[cursor + 3]) && isHexDigit (text[cursor + 4]) && isHexDigit (text[cursor + 5])) { word += utf8_character ( hexToInt ( text[cursor + 2], text[cursor + 3], text[cursor + 4], text[cursor + 5])); cursor += 6; } // An escaped thing. else if (c == '\\') { c = text[++cursor]; switch (c) { case '"': word += (char) 0x22; ++cursor; break; case '\'': word += (char) 0x27; ++cursor; break; case '\\': word += (char) 0x5C; ++cursor; break; case 'b': word += (char) 0x08; ++cursor; break; case 'f': word += (char) 0x0C; ++cursor; break; case 'n': word += (char) 0x0A; ++cursor; break; case 'r': word += (char) 0x0D; ++cursor; break; case 't': word += (char) 0x09; ++cursor; break; case 'v': word += (char) 0x0B; ++cursor; break; // This pass-through default case means that anything can be escaped // harmlessly. In particular 'quote' is included, if it not one of the // above characters. default: word += (char) c; ++cursor; break; } } // Ordinary character. else word += utf8_character (utf8_next_char (text, cursor)); prev = c; } return word.length () > 0 ? true : false; }
//////////////////////////////////////////////////////////////////////////////// // Full implementation of a quoted word. Includes: // '\'' // '"' // "'" // "\"" // 'one two' // Result includes the quotes. bool Lexer::readWord ( const std::string& text, const std::string& quotes, std::string::size_type& cursor, std::string& word) { if (quotes.find (text[cursor]) == std::string::npos) return false; std::string::size_type eos = text.length (); int quote = text[cursor++]; word = quote; int c; while ((c = text[cursor])) { // Quoted word ends on a quote. if (quote && quote == c) { word += utf8_character (utf8_next_char (text, cursor)); break; } // Unicode U+XXXX or \uXXXX codepoint. else if (eos - cursor >= 6 && ((text[cursor + 0] == 'U' && text[cursor + 1] == '+') || (text[cursor + 0] == '\\' && text[cursor + 1] == 'u')) && isHexDigit (text[cursor + 2]) && isHexDigit (text[cursor + 3]) && isHexDigit (text[cursor + 4]) && isHexDigit (text[cursor + 5])) { word += utf8_character ( hexToInt ( text[cursor + 2], text[cursor + 3], text[cursor + 4], text[cursor + 5])); cursor += 6; } // An escaped thing. else if (c == '\\') { c = text[++cursor]; switch (c) { case '"': word += (char) 0x22; ++cursor; break; case '\'': word += (char) 0x27; ++cursor; break; case '\\': word += (char) 0x5C; ++cursor; break; case 'b': word += (char) 0x08; ++cursor; break; case 'f': word += (char) 0x0C; ++cursor; break; case 'n': word += (char) 0x0A; ++cursor; break; case 'r': word += (char) 0x0D; ++cursor; break; case 't': word += (char) 0x09; ++cursor; break; case 'v': word += (char) 0x0B; ++cursor; break; // This pass-through default case means that anything can be escaped // harmlessly. In particular 'quote' is included, if it not one of the // above characters. default: word += (char) c; ++cursor; break; } } // Ordinary character. else word += utf8_character (utf8_next_char (text, cursor)); } // Verify termination. return word[0] == quote && word[word.length () - 1] == quote && word.length () >= 2; }