Document DOMImplementationImp::createHTMLDocument(const std::u16string& title) { try { DocumentPtr document = std::make_shared<DocumentImp>(); document->setContentType(u"text/html"); DocumentType doctype = createDocumentType(u"html", u"", u""); // TODO: set node document document->appendChild(doctype); Element html = document->createElement(u"html"); document->appendChild(html); Element head = document->createElement(u"head"); html.appendChild(head); if (!title.empty()) { Element t = document->createElement(u"title"); head.appendChild(t); Text text = document->createTextNode(title); t.appendChild(text); } Element body = document->createElement(u"body"); html.appendChild(body); // TODO: Step 8. return document; } catch (...) { return nullptr; } }
void KMX_Environment::Load(std::u16string const & key, std::u16string const & value) { assert(!key.empty()); if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_PLATFORM)) { _platform = value; } else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_BASELAYOUT)) { _baseLayout = value; } else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_BASELAYOUTALT)) { _baseLayoutAlt = value; } else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_SIMULATEALTGR)) { _simulateAltGr = value == u"1"; } else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_CAPSLOCK)) { _capsLock = value == u"1"; } else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT)) { _baseLayoutGivesCtrlRAltForRAlt = value == u"1"; } else { // Unsupported key assert(false); } }
void CustomStyle::draw(Painter &p, const std::u16string &text, Style::TextElement elt, const WidgetState& st, const Rect &r, const Style::Extra &extra) const { const Margin& m = extra.margin; p.setFont (font); p.translate(r.x,r.y); const Sprite& icon = iconSprite(extra.icon,st,r); int dX=0; if( !icon.size().isEmpty() && elt!=TE_CheckboxTitle ){ p.setColor(Color(1.f)); p.setTexture( icon ); if( text.empty() ) { p.drawRect( (r.w-icon.w())/2, (r.h-icon.h())/2, icon.w(), icon.h() ); } else { p.drawRect( m.left, (r.h-icon.h())/2, icon.w(), icon.h() ); } } switch( elt ){ case TE_LabelTitle: case TE_CheckboxTitle: p.setColor(Color(0,0,0,1)); break; default: p.setColor(extra.fontColor); } const Size txtSz=extra.font.textSize(text); p.drawText( m.left+dX+(r.w-dX-m.xMargin()-txtSz.w)/2, (r.h-txtSz.h)/2, r.w-m.xMargin(), txtSz.h, text, AlignBottom ); p.translate(-r.x,-r.y); }
void MediaListImp::setMediaText(const std::u16string& mediaText) { clear(); if (!mediaText.empty()) { CSSParser parser; *this = *parser.parseMediaList(mediaText); } }
bool UTF16ToUTF8(const std::u16string& utf16, std::string& outUtf8) { if (utf16.empty()) { outUtf8.clear(); return true; } return llvm::convertUTF16ToUTF8String(utf16, outUtf8); }
void LineEdit::IntValidator::erase(std::u16string &string, size_t &scursor, size_t &ecursor) const { Validator::erase(string,scursor,ecursor); if(string.size()==1 && string[0]=='-') string[0] = '0'; if(string.empty()) string.push_back('0'); }
bool HTMLElementImp::toUnsigned(std::u16string& value) { stripLeadingAndTrailingWhitespace(value); if (value.empty()) return false; const char16_t* s = value.c_str(); while (*s) { if (!isDigit(*s)) return false; ++s; } return true; }
void WordSuggest::suggest(std::u16string input, Dictionary const * pDictionary, std::u16string& rBestSuggestion) { // Clear up mSuggestions.clear(); mThresholds.clear(); // Fallback for suggestion rBestSuggestion = u""; // Only do something when there is input if (!input.empty()) { // Decide whether word should start with big letter bool startsWithUpperCase = false; char16_t lowerCaseLetter = input[0]; if (toLower(lowerCaseLetter)) { startsWithUpperCase = lowerCaseLetter != input[0]; } // Ask for suggestions std::vector<std::u16string> suggestions = pDictionary->similarWords(input, startsWithUpperCase); uint i = 0; for (const std::u16string& rSuggestion : suggestions) { mSuggestions.push_back(std::move(mpAssetManager->createTextSimple(mFontSize, 1, rSuggestion))); // Only add maximal allowed number of suggestions if (++i >= WORD_SUGGEST_MAX_SUGGESTIONS) { break; } } // Save best suggestion if (!suggestions.empty()) { // First one is best rBestSuggestion = suggestions[0]; } // Prepare thresholds mThresholds.resize(mSuggestions.size(), LerpValue(0)); // Transform and position the suggestions initially transformSuggestions(); positionSuggestions(); } }
void LineEdit::IntValidator::insert(std::u16string &string, size_t &cursor, size_t &ecursor, char16_t data) const { if( cursor==0 ){ if(!string.empty() && string[0]=='-') return; if(data=='-' && !(string.size()>=1 && string[0]=='0')){ Validator::insert(string,cursor,ecursor,data); return; } if(data=='0' && ((string.size()==1 && string[0]=='-') || string.size()==0)){ Validator::insert(string,cursor,ecursor,data); return; } if(('1'<=data && data<='9') || data=='-'){ Validator::insert(string,cursor,ecursor,data); return; } return; } const size_t pos = cursor-1; if( data=='0' && !(pos<string.size() && string[pos]=='-') && !(string.size()==1 && string[0]=='0') ){ Validator::insert(string,cursor,ecursor,data); return; } if('1'<=data && data<='9'){ if(string.size()==1 && string[0]=='0'){ string.clear(); cursor = 0; ecursor = cursor; } Validator::insert(string,cursor,ecursor,data); return; } }
bool convertUTF16ToUTF8String(const std::u16string& utf16, std::string &Out) { assert(Out.empty()); // Avoid OOB by returning early on empty input. if (utf16.empty()) return true; const UTF16 *Src = reinterpret_cast<const UTF16 *>(utf16.data()); const UTF16 *SrcEnd = reinterpret_cast<const UTF16 *>(utf16.data() + utf16.length()); // Byteswap if necessary. std::vector<UTF16> ByteSwapped; if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_SWAPPED) { ByteSwapped.insert(ByteSwapped.end(), Src, SrcEnd); for (size_t I = 0, E = ByteSwapped.size(); I != E; ++I) ByteSwapped[I] = SwapByteOrder_16(ByteSwapped[I]); Src = &ByteSwapped[0]; SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1; } // Skip the BOM for conversion. if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_NATIVE) Src++; // Just allocate enough space up front. We'll shrink it later. Out.resize(utf16.length() * UNI_MAX_UTF8_BYTES_PER_CODE_POINT + 1); UTF8 *Dst = reinterpret_cast<UTF8 *>(&Out[0]); UTF8 *DstEnd = Dst + Out.size(); ConversionResult CR = ConvertUTF16toUTF8(&Src, SrcEnd, &Dst, DstEnd, strictConversion); assert(CR != targetExhausted); if (CR != conversionOK) { Out.clear(); return false; } Out.resize(reinterpret_cast<char *>(Dst) - &Out[0]); return true; }
std::vector<TextFlow::Word> TextFlow::calculateFitWord(std::u16string content, int maxPixelWidth, float scale) const { // Calculate word from content Word word = calculateWord(content, scale); // End of recursion if ((content.size() == 1 && word.pixelWidth > maxPixelWidth) || content.empty()) { // Return empty vector as signal of failure return std::vector<Word>(); } else if (word.pixelWidth <= maxPixelWidth) { // If word length is ok, just return it return std::vector<Word>(1, word); } else { // Word is too wide and content longer than 1, split it! int length = (int)content.size(); int left = length / 2; int right = length - left; // Combine results from recursive call std::vector<Word> leftWord = calculateFitWord(content.substr(0, left), maxPixelWidth, scale); std::vector<Word> rightWord = calculateFitWord(content.substr(left+1, right), maxPixelWidth, scale); // If one or more of both are empty, forget it if (leftWord.empty() || rightWord.empty()) { return std::vector<Word>(); } else { std::vector<Word> words(leftWord); words.insert(words.end(), rightWord.begin(), rightWord.end()); return words; } } }
bool HTMLElementImp::toPxOrPercentage(std::u16string& value) { stripLeadingAndTrailingWhitespace(value); if (value.empty()) return false; const char16_t* s = value.c_str(); while (*s) { if (*s == '%') break; if (!isDigit(*s)) return false; ++s; } if (!*s) { value += u"px"; return true; } assert(*s == '%'); if (!s[1] && 1 < value.length()) return true; return false; }
bool TextFlow::insertFitWord(std::vector<TextFlow::Word>& rWords, const std::u16string& rContent, int maxPixelWidth, float scale) const { // Do nothing if input is empty if (rContent.empty()) { return true; } std::vector<Word> newWords = calculateFitWord(rContent, maxPixelWidth, scale); // Check, whether call was successful if (newWords.empty()) { // Was not successful, so return false return false; } else { // Insert new words and return true rWords.insert(rWords.end(), newWords.begin(), newWords.end()); return true; } }
void RenderString::CreateRenderCharacters(const std::u16string& newString) { if (!newString.empty() && mFont) { int advanceAccum = 0; // the accumulated horizontal advance for the current line int kerningAccum = 0; // the accumulated kerning offset for the current line int lineOffset = 0; // the vertical offset of the current line int lineHeight = mFont->GetLineHeight(); // retrieve and store the new line offset if (!mString.empty() && !mRenderChars.empty()) { // if we already have characters entered... if (mString.back() == u'\n') { // if the last character entered was a new line... lineOffset = mRenderChars.back().mLineHeight + lineHeight; // adjust the line offset for following characters } else { // laod the states of the accumulators from the previous characters entered advanceAccum = mRenderChars.back().mAdvanceAccum; kerningAccum = mRenderChars.back().mKerningAccum; lineOffset = mRenderChars.back().mLineHeight; kerningAccum += mFont->GetKerning(mString.back(), newString.front()); // adjust the kerning offset for the new character } } for (unsigned int i = 0u; i < newString.size(); ++i) { char16_t codePoint = newString.at(i); if (codePoint == u'\n') { // if the current character is a new line... advanceAccum = 0; // reset the horizontal advance kerningAccum = 0; // reset the kerning offset lineOffset += lineHeight; // increment the vertical offset by the new line height continue; // go to the next character } try { const FontBase::Glyph& glyph = mFont->GetGlyph(codePoint); // get the glyph object for the current character Shape shape = glyph.mBaseShape; // get the glyph shape from the glyph object float height = 0.0f; // the height of the glyph shape used for positional offsetting { const std::vector<glm::vec2>& bbox = shape.GetLocalBoundingBox(); // get the bounding box of the glyph if (!bbox.empty()) { // if the bounding box is valid... height = bbox.at(2).y - bbox.at(0).y; // calculate the height of the glyph shape } } shape.SetPosition(glm::vec2((advanceAccum + kerningAccum) + glyph.mBearing.x, ((mFont->GetBearingMax().y - glyph.mBearing.y) - mFont->GetBearingMax().y) + lineOffset)); // position the glyph shape { // update the local bounding box // get the bounding box of the newly added character std::vector<glm::vec2> bbox = shape.GetGlobalBoundingBox(); if (bbox.size() > 3) { // if the bounding box is valid... mTopLeft.x = std::min(bbox.at(0).x, mTopLeft.x); mTopLeft.y = std::min(bbox.at(0).y, mTopLeft.y); mBottomRight.x = std::max(bbox.at(2).x, mBottomRight.x); mBottomRight.y = std::max(bbox.at(2).y, mBottomRight.y); } } advanceAccum += glyph.mAdvance; // increment the horizontal advance accumulator by the current glyph's advance metric if (i != newString.size() - 1) { // if this is not the final character in the string... kerningAccum += mFont->GetKerning(codePoint, newString.at(i + 1)); // increment the kerning offset by the kerning value of this and the next character } mRenderChars.push_back({std::move(shape), advanceAccum, kerningAccum, lineOffset, mTopLeft, mBottomRight}); } catch(std::exception& e) { std::cout << "unknown codepoint: " << codePoint << std::endl; } } // update the full sized (not yet scaled) local bounding box glm::vec2 dimensions = mBottomRight - mTopLeft; mLocalBoundingBoxFull.clear(); mLocalBoundingBoxFull.emplace_back(0.0f, 0.0f); mLocalBoundingBoxFull.emplace_back(dimensions.x, 0.0f); mLocalBoundingBoxFull.emplace_back(dimensions.x, dimensions.y); mLocalBoundingBoxFull.emplace_back(0.0f, dimensions.y); } }