void Topology::updateCache(rectObj thebounds, bool purgeonly) { if (!triggerUpdateCache) return; if (!shapefileopen) return; in_scale = CheckScale(); if (!in_scale) { // not visible, so flush the cache // otherwise we waste time on looking up which shapes are in bounds flushCache(); triggerUpdateCache = false; in_scale_last = false; return; } if (purgeonly) { in_scale_last = in_scale; return; } triggerUpdateCache = false; #ifdef DEBUG_TFC #ifdef TOPOFASTCACHE StartupStore(TEXT("---UpdateCache() starts, mode%d%s"),cache_mode,NEWLINE); #else StartupStore(TEXT("---UpdateCache() starts, original code%s"),NEWLINE); #endif int starttick = GetTickCount(); #endif #ifdef TOPOFASTCACHE if(msRectOverlap(&shpfile.bounds, &thebounds) != MS_TRUE) { // this happens if entire shape is out of range // so clear buffer. flushCache(); in_scale_last = in_scale; return; } bool smaller = false; bool bigger = false; bool in_scale_again = in_scale && !in_scale_last; int shapes_loaded = 0; shapes_visible_count = 0; in_scale_last = in_scale; switch (cache_mode) { case 0: // Original code plus one special case smaller = (msRectContained(&thebounds, &lastBounds) == MS_TRUE); if (smaller) { //Special case, search inside, we don't need to load additional shapes, just remove shapes_visible_count = 0; for (int i=0; i<shpfile.numshapes; i++) { if (shpCache[i]) { if(msRectOverlap(&(shpCache[i]->shape.bounds), &thebounds) != MS_TRUE) { removeShape(i); } else shapes_visible_count++; } }//for } else { //In this case we have to run the original algoritm msSHPWhichShapes(&shpfile, thebounds, 0); shapes_visible_count = 0; for (int i=0; i<shpfile.numshapes; i++) { if (msGetBit(shpfile.status, i)) { if (shpCache[i]==NULL) { // shape is now in range, and wasn't before shpCache[i] = addShape(i); shapes_loaded++; } shapes_visible_count++; } else { removeShape(i); } }//for } break; case 1: // Bounds array in memory bigger = (msRectContained(&lastBounds, &thebounds) == MS_TRUE); smaller = (msRectContained(&thebounds, &lastBounds) == MS_TRUE); if (bigger || in_scale_again) { //We don't need to remove shapes, just load, so skip loaded ones for (int i=0; i<shpfile.numshapes; i++) { if (shpCache[i]) continue; if(msRectOverlap(&shpBounds[i], &thebounds) == MS_TRUE) { // shape is now in range, and wasn't before shpCache[i] = addShape(i); shapes_loaded++; } }//for shapes_visible_count+=shapes_loaded; } else if (smaller) { //Search inside, we don't need to load additional shapes, just remove for (int i=0; i<shpfile.numshapes; i++) { if (shpCache[i]==NULL) continue; if(msRectOverlap(&shpBounds[i], &thebounds) != MS_TRUE) { removeShape(i); } else shapes_visible_count++; }//for } else { //Otherwise we have to search the all array for (int i=0; i<shpfile.numshapes; i++) { if(msRectOverlap(&shpBounds[i], &thebounds) == MS_TRUE) { if (shpCache[i]==NULL) { // shape is now in range, and wasn't before shpCache[i] = addShape(i); shapes_loaded++; } shapes_visible_count++; } else { removeShape(i); } }//for } break; case 2: // All shapes in memory XShape *pshp; shapes_visible_count = 0; for (int i=0; i<shpfile.numshapes; i++) { pshp = shps[i]; if(msRectOverlap(&(pshp->shape.bounds), &thebounds) == MS_TRUE) { shpCache[i] = pshp; shapes_visible_count++; } else { shpCache[i] = NULL; } }//for break; }//sw lastBounds = thebounds; #else msSHPWhichShapes(&shpfile, thebounds, 0); if (!shpfile.status) { // this happens if entire shape is out of range // so clear buffer. flushCache(); return; } shapes_visible_count = 0; for (int i=0; i<shpfile.numshapes; i++) { if (msGetBit(shpfile.status, i)) { if (shpCache[i]==NULL) { // shape is now in range, and wasn't before shpCache[i] = addShape(i); } shapes_visible_count++; } else { removeShape(i); } } #endif #ifdef DEBUG_TFC long free_size = CheckFreeRam(); StartupStore(TEXT(" UpdateCache() ends, shps_visible=%d ram=%li (%dms)%s"),shapes_visible_count, free_size, GetTickCount()-starttick,NEWLINE); #endif }
void Topology::TriggerIfScaleNowVisible(void) { triggerUpdateCache |= (CheckScale() != in_scale); }
void Topology::TriggerIfScaleNowVisible(MapWindowProjection &map_projection) { triggerUpdateCache |= (CheckScale(map_projection.GetMapScaleUser()) != in_scale); }
double MLIFont::GetLineDescent() { EnsureUIThread(); CheckScale(); return (double)TTF_FontDescent(pTtfFont) / GetFontScale(); }
void MLIFont::DrawInternal(const string &s, Vector2 position, Color color, double scale, RectangleWH clipRect) { EnsureUIThread(); // If we're trying to draw an empty string, we can just return - // we're not gonna draw anything anyhow. if (s.length() == 0) { return; } CheckScale(); double x = position.GetX(); double y = position.GetY(); for (string::const_iterator it = s.begin(); it < s.end();) { uint32_t c = 0; if (!GetNextFromStringIterator(it, s.end(), &c)) { break; } Image *pGlyphImage = cache[c]; if (pGlyphImage == NULL) { continue; } RectangleWH characterClipRect(0, 0, pGlyphImage->width / GetFontScale(), pGlyphImage->height / GetFontScale()); RectangleWH originalCharacterClipRect = characterClipRect; if (clipRect.GetWidth() < 0 || clipRect.GetX() < originalCharacterClipRect.GetWidth()) { if (clipRect.GetWidth() >= 0) { if (clipRect.GetX() > 0) { characterClipRect.SetX(originalCharacterClipRect.GetX() + clipRect.GetX()); characterClipRect.SetWidth(originalCharacterClipRect.GetWidth() - clipRect.GetX()); } if (clipRect.GetWidth() < characterClipRect.GetWidth()) { characterClipRect.SetWidth(clipRect.GetWidth()); } if (clipRect.GetY() > 0) { characterClipRect.SetY(min(originalCharacterClipRect.GetY() + clipRect.GetY(), originalCharacterClipRect.GetY() + originalCharacterClipRect.GetHeight())); characterClipRect.SetHeight(originalCharacterClipRect.GetHeight() - (characterClipRect.GetY() - originalCharacterClipRect.GetY())); } if (clipRect.GetHeight() < characterClipRect.GetHeight()) { characterClipRect.SetHeight(clipRect.GetHeight()); } } if (characterClipRect.GetWidth() > 0 && characterClipRect.GetHeight() > 0) { characterClipRect.SetHeight(characterClipRect.GetHeight() * GetFontScale()); characterClipRect.SetWidth(characterClipRect.GetWidth() * GetFontScale()); pGlyphImage->Draw(Vector2(x, y), characterClipRect, false, false, scale, scale, color); } } double deltaX = pGlyphImage->width; if (it < s.end()) { uint32_t c2 = 0; if (PeekNextFromStringIterator(it, s.end(), &c2)) { deltaX = GetKernedWidth(c, c2); } } x += deltaX / GetFontScale(); } }
Image *MLIFont::RenderGlyph(uint32_t c) { EnsureUIThread(); CheckScale(); // render char SDL_Color whiteColor = {255, 255, 255, 255}; if (invertedColors) { whiteColor.b = 255 - whiteColor.b; whiteColor.g = 255 - whiteColor.g; whiteColor.a = 255 - whiteColor.a; } string utf8string; utf8::unchecked::append(c, back_inserter(utf8string)); SDL_Surface *pSurface = TTF_RenderUTF8_Blended(pTtfFont, utf8string.c_str(), whiteColor); if (pSurface == NULL) { return NULL; } int scaledStrokeWidth = strokeWidth * GetFontScale() + 0.5; // render outlines if (strokeWidth > 0) { SDL_Color blackColor = {0, 0, 0, 255}; if (invertedColors) { blackColor.b = 255 - blackColor.b; blackColor.g = 255 - blackColor.g; blackColor.a = 255 - blackColor.a; } #ifndef MLI_SDL_FONT_OUTLINING SDL_Surface *pSurfaceOutline = TTF_RenderUTF8_Blended(pTtfFont, utf8string.c_str(), blackColor); SDL_Surface *pSurfaceOutlinedText = SDL_CreateRGBSurface( 0, pSurface->w + scaledStrokeWidth * 2, pSurface->h + scaledStrokeWidth * 2, pSurface->format->BitsPerPixel, pSurface->format->Rmask, pSurface->format->Gmask, pSurface->format->Bmask, pSurface->format->Amask); SDL_SetSurfaceBlendMode(pSurfaceOutline, SDL_BLENDMODE_BLEND); SDL_Rect dstRect = {0, 0, pSurface->w, pSurface->h}; for (dstRect.x = 0; dstRect.x <= scaledStrokeWidth * 2; dstRect.x++) { for (dstRect.y = 0; dstRect.y <= scaledStrokeWidth * 2; dstRect.y++) { SDL_BlitSurface(pSurfaceOutline, NULL, pSurfaceOutlinedText, &dstRect); } } dstRect.x = scaledStrokeWidth; dstRect.y = scaledStrokeWidth; SDL_SetSurfaceBlendMode(pSurfaceOutline, SDL_BLENDMODE_BLEND); SDL_BlitSurface(pSurface, NULL, pSurfaceOutlinedText, &dstRect); SDL_FreeSurface(pSurface); SDL_FreeSurface(pSurfaceOutline); pSurface = pSurfaceOutlinedText; #else TTF_SetFontOutline(pTtfFont, scaledStrokeWidth); SDL_Surface *pSurfaceOutlinedText = TTF_RenderUTF8_Blended(pTtfFont, utf8string.c_str(), blackColor); SDL_SetSurfaceBlendMode(pSurfaceOutlinedText, SDL_BLENDMODE_BLEND); SDL_Rect dstRect = {scaledStrokeWidth, scaledStrokeWidth, pSurface->w, pSurface->h}; SDL_BlitSurface(pSurface, NULL, pSurfaceOutlinedText, &dstRect); SDL_FreeSurface(pSurface); pSurface = pSurfaceOutlinedText; TTF_SetFontOutline(pTtfFont, 0); #endif } // create image Image *pImage = Image::Load(pSurface, true); pImage->FlagFontSource(this); pImage->SetUseScreenScaling(false); return pImage; }