//-----------------------------------------------------------------// inline float compare(const std::string& srca, const std::string& srcb) { lstring a; utf8_to_utf32(srca, a); lstring b; utf8_to_utf32(srcb, b); return compare(a, b); }
float glf_get_string_len(gl_tex_font_p glf, const char *text, int n) { float x = 0.0; if((glf != nullptr) && (glf->ft_face != nullptr)) { uint8_t *nch; uint8_t *nch2; uint8_t *ch = (uint8_t*)text; uint32_t curr_utf32, next_utf32; int i; nch = utf8_to_utf32(ch, &curr_utf32); curr_utf32 = FT_Get_Char_Index(glf->ft_face, curr_utf32); for(i = 0; (*ch != 0) && !((n >= 0) && (i >= n)); i++) { FT_Vector kern; nch2 = utf8_to_utf32(nch, &next_utf32); next_utf32 = FT_Get_Char_Index(glf->ft_face, next_utf32); ch = nch; nch = nch2; FT_Get_Kerning(glf->ft_face, curr_utf32, next_utf32, FT_KERNING_UNSCALED, &kern); // kern in 1/64 pixel curr_utf32 = next_utf32; x += static_cast<GLfloat>(kern.x + glf->glyphs[curr_utf32].advance_x) / 64.0; } } return x; }
int32_t glf_get_string_len(gl_tex_font_p glf, const char *text, int n) { int32_t x = 0; uint8_t *ch = (uint8_t*)text; if(glf && glf->ft_face && *ch) { uint32_t curr_utf32, next_utf32; int i = 0; FT_Vector kern; ch = utf8_to_utf32(ch, &curr_utf32); curr_utf32 = FT_Get_Char_Index(glf->ft_face, curr_utf32); for(; (n < 0) || (i < n); i++) { n = (*ch) ? (n) : (0); ch = utf8_to_utf32(ch, &next_utf32); next_utf32 = FT_Get_Char_Index(glf->ft_face, next_utf32); FT_Get_Kerning(glf->ft_face, curr_utf32, next_utf32, FT_KERNING_UNSCALED, &kern); // kern in 1/64 pixel curr_utf32 = next_utf32; x += kern.x + glf->glyphs[curr_utf32].advance_x_pt; } } return x; }
char *glf_get_string_for_width(gl_tex_font_p glf, char *text, int32_t w_pt, int *n_sym) { int32_t x = 0; uint8_t *ch = (uint8_t*)text; char *ret = text; *n_sym = 0; if(glf && glf->ft_face && *ch) { uint32_t curr_utf32, next_utf32; FT_Vector kern; ch = utf8_to_utf32(ch, &curr_utf32); curr_utf32 = FT_Get_Char_Index(glf->ft_face, curr_utf32); w_pt -= glf->glyphs[curr_utf32].advance_x_pt; do { ret = (char*)ch; (*n_sym)++; w_pt = (*ch) ? (w_pt) : (0); ch = utf8_to_utf32(ch, &next_utf32); next_utf32 = FT_Get_Char_Index(glf->ft_face, next_utf32); FT_Get_Kerning(glf->ft_face, curr_utf32, next_utf32, FT_KERNING_UNSCALED, &kern); // kern in 1/64 pixel curr_utf32 = next_utf32; x += kern.x + glf->glyphs[curr_utf32].advance_x_pt; } while(x < w_pt); } return ret; }
void glf_get_string_bb(gl_tex_font_p glf, const char *text, int n, GLfloat *x0, GLfloat *y0, GLfloat *x1, GLfloat *y1) { *x0 = 0.0; *x1 = 0.0; *y0 = 0.0; *y1 = 0.0; if((glf != nullptr) && (glf->ft_face != nullptr)) { uint8_t *nch; uint8_t *nch2; uint8_t *ch = (uint8_t*)text; float x = 0.0; float y = 0.0; float xx0, xx1, yy0, yy1; int i; uint32_t curr_utf32, next_utf32; nch = utf8_to_utf32(ch, &curr_utf32); curr_utf32 = FT_Get_Char_Index(glf->ft_face, curr_utf32); for(i = 0; (*ch != 0) && !((n >= 0) && (i >= n)); i++) { FT_Vector kern; char_info_p g = glf->glyphs + curr_utf32; nch2 = utf8_to_utf32(nch, &next_utf32); next_utf32 = FT_Get_Char_Index(glf->ft_face, next_utf32); ch = nch; nch = nch2; FT_Get_Kerning(glf->ft_face, curr_utf32, next_utf32, FT_KERNING_UNSCALED, &kern); // kern in 1/64 pixel curr_utf32 = next_utf32; xx0 = x + g->left; xx1 = xx0 + g->width; yy0 = y + g->top; yy1 = yy0 - g->height; bbox_add(&xx0, &xx1, &yy0, &yy1, x0, x1, y0, y1); x += static_cast<GLfloat>(kern.x + g->advance_x) / 64.0; y += static_cast<GLfloat>(kern.y + g->advance_y) / 64.0; } } }
static int befs_utf2nls(struct super_block *sb, const char *in, int in_len, char **out, int *out_len) { struct nls_table *nls = BEFS_SB(sb)->nls; int i, o; unicode_t uni; int unilen, utflen; char *result; /* The utf8->nls conversion won't make the final nls string bigger * than the utf one, but if the string is pure ascii they'll have the * same width and an extra char is needed to save the additional \0 */ int maxlen = in_len + 1; befs_debug(sb, "---> utf2nls()"); if (!nls) { befs_error(sb, "befs_utf2nls called with no NLS table loaded"); return -EINVAL; } *out = result = kmalloc(maxlen, GFP_NOFS); if (!*out) { befs_error(sb, "befs_utf2nls() cannot allocate memory"); *out_len = 0; return -ENOMEM; } for (i = o = 0; i < in_len; i += utflen, o += unilen) { /* convert from UTF-8 to Unicode */ utflen = utf8_to_utf32(&in[i], in_len - i, &uni); if (utflen < 0) goto conv_err; /* convert from Unicode to nls */ if (uni > MAX_WCHAR_T) goto conv_err; unilen = nls->uni2char(uni, &result[o], in_len - o); if (unilen < 0) goto conv_err; } result[o] = '\0'; *out_len = o; befs_debug(sb, "<--- utf2nls()"); return o; conv_err: befs_error(sb, "Name using character set %s contains a character that " "cannot be converted to unicode.", nls->charset); befs_debug(sb, "<--- utf2nls()"); kfree(result); return -EILSEQ; }
ssize_t encoder_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { struct encoder_dev *dev = filp->private_data; int quantum = dev->quantum; int s_pos, q_pos; ssize_t retval = 0; if (down_interruptible(&dev->sem)) return -ERESTARTSYS; if (*f_pos >= dev->size) goto out; if (*f_pos + count > dev->size) count = dev->size - *f_pos; s_pos = (long) *f_pos / quantum; q_pos = (long) *f_pos % quantum; if (dev->data == NULL || ! dev->data[s_pos]) goto out; if (count > quantum - q_pos) count = quantum - q_pos; char* decoded_new_data; /* read only up to the end of this quantum */ switch(current_output_encoding){ case ENC_UTF8: /*do nothing*/ break; case ENC_UTF16: count = utf8_to_utf16(dev->data[s_pos] + q_pos, count, decoded_new_data); break; case ENC_UTF32: count = utf8_to_utf32(dev->data[s_pos] + q_pos, count, decoded_new_data); break; case ENC_88591: count = utf8_to_iso88591(dev->data[s_pos] + q_pos, count, decoded_new_data); break; case ENC_88599: count = utf8_to_iso88599(dev->data[s_pos] + q_pos, count, decoded_new_data); break; } if (copy_to_user(buf, decoded_new_data, count)) { retval = -EFAULT; goto out; } *f_pos += count; retval = count; out: up(&dev->sem); return retval; }
void glf_get_string_bb(gl_tex_font_p glf, const char *text, int n, int32_t *x0, int32_t *y0, int32_t *x1, int32_t *y1) { uint8_t *ch = (uint8_t*)text; *x0 = 0; *x1 = 0; *y0 = 0; *y1 = 0; if(glf && glf->ft_face && *ch) { FT_Vector kern; int32_t x_pt = 0; int32_t y_pt = 0; int32_t xx0, xx1, yy0, yy1; uint32_t curr_utf32, next_utf32; ch = utf8_to_utf32(ch, &curr_utf32); curr_utf32 = FT_Get_Char_Index(glf->ft_face, curr_utf32); for(int i = 0; (n < 0) || (i < n); i++) { char_info_p g = glf->glyphs + curr_utf32; n = (*ch) ? (n) : (0); ch = utf8_to_utf32(ch, &next_utf32); next_utf32 = FT_Get_Char_Index(glf->ft_face, next_utf32); FT_Get_Kerning(glf->ft_face, curr_utf32, next_utf32, FT_KERNING_UNSCALED, &kern); // kern in 1/64 pixel curr_utf32 = next_utf32; xx0 = x_pt + g->left * 64; xx1 = xx0 + g->width * 64; yy0 = y_pt + g->top * 64; yy1 = yy0 - g->height * 64; bbox_add(&xx0, &xx1, &yy0, &yy1, x0, x1, y0, y1); x_pt += kern.x + g->advance_x_pt; y_pt += kern.y + g->advance_y_pt; } } }
static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni) { int n; unicode_t u; n = utf8_to_utf32(rawstring, boundlen, &u); if (n < 0 || u > MAX_WCHAR_T) { *uni = 0x003f; /* ? */ return -EINVAL; } *uni = (wchar_t) u; return n; }
/* * utf-8文字列の文字数を返す */ int utf8_chars(const char *mbs) { int count; int mblen; count = 0; while (*mbs != '\0') { mblen = utf8_to_utf32(mbs, NULL); if (mblen == -1) return -1; count++; mbs += mblen; } return count; }
//------------------------------------------------------------------------------------ // получаем размер строки //------------------------------------------------------------------------------------ int vw_FontSize(const char *Text, ...) { if (Text == 0) return 0; // смотрим значения параметров в строке char text[1024]; va_list ap; va_start(ap, Text); vsprintf(text, Text, ap); va_end(ap); // в text уже полная строка if (strlen(text) == 0) return 0; const char *textdraw = text; // сразу определяем "базовую" ширину пробела if (vw_FindFontCharByUTF32(0x020) == 0) vw_LoadFontChar(0x020); float SpaceWidth = vw_FindFontCharByUTF32(0x020)->AdvanceX; // чтобы было более читаемо - делаем пробел не менее 2/3 ширины if (SpaceWidth < (InternalFontSize * 0.65f)) SpaceWidth = InternalFontSize * 0.65f; float LineWidth = 0; while (strlen(textdraw) > 0) { unsigned UTF32; // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке textdraw = utf8_to_utf32(textdraw, &UTF32); // находим наш текущий символ eFontChar* DrawChar = vw_FindFontCharByUTF32(UTF32); if (DrawChar == 0) DrawChar = vw_LoadFontChar(UTF32); // считаем кол-во пробелов if (UTF32 == 0x020) LineWidth += SpaceWidth; else LineWidth += DrawChar->AdvanceX; } return (int)LineWidth; }
/* * utf-8文字列を描画した際の幅を取得する */ int get_utf8_width(const char *mbs) { uint32_t c; int mblen, w; /* 1文字ずつ描画する */ w = 0; c = 0; /* warning avoidance on gcc 5.3.1 */ while (*mbs != '\0') { /* 文字を取得する */ mblen = utf8_to_utf32(mbs, &c); if (mblen == -1) return -1; /* 幅を取得する */ w += get_glyph_width(c); /* 次の文字へ移動する */ mbs += mblen; } return w; }
Tree::Expr ConsDefWS::group(const std::list<EquationDefinition>& defs) { if (defs.size() != 1) { throw "too many definitions"; } auto& cons = get<Parser::ConstructorDecl>(*defs.front().parsed()); Tree::TupleExpr::TuplePairs pairs { {Tree::DimensionExpr{DIM_TYPE}, cons.type}, {Tree::DimensionExpr{DIM_CONS}, cons.name} }; std::map<u32string, dimension_index> rewrites; std::vector<dimension_index> dims; for (size_t i = 0; i != cons.args.size(); ++i) { std::ostringstream argos; argos << "arg" << i; pairs.push_back(std::make_pair( Tree::DimensionExpr(utf8_to_utf32(argos.str())), Tree::IdentExpr(cons.args[i]) )); auto dim = m_system.nextHiddenDim(); dims.push_back(dim); rewrites.insert({cons.args[i], dim}); } Tree::Expr guard = fixupGuardArgs(cons.guard, rewrites); Tree::ConditionalBestfitExpr cond; cond.declarations.push_back(std::make_tuple ( defs.front().start(), guard, Tree::Expr(), Tree::TupleExpr{pairs} )); Tree::Expr abstractions = cond; auto dimIter = dims.rbegin(); for (auto argsIter = cons.args.rbegin(); argsIter != cons.args.rend(); ++argsIter, ++dimIter) { auto base = Tree::BaseAbstractionExpr(*argsIter, abstractions); base.dims.push_back(*dimIter); abstractions = std::move(base); } return abstractions; }
void String8::getUtf32(char32_t* dst) const { utf8_to_utf32(mString, length(), dst); }
void glf_render_str(gl_tex_font_p glf, GLfloat x, GLfloat y, const char *text) { uint8_t *nch; uint8_t *ch = (uint8_t*)text; FT_Vector kern; if((glf == nullptr) || (glf->ft_face == nullptr) || (text == nullptr) || (text[0] == '\0')) { return; } FontBuffer_Bind(); if(glf->gl_real_tex_indexes_count == 1) { GLfloat *p = FontBuffer_ResizeAndMap(48 * utf8_strlen(text) * sizeof(GLfloat)); GLuint elements_count = 0; uint32_t curr_utf32, next_utf32; nch = utf8_to_utf32(ch, &curr_utf32); curr_utf32 = FT_Get_Char_Index(glf->ft_face, curr_utf32); while(*ch) { char_info_p g; uint8_t *nch2 = utf8_to_utf32(nch, &next_utf32); next_utf32 = FT_Get_Char_Index(glf->ft_face, next_utf32); ch = nch; nch = nch2; g = glf->glyphs + curr_utf32; FT_Get_Kerning(glf->ft_face, curr_utf32, next_utf32, FT_KERNING_UNSCALED, &kern); // kern in 1/64 pixel curr_utf32 = next_utf32; if(g->tex_index != 0) { GLfloat x0 = x + g->left; GLfloat x1 = x0 + g->width; GLfloat y0 = y + g->top; GLfloat y1 = y0 - g->height; *p = x0; p++; *p = y0; p++; *p = g->tex_x0; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y0; p++; *p = g->tex_x1; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y1; p++; *p = g->tex_x1; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); p += 4; elements_count++; *p = x0; p++; *p = y0; p++; *p = g->tex_x0; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y1; p++; *p = g->tex_x1; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x0; p++; *p = y1; p++; *p = g->tex_x0; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); p += 4; elements_count++; } x += static_cast<GLfloat>(kern.x + g->advance_x) / 64.0; y += static_cast<GLfloat>(kern.y + g->advance_y) / 64.0; } FontBuffer_Unmap(); ///RENDER if(elements_count != 0) { glBindTexture(GL_TEXTURE_2D, glf->gl_tex_indexes[0]); glDrawArrays(GL_TRIANGLES, 0, elements_count * 3); } } else { GLuint active_texture = 0; uint32_t curr_utf32, next_utf32; nch = utf8_to_utf32(ch, &curr_utf32); curr_utf32 = FT_Get_Char_Index(glf->ft_face, curr_utf32); for(; *ch;) { GLfloat *p = FontBuffer_ResizeAndMap(sizeof(GLfloat[32])); char_info_p g; uint8_t *nch2 = utf8_to_utf32(nch, &next_utf32); next_utf32 = FT_Get_Char_Index(glf->ft_face, next_utf32); ch = nch; nch = nch2; g = glf->glyphs + curr_utf32; FT_Get_Kerning(glf->ft_face, curr_utf32, next_utf32, FT_KERNING_UNSCALED, &kern); // kern in 1/64 pixel curr_utf32 = next_utf32; if(g->tex_index != 0) { if(active_texture != g->tex_index) { glBindTexture(GL_TEXTURE_2D, g->tex_index); active_texture = g->tex_index; } ///RENDER GLfloat x0 = x + g->left; GLfloat x1 = x0 + g->width; GLfloat y0 = y + g->top; GLfloat y1 = y0 - g->height; *p = x0; p++; *p = y0; p++; *p = g->tex_x0; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y0; p++; *p = g->tex_x1; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y1; p++; *p = g->tex_x1; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x0; p++; *p = y1; p++; *p = g->tex_x0; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); FontBuffer_Unmap(); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } x += static_cast<GLfloat>(kern.x + g->advance_x) / 64.0; y += static_cast<GLfloat>(kern.y + g->advance_y) / 64.0; } } }
//-----------------------------------------------------------------// inline lstring utf8_to_utf32(const std::string& src) noexcept { lstring dst; utf8_to_utf32(src, dst); return dst; }
//----------------------------------------------------------------------------- // делаем генерацию нужных символов по списку генерируя одну текстуру //----------------------------------------------------------------------------- void vw_GenerateFontChars(int FontTextureWidth, int FontTextureHeight, const char * CharsList) { printf("Font characters generation start.\n"); // будем использовать последовательность как имя текстуры const char *TextureName = CharsList; // временный массив BYTE * DIB; DIB = new BYTE[FontTextureWidth*FontTextureHeight*4]; // всегда делаем rgba // устанавливаем 0 везде, чтобы потом не краcить rgb, а только формировать альфу memset(DIB, 0, FontTextureWidth*FontTextureHeight*4); // данные для работы с вклеиванием в текстуру int CurrentDIBX = 0; int CurrentDIBY = 0; int EdgingSpace = 2; int MaxHeightInCurrentLine = 0; // первый проход, формируем одну большую текстуру const char *CharsList2 = CharsList; while (strlen(CharsList) > 0) { unsigned CurrentChar; // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке CharsList = utf8_to_utf32(CharsList, &CurrentChar); // загрузка глифа нужного нам символа if (FT_Load_Char( InternalFace, CurrentChar, FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT)) { fprintf(stderr, "Can't load Char: %u\n", CurrentChar); return; } // создаем структуру FontChar eFontChar* NewChar; NewChar = new eFontChar; NewChar->UTF32 = CurrentChar; NewChar->CharTexture = 0; NewChar->TexturePositionLeft = 0; NewChar->TexturePositionRight = 0; NewChar->TexturePositionTop = 0; NewChar->TexturePositionBottom = 0; NewChar->Width = InternalFace->glyph->bitmap.width; NewChar->Height = InternalFace->glyph->bitmap.rows; NewChar->Left = InternalFace->glyph->bitmap_left; NewChar->Top = InternalFace->glyph->bitmap_top; NewChar->AdvanceX = InternalFace->glyph->advance.x / 64.0f; NewChar->Prev = 0; NewChar->Next = 0; // делаем установку параметров для вклеивания // если в текущую строку символов уже не можем вписывать - смещаемся на новую, ниже if (CurrentDIBX + NewChar->Width > FontTextureWidth) { CurrentDIBX = 0; CurrentDIBY += MaxHeightInCurrentLine + EdgingSpace; MaxHeightInCurrentLine = 0; } // если в текущую строку не влазит уже по высоте - значит это фейл... кричим чтоб дали больше текстуру if (CurrentDIBY + NewChar->Height > FontTextureHeight) { fprintf(stderr, "!!! Can't generate all font chars in one texture. Too many chars or too small texture size!\n"); delete NewChar; break; } // "вклеиваем" новый символ в массив BYTE ColorRGB[3]={255,255,255}; for (int j=0; j<NewChar->Height; j++) for (int i=0; i<NewChar->Width; i++) { memcpy(DIB + (FontTextureHeight-CurrentDIBY-j-1)*FontTextureWidth*4 + (CurrentDIBX+i)*4, ColorRGB, 3); memcpy(DIB + (FontTextureHeight-CurrentDIBY-j-1)*FontTextureWidth*4 + (CurrentDIBX+i)*4 + 3, InternalFace->glyph->bitmap.buffer+j*NewChar->Width+i, 1); } // устанавливаем параметры текстуры для прорисовки нашему символу NewChar->TexturePositionLeft = CurrentDIBX; NewChar->TexturePositionRight = CurrentDIBX + NewChar->Width; NewChar->TexturePositionTop = CurrentDIBY; NewChar->TexturePositionBottom = CurrentDIBY + NewChar->Height; // выбираем наибольшую высоту символов if (MaxHeightInCurrentLine < NewChar->Height) MaxHeightInCurrentLine = NewChar->Height; // смещаем указатель CurrentDIBX += NewChar->Width + EdgingSpace; // подключаем к менеджеру vw_AttachFontChar(NewChar); } ///////////////////////////////// /* // выводим в bmp файл сгенерированный DIB, если нужно проверить SDL_Surface *temp; temp = SDL_CreateRGBSurface(SDL_SWSURFACE, FontTextureWidth, FontTextureHeight, 32, #if SDL_BYTEORDER == SDL_LIL_ENDIAN 0x000000FF, 0x0000FF00, 0x00FF0000, 0 #else 0x00FF0000, 0x0000FF00, 0x000000FF, 0 #endif ); memcpy(temp->pixels, DIB, FontTextureWidth*FontTextureHeight*4); SDL_SaveBMP(temp, "fontgenerationtest.bmp"); SDL_FreeSurface(temp); */ ///////////////////////////////// // создаем текстуру vw_SetTextureProp(RI_MAGFILTER_LINEAR | RI_MINFILTER_LINEAR | RI_MIPFILTER_NONE, RI_CLAMP_TO_EDGE, true, TX_ALPHA_GREYSC, false); eTexture* FontTexture = vw_CreateTextureFromMemory(TextureName, DIB, FontTextureWidth, FontTextureHeight, 4, false); // освобождаем память delete [] DIB; if (FontTexture == 0) { fprintf(stderr, "Can't create font texture.\n"); return; } // второй проход, всем FontChars из списка, присваиваем сгенерированную текстуру while (strlen(CharsList2) > 0) { unsigned CurrentChar; // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке CharsList2 = utf8_to_utf32(CharsList2, &CurrentChar); // ставим нашу общую текстуру eFontChar* TMPChar = vw_FindFontCharByUTF32(CurrentChar); if (TMPChar != 0) TMPChar->CharTexture = FontTexture; } printf("Font characters generation end.\n\n"); }
// ------------------------------------------------------------- load_glyph --- texture_glyph_t * load_glyph( const char * filename, const char* charcode, const float highres_size, const float lowres_size, const float padding ) { size_t i, j; FT_Library library; FT_Face face; FT_Init_FreeType( &library ); FT_New_Face( library, filename, 0, &face ); FT_Select_Charmap( face, FT_ENCODING_UNICODE ); FT_UInt glyph_index = FT_Get_Char_Index( face, utf8_to_utf32( charcode ) ); // Render glyph at high resolution (highres_size points) FT_Set_Char_Size( face, highres_size*64, 0, 72, 72 ); FT_Load_Glyph( face, glyph_index, FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT); FT_GlyphSlot slot = face->glyph; FT_Bitmap bitmap = slot->bitmap; // Allocate high resolution buffer size_t highres_width = bitmap.width + 2*padding*highres_size; size_t highres_height = bitmap.rows + 2*padding*highres_size; double * highres_data = (double *) malloc( highres_width*highres_height*sizeof(double) ); memset( highres_data, 0, highres_width*highres_height*sizeof(double) ); // Copy high resolution bitmap with padding and normalize values for( j=0; j < bitmap.rows; ++j ) { for( i=0; i < bitmap.width; ++i ) { int x = i + padding; int y = j + padding; highres_data[y*highres_width+x] = bitmap.buffer[j*bitmap.width+i]/255.0; } } // Compute distance map highres_data = make_distance_mapd( highres_data, highres_width, highres_height ); // Allocate low resolution buffer size_t lowres_width = round(highres_width * lowres_size/highres_size); size_t lowres_height = round(highres_height * lowres_width/(float) highres_width); double * lowres_data = (double *) malloc( lowres_width*lowres_height*sizeof(double) ); memset( lowres_data, 0, lowres_width*lowres_height*sizeof(double) ); // Scale down highres buffer into lowres buffer resize( highres_data, highres_width, highres_height, lowres_data, lowres_width, lowres_height ); // Convert the (double *) lowres buffer into a (unsigned char *) buffer and // rescale values between 0 and 255. unsigned char * data = (unsigned char *) malloc( lowres_width*lowres_height*sizeof(unsigned char) ); for( j=0; j < lowres_height; ++j ) { for( i=0; i < lowres_width; ++i ) { double v = lowres_data[j*lowres_width+i]; data[j*lowres_width+i] = (int) (255*(1-v)); } } // Compute new glyph information from highres value float ratio = lowres_size / highres_size; size_t pitch = lowres_width * sizeof( unsigned char ); // Create glyph texture_glyph_t * glyph = texture_glyph_new( ); glyph->offset_x = (slot->bitmap_left + padding*highres_width) * ratio; glyph->offset_y = (slot->bitmap_top + padding*highres_height) * ratio; glyph->width = lowres_width; glyph->height = lowres_height; glyph->charcode = utf8_to_utf32( charcode ); /* printf( "Glyph width: %ld\n", glyph->width ); printf( "Glyph height: %ld\n", glyph->height ); printf( "Glyph offset x: %d\n", glyph->offset_x ); printf( "Glyph offset y: %d\n", glyph->offset_y ); */ ivec4 region = texture_atlas_get_region( atlas, glyph->width, glyph->height ); /* printf( "Region x : %d\n", region.x ); printf( "Region y : %d\n", region.y ); printf( "Region width : %d\n", region.width ); printf( "Region height : %d\n", region.height ); */ texture_atlas_set_region( atlas, region.x, region.y, glyph->width, glyph->height, data, pitch ); glyph->s0 = region.x/(float)atlas->width; glyph->t0 = region.y/(float)atlas->height; glyph->s1 = (region.x + glyph->width)/(float)atlas->width; glyph->t1 = (region.y + glyph->height)/(float)atlas->height; FT_Load_Glyph( face, glyph_index, FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT); glyph->advance_x = ratio * face->glyph->advance.x/64.0; glyph->advance_y = ratio * face->glyph->advance.y/64.0; /* printf( "Advance x : %f\n", glyph->advance_x ); printf( "Advance y : %f\n", glyph->advance_y ); */ free( highres_data ); free( lowres_data ); free( data ); return glyph; }
//----------------------------------------------------------------------------- // делаем генерацию нужных символов по списку генерируя одну текстуру //----------------------------------------------------------------------------- void vw_GenerateFontChars(int FontTextureWidth, int FontTextureHeight, const char * CharsList) { printf("Font characters generation start.\n"); // будем использовать последовательность как имя текстуры const char *TextureName = CharsList; // временный массив BYTE * DIB; DIB = new BYTE[FontTextureWidth*FontTextureHeight*4]; // всегда делаем rgba // устанавливаем 0 везде, чтобы потом не краcить rgb, а только формировать альфу memset(DIB, 0, FontTextureWidth*FontTextureHeight*4); // данные для работы с вклеиванием в текстуру int CurrentDIBX = 0; int CurrentDIBY = 0; int EdgingSpace = 2; int MaxHeightInCurrentLine = 0; // устанавливаем размеры if (FT_Set_Char_Size( InternalFace, InternalFontSize <<6, InternalFontSize <<6, 96, 96 )) { fprintf(stderr, "Can't set char size %i.", InternalFontSize); return; } // первый проход, формируем одну большую текстуру const char *CharsList2 = CharsList; while (strlen(CharsList) > 0) { unsigned CurrentChar; // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке CharsList = utf8_to_utf32(CharsList, &CurrentChar); // загрузка глифа нужного нам символа if (FT_Load_Char( InternalFace, CurrentChar, FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT)) { fprintf(stderr, "Can't load Char: %u\n", CurrentChar); return; } // создаем структуру FontChar eFontChar* NewChar; NewChar = new eFontChar; NewChar->UTF32 = CurrentChar; NewChar->CharTexture = 0; NewChar->FontSize = InternalFontSize; NewChar->TexturePositionLeft = 0; NewChar->TexturePositionRight = 0; NewChar->TexturePositionTop = 0; NewChar->TexturePositionBottom = 0; NewChar->Width = InternalFace->glyph->bitmap.width; NewChar->Height = InternalFace->glyph->bitmap.rows; NewChar->Left = InternalFace->glyph->bitmap_left; NewChar->Top = InternalFace->glyph->bitmap_top; NewChar->AdvanceX = InternalFace->glyph->advance.x / 64.0f; NewChar->Prev = 0; NewChar->Next = 0; // делаем установку параметров для вклеивания // если в текущую строку символов уже не можем вписывать - смещаемся на новую, ниже if (CurrentDIBX + NewChar->Width > FontTextureWidth) { CurrentDIBX = 0; CurrentDIBY += MaxHeightInCurrentLine + EdgingSpace; MaxHeightInCurrentLine = 0; } // если в текущую строку не влазит уже по высоте - значит это фейл... кричим чтоб дали больше текстуру if (CurrentDIBY + NewChar->Height > FontTextureHeight) { fprintf(stderr, "!!! Can't generate all font chars in one texture. Too many chars or too small texture size!\n"); delete NewChar; break; } // "вклеиваем" новый символ в массив BYTE ColorRGB[3]={255,255,255}; for (int j=0; j<NewChar->Height; j++) for (int i=0; i<NewChar->Width; i++) { memcpy(DIB + (FontTextureHeight-CurrentDIBY-j-1)*FontTextureWidth*4 + (CurrentDIBX+i)*4, ColorRGB, 3); memcpy(DIB + (FontTextureHeight-CurrentDIBY-j-1)*FontTextureWidth*4 + (CurrentDIBX+i)*4 + 3, InternalFace->glyph->bitmap.buffer+j*NewChar->Width+i, 1); } // устанавливаем параметры текстуры для прорисовки нашему символу NewChar->TexturePositionLeft = CurrentDIBX; NewChar->TexturePositionRight = CurrentDIBX + NewChar->Width; NewChar->TexturePositionTop = CurrentDIBY; NewChar->TexturePositionBottom = CurrentDIBY + NewChar->Height; // выбираем наибольшую высоту символов if (MaxHeightInCurrentLine < NewChar->Height) MaxHeightInCurrentLine = NewChar->Height; // смещаем указатель CurrentDIBX += NewChar->Width + EdgingSpace; // подключаем к менеджеру vw_AttachFontChar(NewChar); } ///////////////////////////////// /* // выводим в tga файл сгенерированный DIB, если нужно проверить SDL_RWops *TgaFile = SDL_RWFromFile("fontgenerationtest.tga", "wb"); if (TgaFile == NULL) { fprintf(stderr, "Can't open VFS file for write.\n"); return; } unsigned char UselessChar = 0; // used for useless char. short int UselessInt = 0; // used for useless int. unsigned char ImageType = 2; // Type of image we are saving. unsigned char ImageBits = 32; // Bit depth. short int ImageWidth = (short int)FontTextureWidth; short int ImageHeight = (short int)FontTextureHeight; // пишем неиспользуемые данные SDL_RWwrite(TgaFile, &UselessChar, sizeof(unsigned char), 1); SDL_RWwrite(TgaFile, &UselessChar, sizeof(unsigned char), 1); // тип картинки SDL_RWwrite(TgaFile, &ImageType, sizeof(unsigned char), 1); // пишем неиспользуемые данные SDL_RWwrite(TgaFile, &UselessInt, sizeof(short int), 1); SDL_RWwrite(TgaFile, &UselessInt, sizeof(short int), 1); SDL_RWwrite(TgaFile, &UselessChar, sizeof(unsigned char), 1); SDL_RWwrite(TgaFile, &UselessInt, sizeof(short int), 1); SDL_RWwrite(TgaFile, &UselessInt, sizeof(short int), 1); // записываем параметры картинки SDL_RWwrite(TgaFile, &ImageWidth, sizeof(short int), 1); SDL_RWwrite(TgaFile, &ImageHeight, sizeof(short int), 1); SDL_RWwrite(TgaFile, &ImageBits, sizeof(unsigned char), 1); // пишем неиспользуемые данные SDL_RWwrite(TgaFile, &UselessChar, sizeof(unsigned char), 1); // пишем данные диб массива SDL_RWwrite(TgaFile, DIB, FontTextureWidth*FontTextureHeight*4, 1); // закрываем файл SDL_RWclose(TgaFile); */ ///////////////////////////////// // создаем текстуру vw_SetTextureProp(RI_MAGFILTER_LINEAR | RI_MINFILTER_LINEAR | RI_MIPFILTER_NONE, RI_CLAMP_TO_EDGE, true, TX_ALPHA_GREYSC, false); eTexture* FontTexture = vw_CreateTextureFromMemory(TextureName, DIB, FontTextureWidth, FontTextureHeight, 4, false); // освобождаем память delete [] DIB; if (FontTexture == 0) { fprintf(stderr, "Can't create font texture.\n"); return; } // второй проход, всем FontChars из списка, присваиваем сгенерированную текстуру while (strlen(CharsList2) > 0) { unsigned CurrentChar; // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке CharsList2 = utf8_to_utf32(CharsList2, &CurrentChar); // ставим нашу общую текстуру eFontChar* TMPChar = vw_FindFontCharByUTF32(CurrentChar); if (TMPChar != 0) TMPChar->CharTexture = FontTexture; } printf("Font characters generation end.\n\n"); }
static utf32_string utf(utf8_char const* str, size_t size) { return utf8_to_utf32(str, size); }
std::pair<bool, u32string> build_escaped_characters ( Iterator& current, const Iterator& end ) { std::string building; bool error = false; int to_read = 0; while (*current == '\\' && error == false) { ++current; char32_t c = *current; switch(c) { case 'U': to_read = 8; ++current; break; case 'u': to_read = 4; ++current; break; case 'x': to_read = 2; ++current; break; case 'n': building += "\n"; ++current; break; case 'r': building += "\r"; ++current; break; case 't': building += "\t"; ++current; break; case '\'': building += "\'"; ++current; break; case '\"': building += "\""; ++current; break; case '\\': building += "\\"; ++current; break; default: //invalid control character error = true; break; } //read the requested number of characters std::string chars; if (to_read > 0) { while (to_read > 0 && current != end && *current != '\'') { c = *current; if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) { chars += c; } else { break; } --to_read; ++current; } } //if we didn't read everything then error if (to_read != 0) { error = true; } else { uint32_t value = 0; for (char c : chars) { if (c >= '0' && c <= '9') { value = value * 16 + (c - '0'); } else { value = value * 16 + (c - 'A' + 10); } } //it was a byte if it was two characters, otherwise it was a whole //character if (chars.length() == 2) { building += char(value & 0xFF); } else { building += utf32_to_utf8(u32string(1, value)); } } } u32string u32result = utf8_to_utf32(building); return std::make_pair(!error, u32result); }
/* * Convert 16 bit Unicode pathname to wire format from string in current code * page. Conversion may involve remapping up the six characters that are * only legal in POSIX-like OS (if they are present in the string). Path * names are little endian 16 bit Unicode on the wire */ int cifsConvertToUTF16(__le16 *target, const char *source, int srclen, const struct nls_table *cp, int map_chars) { int i, charlen; int j = 0; char src_char; __le16 dst_char; wchar_t tmp; wchar_t *wchar_to; /* UTF-16 */ int ret; unicode_t u; if (map_chars == NO_MAP_UNI_RSVD) return cifs_strtoUTF16(target, source, PATH_MAX, cp); wchar_to = kzalloc(6, GFP_KERNEL); for (i = 0; i < srclen; j++) { src_char = source[i]; charlen = 1; /* check if end of string */ if (src_char == 0) goto ctoUTF16_out; /* see if we must remap this char */ if (map_chars == SFU_MAP_UNI_RSVD) dst_char = convert_to_sfu_char(src_char); else if (map_chars == SFM_MAP_UNI_RSVD) { bool end_of_string; if (i == srclen - 1) end_of_string = true; else end_of_string = false; dst_char = convert_to_sfm_char(src_char, end_of_string); } else dst_char = 0; /* * FIXME: We can not handle remapping backslash (UNI_SLASH) * until all the calls to build_path_from_dentry are modified, * as they use backslash as separator. */ if (dst_char == 0) { charlen = cp->char2uni(source + i, srclen - i, &tmp); dst_char = cpu_to_le16(tmp); /* * if no match, use question mark, which at least in * some cases serves as wild card */ if (charlen > 0) goto ctoUTF16; /* convert SURROGATE_PAIR */ if (strcmp(cp->charset, "utf8") || !wchar_to) goto unknown; if (*(source + i) & 0x80) { charlen = utf8_to_utf32(source + i, 6, &u); if (charlen < 0) goto unknown; } else goto unknown; ret = utf8s_to_utf16s(source + i, charlen, UTF16_LITTLE_ENDIAN, wchar_to, 6); if (ret < 0) goto unknown; i += charlen; dst_char = cpu_to_le16(*wchar_to); if (charlen <= 3) /* 1-3bytes UTF-8 to 2bytes UTF-16 */ put_unaligned(dst_char, &target[j]); else if (charlen == 4) { /* 4bytes UTF-8(surrogate pair) to 4bytes UTF-16 * 7-8bytes UTF-8(IVS) divided to 2 UTF-16 * (charlen=3+4 or 4+4) */ put_unaligned(dst_char, &target[j]); dst_char = cpu_to_le16(*(wchar_to + 1)); j++; put_unaligned(dst_char, &target[j]); } else if (charlen >= 5) { /* 5-6bytes UTF-8 to 6bytes UTF-16 */ put_unaligned(dst_char, &target[j]); dst_char = cpu_to_le16(*(wchar_to + 1)); j++; put_unaligned(dst_char, &target[j]); dst_char = cpu_to_le16(*(wchar_to + 2)); j++; put_unaligned(dst_char, &target[j]); } continue; unknown: dst_char = cpu_to_le16(0x003f); charlen = 1; } ctoUTF16: /* * character may take more than one byte in the source string, * but will take exactly two bytes in the target string */ i += charlen; put_unaligned(dst_char, &target[j]); } ctoUTF16_out: put_unaligned(0, &target[j]); /* Null terminate target unicode string */ kfree(wchar_to); return j; }
//------------------------------------------------------------------------------------ // прорисовка фонта //------------------------------------------------------------------------------------ void vw_DrawFont(int X, int Y, float FlattenWidth, float MaxWidth, float FontScale, float R, float G, float B, float Transp, const char *Text, ...) { if (Text == 0) return; // учитываем аспект рейшен float AW; float AH; bool ASpresent=false; ASpresent = vw_GetAspectWH(&AW, &AH); // получаем данные текущего вьюпорта int W, H; vw_GetViewport(0, 0, &W, &H); float AHw = H*1.0f; // если текст ниже чем ширина нашего окна - не рисуем if (ASpresent){ if (Y > AH) return;} else {if (Y > H) return;} // если текст выше чем ноль - тоже рисовать его смысла нет if (Y+InternalFontSize*FontScale < 0) return; // FlattenWidth - выравнивать по ширине // если FlattenWidth отрицателен, выравниваем по значению, "сжимая" буквы, если нужно // MaxWidth - рисовать до ширины // смотрим значения параметров в строке char text[1024]; va_list ap; va_start(ap, Text); vsprintf(text, Text, ap); va_end(ap); // в text уже полная строка if (strlen(text) == 0) return; float Xstart = X; // сразу определяем "базовую" ширину пробела, чтобы учитывать в расчетах if (vw_FindFontCharByUTF32(0x020) == 0) vw_LoadFontChar(0x020); float SpaceWidth = vw_FindFontCharByUTF32(0x020)->AdvanceX*FontScale; // чтобы было более читаемо - делаем пробел не менее 2/3 ширины if (SpaceWidth < (InternalFontSize * 0.65f)) SpaceWidth = InternalFontSize * 0.65f; // коэф. изменения букв по ширине float FontWidthScale = 1.0f; if (Transp >= 1.0f) Transp = 1.0f; // если нужно выравнивать, считаем данные пробелов if (FlattenWidth > 0) { float LineWidth = 0; int SpaceCount = 0; const char *CountCheck = text; while (strlen(CountCheck) > 0) { unsigned UTF32; // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке CountCheck = utf8_to_utf32(CountCheck, &UTF32); // находим наш текущий символ eFontChar* DrawChar = vw_FindFontCharByUTF32(UTF32); if (DrawChar == 0) DrawChar = vw_LoadFontChar(UTF32); // считаем кол-во пробелов if (UTF32 == 0x020) SpaceCount++; else LineWidth += DrawChar->AdvanceX; } if (FlattenWidth > LineWidth) if (SpaceCount!=0) SpaceWidth = (FlattenWidth - LineWidth)/SpaceCount; } // если нужно сжать, считаем коэф. сжатия букв if (FlattenWidth < 0) { float LineWidth = 0; const char *CountCheck = text; while (strlen(CountCheck) > 0) { unsigned UTF32; // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке CountCheck = utf8_to_utf32(CountCheck, &UTF32); // находим наш текущий символ eFontChar* DrawChar = vw_FindFontCharByUTF32(UTF32); if (DrawChar == 0) DrawChar = vw_LoadFontChar(UTF32); // считаем длину символов с пробелами if (UTF32 != 0x020) LineWidth += DrawChar->AdvanceX; else LineWidth += SpaceWidth; } if (FlattenWidth*(-1.0f) < LineWidth) FontWidthScale = FlattenWidth/LineWidth*(-1.0f); } float LineWidth = 0; // установка свойств текстуры vw_SetTextureBlend(true, RI_BLEND_SRCALPHA, RI_BLEND_INVSRCALPHA); // ставим цвет vw_SetColor(R, G, B, Transp); // для отрисовки eTexture* CurrentTexture = 0; int k=0; // буфер для последовательности RI_QUADS // войдет RI_2f_XYZ | RI_2f_TEX #ifdef USE_GLES float tmp[(2+2)*6*strlen(text)]; #else float tmp[(2+2)*4*strlen(text)]; #endif // чтобы меньше делать операций умножения, включаем коэф. один в другой сразу для ширины символов FontWidthScale = FontScale*FontWidthScale; // прорисовка текста const char *textdraw = text; // прорисовываем все символы while (strlen(textdraw) > 0) { unsigned UTF32; // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке textdraw = utf8_to_utf32(textdraw, &UTF32); // находим наш текущий символ eFontChar* DrawChar = vw_FindFontCharByUTF32(UTF32); if (DrawChar == 0) DrawChar = vw_LoadFontChar(UTF32); // первый символ - запоминаем его текстуру if (CurrentTexture == 0) CurrentTexture = DrawChar->CharTexture; // проверка на текстуру, если текстура поменялась - отрисовываем все что есть в буфере, если там что-то есть if (CurrentTexture != DrawChar->CharTexture) { // если что-то было в буфере - выводим if (k > 0) { // Установка текстуры vw_SetTexture(0, CurrentTexture); // отрисовываем все что есть в буфере #ifdef USE_GLES vw_SendVertices(RI_QUADS, 6*(k/24), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float)); #else vw_SendVertices(RI_QUADS, 4*(k/16), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float)); #endif } // запоминаем новую текстуру CurrentTexture = DrawChar->CharTexture; // сбрасываем счетчики k=0; } // если не пробел - рисуем if (UTF32 != 0x020) { float DrawX = Xstart + DrawChar->Left*FontWidthScale; float DrawY = Y + GlobalFontOffsetY + (InternalFontSize - DrawChar->Top)*FontScale; // Вычисление поправки по У в зависимости от DrawCorner // - расположения угла начала координат float tmpPosY = 0; // изменяем только в случае RI_UL_CORNER if (ASpresent) tmpPosY = (AH - DrawY - DrawY - DrawChar->Height*FontScale); else tmpPosY = (AHw - DrawY - DrawY - DrawChar->Height*FontScale); float ImageHeight = DrawChar->CharTexture->Height*1.0f; float ImageWidth = DrawChar->CharTexture->Width*1.0f; float FrameHeight = (DrawChar->TexturePositionBottom*1.0f )/ImageHeight; float FrameWidth = (DrawChar->TexturePositionRight*1.0f )/ImageWidth; float Yst = (DrawChar->TexturePositionTop*1.0f)/ImageHeight; float Xst = (DrawChar->TexturePositionLeft*1.0f)/ImageWidth; #ifdef USE_GLES tmp[k++] = DrawX; tmp[k++] = DrawY +tmpPosY + DrawChar->Height*FontScale; tmp[k++] = Xst; tmp[k++] = 1.0f-Yst; tmp[k++] = DrawX; tmp[k++] = DrawY +tmpPosY + DrawChar->Height*FontScale; tmp[k++] = Xst; tmp[k++] = 1.0f-Yst; tmp[k++] = DrawX; tmp[k++] = DrawY +tmpPosY; tmp[k++] = Xst; tmp[k++] = 1.0f-FrameHeight; tmp[k++] = DrawX + DrawChar->Width*FontWidthScale; tmp[k++] = DrawY +tmpPosY + DrawChar->Height*FontScale; tmp[k++] = FrameWidth; tmp[k++] = 1.0f-Yst; tmp[k++] = DrawX + DrawChar->Width*FontWidthScale; tmp[k++] = DrawY +tmpPosY; tmp[k++] = FrameWidth; tmp[k++] = 1.0f-FrameHeight; tmp[k++] = DrawX + DrawChar->Width*FontWidthScale; tmp[k++] = DrawY +tmpPosY; tmp[k++] = FrameWidth; tmp[k++] = 1.0f-FrameHeight; #else tmp[k++] = DrawX; tmp[k++] = DrawY +tmpPosY + DrawChar->Height*FontScale; tmp[k++] = Xst; tmp[k++] = 1.0f-Yst; tmp[k++] = DrawX; tmp[k++] = DrawY +tmpPosY; tmp[k++] = Xst; tmp[k++] = 1.0f-FrameHeight; tmp[k++] = DrawX + DrawChar->Width*FontWidthScale; tmp[k++] = DrawY +tmpPosY; tmp[k++] = FrameWidth; tmp[k++] = 1.0f-FrameHeight; tmp[k++] = DrawX + DrawChar->Width*FontWidthScale; tmp[k++] = DrawY +tmpPosY + DrawChar->Height*FontScale; tmp[k++] = FrameWidth; tmp[k++] = 1.0f-Yst; #endif Xstart += DrawChar->AdvanceX*FontWidthScale; LineWidth += DrawChar->AdvanceX*FontWidthScale; } else { Xstart += SpaceWidth*FontWidthScale; LineWidth += SpaceWidth*FontWidthScale; } // если нужно прорисовывать с ограничением по длине if (MaxWidth != 0.0f) if (LineWidth >= MaxWidth) break; } // если что-то было в буфере - выводим if (k > 0) { // Установка текстуры vw_SetTexture(0, CurrentTexture); // отрисовываем все что есть в буфере #ifdef USE_GLES vw_SendVertices(RI_QUADS, 6*(k/24), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float)); #else vw_SendVertices(RI_QUADS, 4*(k/16), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float)); #endif } vw_SetColor(1.0f, 1.0f, 1.0f, 1.0f); vw_SetTextureBlend(false, 0, 0); vw_BindTexture(0, 0); }
void glf_render_str(gl_tex_font_p glf, GLfloat x, GLfloat y, const char *text, int32_t n_sym) { if(glf && glf->ft_face && text && (text[0] != 0)) { uint8_t *nch, *ch = (uint8_t*)text; FT_Vector kern; int32_t x_pt = 0; int32_t y_pt = 0; if(glf->gl_real_tex_indexes_count == 1) { GLuint elements_count = 0; uint32_t curr_utf32, next_utf32; GLfloat *p, *buffer; buffer = (GLfloat*)malloc(48 * utf8_strlen(text) * sizeof(GLfloat)); nch = utf8_to_utf32(ch, &curr_utf32); curr_utf32 = FT_Get_Char_Index(glf->ft_face, curr_utf32); qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); for(p = buffer; *ch && n_sym--;) { char_info_p g; uint8_t *nch2 = utf8_to_utf32(nch, &next_utf32); next_utf32 = FT_Get_Char_Index(glf->ft_face, next_utf32); ch = nch; nch = nch2; g = glf->glyphs + curr_utf32; FT_Get_Kerning(glf->ft_face, curr_utf32, next_utf32, FT_KERNING_UNSCALED, &kern); // kern in 1/64 pixel curr_utf32 = next_utf32; if(g->tex_index != 0) { GLfloat x0 = x + g->left + x_pt / 64.0f; GLfloat x1 = x0 + g->width; GLfloat y0 = y + g->top + y_pt / 64.0f; GLfloat y1 = y0 - g->height; *p = x0; p++; *p = y0; p++; *p = g->tex_x0; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y0; p++; *p = g->tex_x1; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y1; p++; *p = g->tex_x1; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); p += 4; elements_count++; *p = x0; p++; *p = y0; p++; *p = g->tex_x0; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y1; p++; *p = g->tex_x1; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x0; p++; *p = y1; p++; *p = g->tex_x0; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); p += 4; elements_count++; } x_pt += kern.x + g->advance_x_pt; y_pt += kern.y + g->advance_y_pt; } ///RENDER if(elements_count != 0) { qglBindTexture(GL_TEXTURE_2D, glf->gl_tex_indexes[0]); qglVertexPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), buffer+0); qglTexCoordPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), buffer+2); qglColorPointer(4, GL_FLOAT, 8 * sizeof(GLfloat), buffer+4); qglDrawArrays(GL_TRIANGLES, 0, elements_count * 3); } qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); free(buffer); } else { GLfloat *p, buffer[32]; GLuint active_texture = 0; uint32_t curr_utf32, next_utf32; nch = utf8_to_utf32(ch, &curr_utf32); curr_utf32 = FT_Get_Char_Index(glf->ft_face, curr_utf32); qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); for(; *ch && n_sym--;) { char_info_p g; uint8_t *nch2 = utf8_to_utf32(nch, &next_utf32); next_utf32 = FT_Get_Char_Index(glf->ft_face, next_utf32); ch = nch; nch = nch2; g = glf->glyphs + curr_utf32; FT_Get_Kerning(glf->ft_face, curr_utf32, next_utf32, FT_KERNING_UNSCALED, &kern); // kern in 1/64 pixel curr_utf32 = next_utf32; if(g->tex_index != 0) { ///RENDER GLfloat x0 = x + g->left + x_pt / 64.0f; GLfloat x1 = x0 + g->width; GLfloat y0 = y + g->top + y_pt / 64.0f; GLfloat y1 = y0 - g->height; p = buffer; *p = x0; p++; *p = y0; p++; *p = g->tex_x0; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y0; p++; *p = g->tex_x1; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y1; p++; *p = g->tex_x1; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x0; p++; *p = y1; p++; *p = g->tex_x0; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); if(active_texture != g->tex_index) { qglBindTexture(GL_TEXTURE_2D, g->tex_index); active_texture = g->tex_index; } qglVertexPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), buffer+0); qglTexCoordPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), buffer+2); qglColorPointer(4, GL_FLOAT, 8 * sizeof(GLfloat), buffer+4); qglDrawArrays(GL_TRIANGLE_FAN, 0, 4); } x_pt += kern.x + g->advance_x_pt; y_pt += kern.y + g->advance_y_pt; } } } }
//------------------------------------------------------------------------------------ // прорисовка фонта в 3д пространстве //------------------------------------------------------------------------------------ void vw_DrawFont3D(float X, float Y, float Z, const char *Text, ...) { if (Text == 0) return; // смотрим значения параметров в строке char text[1024]; va_list ap; va_start(ap, Text); vsprintf(text, Text, ap); va_end(ap); // в text уже полная строка if (strlen(text) == 0) return; // прорисовка текста const char *textdraw = text; float Xstart = 0.0f; // сразу определяем "базовую" ширину пробела float SpaceWidth = vw_FindFontCharByUTF32(0x020)->AdvanceX; // чтобы было более читаемо - делаем пробел не менее 2/3 ширины if (SpaceWidth < (InternalFontSize * 0.65f)) SpaceWidth = InternalFontSize * 0.65f; textdraw = text; // для отрисовки eTexture* CurrentTexture = 0; int k=0; // буфер для последовательности RI_QUADS // войдет RI_2f_XY | RI_2f_TEX #ifdef USE_GLES float tmp[(2+2)*6*strlen(textdraw)]; #else float tmp[(2+2)*4*strlen(textdraw)]; #endif // установка свойств текстуры vw_SetTextureBlend(true, RI_BLEND_SRCALPHA, RI_BLEND_INVSRCALPHA); // всегда стаим белый цвет vw_SetColor(1.0f, 1.0f, 1.0f, 1.0f); vw_PushMatrix(); vw_Translate(VECTOR3D(X, Y, Z)); VECTOR3D CurrentCameraRotation; vw_GetCameraRotation(&CurrentCameraRotation); // поворачиваем к камере vw_Rotate(CurrentCameraRotation.y, 0.0f, 1.0f, 0.0f); vw_Rotate(CurrentCameraRotation.x, 1.0f, 0.0f, 0.0f); // прорисовываем все символы while (strlen(textdraw) > 0) { unsigned UTF32; // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке textdraw = utf8_to_utf32(textdraw, &UTF32); // находим наш текущий символ eFontChar* DrawChar = vw_FindFontCharByUTF32(UTF32); if (DrawChar == 0) DrawChar = vw_LoadFontChar(UTF32); // первый символ - запоминаем его текстуру if (CurrentTexture == 0) CurrentTexture = DrawChar->CharTexture; // проверка на текстуру, если текстура поменялась - отрисовываем все что есть в буфере, если там что-то есть if (CurrentTexture != DrawChar->CharTexture) { // если что-то было в буфере - выводим if (k > 0) { // Установка текстуры vw_SetTexture(0, CurrentTexture); // отрисовываем все что есть в буфере vw_SendVertices(RI_QUADS, 4*(k/16), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float)); } // запоминаем новую текстуру CurrentTexture = DrawChar->CharTexture; // сбрасываем счетчики k=0; } // если не пробел - рисуем if (UTF32 != 0x020) { float DrawX = Xstart + DrawChar->Left; float DrawY = InternalFontSize - DrawChar->Top; float ImageHeight = DrawChar->CharTexture->Height*1.0f; float ImageWidth = DrawChar->CharTexture->Width*1.0f; float FrameHeight = (DrawChar->TexturePositionBottom*1.0f )/ImageHeight; float FrameWidth = (DrawChar->TexturePositionRight*1.0f )/ImageWidth; float Yst = (DrawChar->TexturePositionTop*1.0f)/ImageHeight; float Xst = (DrawChar->TexturePositionLeft*1.0f)/ImageWidth; #ifdef USE_GLES tmp[k++] = DrawX/10.0f; tmp[k++] = (DrawY + DrawChar->Height)/10.0f; tmp[k++] = Xst; tmp[k++] = 1.0f-Yst; tmp[k++] = DrawX/10.0f; tmp[k++] = (DrawY + DrawChar->Height)/10.0f; tmp[k++] = Xst; tmp[k++] = 1.0f-Yst; tmp[k++] = DrawX/10.0f; tmp[k++] = DrawY/10.0f; tmp[k++] = Xst; tmp[k++] = 1.0f-FrameHeight; tmp[k++] = (DrawX + DrawChar->Width)/10.0f; tmp[k++] = (DrawY + DrawChar->Height)/10.0f; tmp[k++] = FrameWidth; tmp[k++] = 1.0f-Yst; tmp[k++] = (DrawX + DrawChar->Width)/10.0f; tmp[k++] = DrawY/10.0f; tmp[k++] = FrameWidth; tmp[k++] = 1.0f-FrameHeight; tmp[k++] = (DrawX + DrawChar->Width)/10.0f; tmp[k++] = DrawY/10.0f; tmp[k++] = FrameWidth; tmp[k++] = 1.0f-FrameHeight; #else tmp[k++] = DrawX/10.0f; tmp[k++] = (DrawY + DrawChar->Height)/10.0f; tmp[k++] = Xst; tmp[k++] = 1.0f-Yst; tmp[k++] = DrawX/10.0f; tmp[k++] = DrawY/10.0f; tmp[k++] = Xst; tmp[k++] = 1.0f-FrameHeight; tmp[k++] = (DrawX + DrawChar->Width)/10.0f; tmp[k++] = DrawY/10.0f; tmp[k++] = FrameWidth; tmp[k++] = 1.0f-FrameHeight; tmp[k++] = (DrawX + DrawChar->Width)/10.0f; tmp[k++] = (DrawY + DrawChar->Height)/10.0f; tmp[k++] = FrameWidth; tmp[k++] = 1.0f-Yst; #endif Xstart += DrawChar->AdvanceX; } else { Xstart += SpaceWidth; } } // если что-то было в буфере - выводим if (k > 0) { // Установка текстуры vw_SetTexture(0, CurrentTexture); // отрисовываем все что есть в буфере #ifdef USE_GLES vw_SendVertices(RI_QUADS, 6*(k/16), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float)); #else vw_SendVertices(RI_QUADS, 4*(k/16), RI_2f_XY | RI_1_TEX, tmp, 4*sizeof(float)); #endif } vw_PopMatrix(); vw_SetTextureBlend(false, 0, 0); vw_BindTexture(0, 0); }
size_t String8::getUtf32(char32_t* dst, size_t dst_len) const { return utf8_to_utf32(mString, length(), dst, dst_len); }
int sf_nlscpy(struct sf_glob_info *sf_g, char *name, size_t name_bound_len, const unsigned char *utf8_name, size_t utf8_len) { if (sf_g->nls) { const char *in; char *out; size_t out_len; size_t out_bound_len; size_t in_bound_len; in = utf8_name; in_bound_len = utf8_len; out = name; out_len = 0; out_bound_len = name_bound_len; while (in_bound_len) { int nb; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) unicode_t uni; nb = utf8_to_utf32(in, in_bound_len, &uni); #else linux_wchar_t uni; nb = utf8_mbtowc(&uni, in, in_bound_len); #endif if (nb < 0) { LogFunc(("utf8_mbtowc failed(%s) %x:%d\n", (const char *) utf8_name, *in, in_bound_len)); return -EINVAL; } in += nb; in_bound_len -= nb; nb = sf_g->nls->uni2char(uni, out, out_bound_len); if (nb < 0) { LogFunc(("nls->uni2char failed(%s) %x:%d\n", utf8_name, uni, out_bound_len)); return nb; } out += nb; out_bound_len -= nb; out_len += nb; } *out = 0; } else { if (utf8_len + 1 > name_bound_len) return -ENAMETOOLONG; memcpy(name, utf8_name, utf8_len + 1); } return 0; }
void Button_base::set_label(const std::string &label) { set_label( utf8_to_utf32(label) ); }