IRIRef *IRIRef::urify() throw(BadAllocException) { if (this->urified) { return this; } const uint8_t *begin = this->utf8str->dptr(); const uint8_t *end = begin + this->utf8str->size(); const uint8_t *mark = begin; const uint8_t *next = NULL; uint32_t codepoint; while (mark != end) { codepoint = utf8char(mark, &next); if (IRIRef::isIPrivate(codepoint) || IRIRef::isUCSChar(codepoint)) { break; } mark = next; } if (mark == end) { this->urified = true; return this; } vector<uint8_t> urivec; urivec.reserve(this->utf8str->size() + 2); do { urivec.insert(urivec.end(), begin, mark); for (; mark != next; ++mark) { urivec.push_back(to_ascii('%')); uint8_t hi4 = (*mark) >> 4; uint8_t lo4 = (*mark) & UINT8_C(0x0F); urivec.push_back(hi4 <= UINT8_C(9) ? to_ascii('0') + hi4 : to_ascii('A') + (hi4 - 10)); urivec.push_back(lo4 <= UINT8_C(9) ? to_ascii('0') + lo4 : to_ascii('A') + (lo4 - 10)); } begin = mark; while (mark != end) { codepoint = utf8char(mark, &next); if (IRIRef::isIPrivate(codepoint) || IRIRef::isUCSChar(codepoint)) { break; } mark = next; } } while(mark != end); urivec.insert(urivec.end(), begin, mark); MPtr<uint8_t> *uristr; try { NEW(uristr, MPtr<uint8_t>, urivec.size()); } RETHROW_BAD_ALLOC copy(urivec.begin(), urivec.end(), uristr->dptr()); this->utf8str->drop(); this->utf8str = uristr; this->urified = true; return this; }
void Utf8Charset::push_back(int amount, unicode_t unicode, ...) { unicode_t val; UnicodeGroup unicodegroup; if(amount <= 0) return; unicodegroup.array.push_back(unicode); va_list vl; va_start(vl, unicode); for (int i = 1; i < amount; i++) { val = va_arg(vl, unicode_t); unicodegroup.array.push_back(val); } va_end(vl); unicodegroup.group_code = unicode; Utf8Char utf8char(unicode); unicodegroup.output_string = utf8char.tostring(); unicodegroup.flags = 0x0; unicodegroup.index = this->charset.size(); this->charset.push_back(unicodegroup); }
void Utf8Charset::push_back(unicode_t group_code, std::string output_string, unsigned int flags, int amount, unicode_t unicode, ...) { unicode_t val; UnicodeGroup unicodegroup; if(amount <= 0) return; unicodegroup.array.push_back(unicode); va_list vl; va_start(vl, unicode); for (int i = 1; i < amount; i++) { val = va_arg(vl, unicode_t); unicodegroup.array.push_back(val); } va_end(vl); if (group_code != 0) unicodegroup.group_code = group_code; else unicodegroup.group_code = unicode; if (!output_string.empty()) unicodegroup.output_string = output_string; else { Utf8Char utf8char(unicode); unicodegroup.output_string = utf8char.tostring(); } unicodegroup.flags = flags; this->charset.push_back(unicodegroup); }
IRIRef *IRIRef::normalize() THROWS(BadAllocException, TraceableException) { if (this->normalized && !this->urified) { return this; } uint8_t *normed = NULL; DPtr<uint8_t> *normal = NULL; if (this->utf8str->standable()) { this->utf8str = this->utf8str->stand(); normal = this->utf8str; normal->hold(); } else { NEW(normal, MPtr<uint8_t>, this->utf8str->size()); } normed = normal->dptr(); // Percent encoding; decode if IUnreserved uint8_t bits = UINT8_C(0); uint8_t *begin = this->utf8str->dptr(); uint8_t *end = begin + this->utf8str->size(); uint8_t *marki = begin; uint8_t *markj = begin; uint8_t *markk = normed; for (; marki != end; marki = markj) { for (markj = marki; markj != end && *markj != to_ascii('%'); ++markj) { // loop does the work } size_t sz = markj - marki; memmove(markk, marki, sz * sizeof(uint8_t)); markk += sz; if (markj == end) { break; } uint8_t enc[4] = { UINT8_C(0xFF), UINT8_C(0xFF), UINT8_C(0xFF), UINT8_C(0xFF) }; enc[0] = (((uint8_t) IRI_HEX_VALUE(markj[1])) << 4) | (uint8_t) IRI_HEX_VALUE(markj[2]); if (enc[0] <= UINT8_C(0x7F)) { if (IRIRef::isIUnreserved(enc[0])) { *markk = enc[0]; ++markk; } else { markk[0] = markj[0]; markk[1] = to_upper(markj[1]); markk[2] = to_upper(markj[2]); markk += 3; } markj += 3; continue; } uint8_t *markl = markj + 3; int i = 1; uint8_t bits; for (bits = enc[0] << 1; markl != end && *markl == to_ascii('%') && bits > UINT8_C(0x7F) && i < 4; bits <<= 1) { enc[i] = (((uint8_t) IRI_HEX_VALUE(markl[1])) << 4) | (uint8_t) IRI_HEX_VALUE(markl[2]); markl += 3; ++i; } try { const uint8_t *endenc; uint32_t codepoint = utf8char(enc, &endenc); if (IRIRef::isIUnreserved(codepoint)) { i = endenc - enc; // should already be equal, but just in case memmove(markk, enc, i * sizeof(uint8_t)); markk += i; markj = markl; this->urified = false; } else { for (; markj != markl; markj += 3) { markk[0] = markj[0]; markk[1] = to_upper(markj[1]); markk[2] = to_upper(markj[2]); markk += 3; } } } catch (InvalidEncodingException &e) { markk[0] = markj[0]; markk[1] = to_upper(markj[1]); markk[2] = to_upper(markj[2]); markk += 3; markj += 3; } } if (markk != end) { DPtr<uint8_t> *temp = normal->sub(0, markk - normed); normal->drop(); normal = temp; } if (this->normalized) { this->utf8str->drop(); this->utf8str = normal; return this; } // Character normalization; NFC DPtr<uint32_t> *codepoints = utf8dec(normal); normal->drop(); DPtr<uint32_t> *codepoints2 = nfc_opt(codepoints); codepoints->drop(); normal = utf8enc(codepoints2); codepoints2->drop(); this->utf8str->drop(); this->utf8str = normal; // Path normalization this->resolve(NULL); // Case normalization; scheme and host DPtr<uint8_t> *part = this->getPart(SCHEME); if (part != NULL) { begin = part->dptr(); end = begin + part->size(); for (; begin != end; ++begin) { *begin = to_lower(*begin); } part->drop(); } part = this->getPart(HOST); if (part != NULL) { begin = part->dptr(); end = begin + part->size(); for (; begin != end; ++begin) { *begin = to_lower(*begin); } part->drop(); } this->normalized = true; return this; }
int DrawText(HDC ctx, const char *buf, int buflen, RECT *r, int align) { const char *obuf=buf; HDC__ *ct=(HDC__ *)ctx; if (!r) return 0; int lineh = 8; int charw = 8; HGDIOBJ__ *font = NULL; #ifdef SWELL_FREETYPE int ascent=0; font = HDC_VALID(ct) && HGDIOBJ_VALID(ct->curfont,TYPE_FONT) ? ct->curfont : SWELL_GetDefaultFont(); FT_Face face = NULL; if (font && font->fontface) { face=(FT_Face)font->fontface; lineh = face->size->metrics.height/64; ascent = face->size->metrics.ascender/64; charw = face->size->metrics.max_advance/64; } #endif if (align&DT_CALCRECT) { if (!font && (align&DT_SINGLELINE)) { r->right = r->left + ( buflen < 0 ? strlen(buf) : buflen ) * charw; int h = r->right ? lineh:0; r->bottom = r->top+h; return h; } int xpos=0; int ypos=0; r->bottom=r->top; bool in_prefix=false; while (buflen && *buf) // if buflen<0, go forever { unsigned short c=0; int charlen = utf8char(buf,&c); buf+=charlen; if (buflen > 0) { buflen -= charlen; if (buflen < 0) buflen=0; } if (!c) break; if (c=='&' && !in_prefix && !(align&DT_NOPREFIX)) { in_prefix = true; continue; } in_prefix=false; if (c == '\n') { ypos += lineh; xpos=0; } else if (c != '\r') { if (font) { #ifdef SWELL_FREETYPE if (!FT_Load_Char(face, c, FT_LOAD_DEFAULT) && face->glyph) { // measure character FT_GlyphSlot g = face->glyph; int rext = xpos + (g->metrics.width + g->metrics.horiBearingX)/64; if (rext<=xpos) rext=xpos + g->metrics.horiAdvance/64; if (r->left+rext > r->right) r->right = r->left+rext; xpos += g->metrics.horiAdvance/64; int bext = r->top + ypos + lineh; // ascent + (g->metrics.height - g->metrics.horiBearingY)/64; if (bext > r->bottom) r->bottom = bext; continue; } } #endif xpos += c=='\t' ? charw*5 : charw; if (r->top + ypos + lineh > r->bottom) r->bottom = r->top+ypos+lineh; if (r->left+xpos>r->right) r->right=r->left+xpos; } } return r->bottom-r->top; } if (!HDC_VALID(ct)) return 0; RECT use_r = *r; use_r.left += ct->surface_offs.x; use_r.right += ct->surface_offs.x; use_r.top += ct->surface_offs.y; use_r.bottom += ct->surface_offs.y; int xpos = use_r.left; int ypos = use_r.top; if (align&(DT_CENTER|DT_VCENTER|DT_RIGHT|DT_BOTTOM)) { RECT tr={0,}; DrawText(ctx,buf,buflen,&tr,align|DT_CALCRECT); if (align&DT_CENTER) xpos -= ((tr.right-tr.left) - (use_r.right-use_r.left))/2; else if (align&DT_RIGHT) xpos = use_r.right - (tr.right-tr.left); if (align&DT_VCENTER) ypos -= ((tr.bottom-tr.top) - (use_r.bottom-use_r.top))/2; else if (align&DT_BOTTOM) ypos = use_r.bottom - (tr.bottom-tr.top); } LICE_IBitmap *surface = ct->surface; int fgcol = ct->cur_text_color_int; int bgcol = ct->curbkcol; int bgmode = ct->curbkmode; int clip_x1=wdl_max(use_r.left,0), clip_y1 = wdl_max(use_r.top,0); int clip_w=0, clip_h=0; if (surface) { clip_w = wdl_min(use_r.right,surface->getWidth())-clip_x1; clip_h = wdl_min(use_r.bottom,surface->getHeight())-clip_y1; if (clip_w<0)clip_w=0; if (clip_h<0)clip_h=0; } LICE_SubBitmap clipbm(surface,clip_x1,clip_y1,clip_w,clip_h); if (surface && !(align&DT_NOCLIP)) { surface = &clipbm; xpos-=clip_x1; ypos-=clip_y1; } int left_xpos = xpos,ysize=0,max_xpos=0; int start_ypos = ypos; bool in_prefix=false; while (buflen && *buf) { unsigned short c=0; int charlen = utf8char(buf,&c); if (buflen>0) { buflen -= charlen; if (buflen<0) buflen=0; } buf+=charlen; bool doUl=in_prefix; if (c=='&' && !in_prefix && !(align&DT_NOPREFIX)) { in_prefix = true; continue; } in_prefix=false; if (c=='\n' && !(align&DT_SINGLELINE)) { xpos=left_xpos; ypos+=lineh; } else if (c=='\r') {} else { bool needr=true; if (font) { #ifdef SWELL_FREETYPE if (!FT_Load_Char(face, c, FT_LOAD_RENDER) && face->glyph) { FT_GlyphSlot g = face->glyph; if (bgmode==OPAQUE) LICE_FillRect(surface,xpos,ypos,g->metrics.horiAdvance/64,lineh,bgcol,1.0f,LICE_BLIT_MODE_COPY); LICE_DrawGlyphEx(surface,xpos+g->bitmap_left,ypos+ascent-g->bitmap_top,fgcol,(LICE_pixel_chan *)g->bitmap.buffer,g->bitmap.width,g->bitmap.pitch,g->bitmap.rows,1.0f,LICE_BLIT_MODE_COPY); int rext = xpos + (g->metrics.width + g->metrics.horiBearingX)/64; if (rext<=xpos) rext=xpos + g->metrics.horiAdvance/64; if (rext > max_xpos) max_xpos=rext; xpos += g->metrics.horiAdvance/64; int bext = ypos + lineh; // + (g->metrics.height - g->metrics.horiBearingY)/64; if (ysize < bext) ysize=bext; needr=false; } #endif } if (needr) { if (c=='\t') { if (bgmode==OPAQUE) LICE_FillRect(surface,xpos,ypos,charw*5,lineh,bgcol,1.0f,LICE_BLIT_MODE_COPY); xpos+=charw*5; if (ysize < ypos+lineh) ysize=ypos+lineh; } else { if (bgmode==OPAQUE) LICE_FillRect(surface,xpos,ypos,charw,lineh,bgcol,1.0f,LICE_BLIT_MODE_COPY); LICE_DrawChar(surface,xpos,ypos,c,fgcol,1.0f,LICE_BLIT_MODE_COPY); if (doUl) LICE_Line(surface,xpos,ypos+lineh+1,xpos+charw,ypos+lineh+1,fgcol,1.0f,LICE_BLIT_MODE_COPY,false); if (ysize < ypos+lineh+(doUl ? 2:1)) ysize=ypos+lineh+(doUl ? 2:1); xpos+=charw; } } } if(xpos>max_xpos)max_xpos=xpos; } if (surface==&clipbm) swell_DirtyContext(ct,clip_x1+left_xpos,clip_y1+start_ypos,clip_x1+max_xpos,clip_y1+start_ypos+ysize); else swell_DirtyContext(ct,left_xpos,start_ypos,max_xpos,start_ypos+ysize); return ysize; }