void Animation::MirrorAnimationVert() { Video *video = core->GetVideoDriver(); for (size_t i = 0; i < indicesCount; i++) { Sprite2D * tmp = frames[i]; frames[i] = video->MirrorSpriteVertical( tmp, true ); tmp->release(); } // flip animArea vertically as well // animArea.y = -animArea.h - animArea.y; }
void Animation::MirrorAnimation() { Video *video = core->GetVideoDriver(); for (size_t i = 0; i < indicesCount; i++) { Sprite2D * tmp = frames[i]; frames[i] = video->MirrorSpriteHorizontal( tmp, true ); tmp->release(); } // flip animArea horizontally as well animArea.x = -animArea.w - animArea.x; }
TTFFont::TTFFont(Palette* pal, FT_Face face, int lineheight, int baseline) : Font(pal, lineheight, baseline), face(face) { // on FT < 2.4.2 the manager will defer ownership to this object #if FREETYPE_VERSION_ATLEAST(2,4,2) FT_Reference_Face(face); // retain the face or the font manager will destroy it #endif // ttf fonts dont produce glyphs for whitespace Sprite2D* blank = core->GetVideoDriver()->CreateSprite8(0, 0, NULL, NULL); // blank for returning when there is an error // TODO: ttf fonts have a "box" glyph they use for this CreateGlyphForCharSprite(0, blank); blank->Width = core->TLKEncoding.zerospace ? 1 : (LineHeight * 0.25);; CreateGlyphForCharSprite(' ', blank); blank->Width *= 4; CreateGlyphForCharSprite('\t', blank); blank->release(); }
Font* BAMFontManager::GetFont(unsigned short /*ptSize*/, FontStyle /*style*/, Palette* pal) { AnimationFactory* af = bamImp->GetAnimationFactory(resRef); // released by BAMFont Font* fnt = NULL; if (isStateFont) { // Hack to work around original data where some status icons have inverted x and y positions (ie level up icon) // isStateFont is set in Open() and simply compares the first 6 characters of the file with "STATES" // since state icons should all be the same size/position we can just take the position of the first one Sprite2D* first = af->GetFrame(0, 0); int pos = first->YPos; // baseline first->release(); fnt = new BAMFont(af, &pos); } else { fnt = new BAMFont(af, NULL); } if (pal) { fnt->SetPalette(pal); } return fnt; }
const Glyph& TTFFont::GetGlyph(ieWord chr) const { #if HAVE_ICONV if (!core->TLKEncoding.multibyte) { char* oldchar = (char*)&chr; ieWord unicodeChr = 0; char* newchar = (char*)&unicodeChr; size_t in = (core->TLKEncoding.widechar) ? 2 : 1, out = 2; // TODO: make this work on BE systems // TODO: maybe we want to work with non-unicode fonts? iconv_t cd = iconv_open("UTF-16LE", core->TLKEncoding.encoding.c_str()); #if __FreeBSD__ size_t ret = iconv(cd, (const char **)&oldchar, &in, &newchar, &out); #else size_t ret = iconv(cd, &oldchar, &in, &newchar, &out); #endif if (ret != GEM_OK) { Log(ERROR, "FONT", "iconv error: %d", errno); } iconv_close(cd); chr = unicodeChr; } #endif // first check if the glyph already exists const Glyph& g = Font::GetGlyph(chr); if (g.pixels) { return g; } // attempt to generate glyph // TODO: fix the font styles! /* // currently gemrb has exclusive styles... // TODO: make styles ORable style = NORMAL; if ( face->style_flags & FT_STYLE_FLAG_ITALIC ) { style = ITALIC; } if ( face->style_flags & FT_STYLE_FLAG_BOLD ) { // bold overrides italic // TODO: allow bold and italic together style = BOLD; } glyph_overhang = face->size->metrics.y_ppem / 10; // x offset = cos(((90.0-12)/360)*2*M_PI), or 12 degree angle glyph_italics = 0.207f; glyph_italics *= height; */ FT_Error error = 0; FT_UInt index = FT_Get_Char_Index(face, chr); if (!index) { return AliasBlank(chr); } error = FT_Load_Glyph( face, index, FT_LOAD_DEFAULT | FT_LOAD_TARGET_MONO); if( error ) { LogFTError(error); return AliasBlank(chr); } FT_GlyphSlot glyph = face->glyph; FT_Glyph_Metrics* metrics = &glyph->metrics; /* //int maxx, yoffset; if ( FT_IS_SCALABLE( face ) ) { // Get the bounding box maxx = FT_FLOOR(metrics->horiBearingX) + FT_CEIL(metrics->width); yoffset = ascent - FT_FLOOR(metrics->horiBearingY); } else { // Get the bounding box for non-scalable format. // Again, freetype2 fills in many of the font metrics // with the value of 0, so some of the values we // need must be calculated differently with certain // assumptions about non-scalable formats. maxx = FT_FLOOR(metrics->horiBearingX) + FT_CEIL(metrics->horiAdvance); yoffset = 0; } // TODO: handle styles for fonts that dont do it themselves FIXME: maxx is currently unused. glyph spacing is non existant right now font styles are non functional too */ FT_Bitmap* bitmap; uint8_t* pixels = NULL; /* Render the glyph */ error = FT_Render_Glyph( glyph, ft_render_mode_normal ); if( error ) { LogFTError(error); return AliasBlank(chr); } bitmap = &glyph->bitmap; Size sprSize(bitmap->width, bitmap->rows); /* Ensure the width of the pixmap is correct. On some cases, * freetype may report a larger pixmap than possible.*/ /* if (sprSize.w > maxx) { sprSize.w = maxx; }*/ if (sprSize.IsEmpty()) { return AliasBlank(chr); } // we need 1px empty space on each side sprSize.w += 2; pixels = (uint8_t*)malloc(sprSize.w * sprSize.h); uint8_t* dest = pixels; uint8_t* src = bitmap->buffer; for( int row = 0; row < sprSize.h; row++ ) { // TODO: handle italics. we will need to offset the row by font->glyph_italics * row i think. // add 1px left padding memset(dest++, 0, 1); // -2 to account for padding memcpy(dest, src, sprSize.w - 2); dest += sprSize.w - 2; src += bitmap->pitch; // add 1px right padding memset(dest++, 0, 1); } // assert that we fill the buffer exactly assert((dest - pixels) == (sprSize.w * sprSize.h)); // TODO: do an underline if requested Sprite2D* spr = core->GetVideoDriver()->CreateSprite8(sprSize.w, sprSize.h, pixels, NULL, true, 0); spr->YPos = FT_FLOOR(metrics->horiBearingY); // FIXME: casting away const const Glyph& ret = ((TTFFont*)this)->CreateGlyphForCharSprite(chr, spr); spr->release(); return ret; }