FT_Face FTFace(Font fnt) { LTIMING("FTFace"); LLOG("FTFace " << fnt); ONCELOCK { ClearFtFaceCache(); } FtFaceEntry be; be = ft_cache[0]; for(int i = 0; i < FONTCACHE; i++) { FtFaceEntry e = ft_cache[i]; if(i) ft_cache[i] = be; if(e.font == fnt && e.face) { if(i) ft_cache[0] = e; LLOG("Found " << e.face); return e.face; } be = e; } LTIMING("FTFace2"); if(be.face) { LLOG("Removing " << be.font << " - " << (void *)be.face); FT_Done_Face(be.face); } be.font = fnt; be.face = CreateFTFace(be.font); ft_cache[0] = be; LLOG("Created " << be.face); return be.face; }
void Ctrl::RefreshFrame(const Rect& r) { GuiLock __; if(!IsOpen() || !IsVisible() || r.IsEmpty()) return; LTIMING("RefreshFrame"); LLOG("RefreshRect " << Name() << ' ' << r); #ifdef PLATFORM_WIN32 if(isdhctrl) { InvalidateRect(((DHCtrl *)this)->GetHWND(), r, false); return; } #endif if(!top) { if(InFrame()) parent->RefreshFrame(r + GetRect().TopLeft()); else parent->Refresh(r + GetRect().TopLeft()); } else { LLOG("WndInvalidateRect: " << r << ' ' << Name()); LTIMING("RefreshFrame InvalidateRect"); WndInvalidateRect(r); #ifdef PLATFORM_WIN32 LLOG("UpdateRect: " << GetWndUpdateRect() << ' ' << Name()); #endif } }
HFONT GetWin32Font(Font fnt, int angle) { LTIMING("GetWin32Font"); static HFontEntry cache[FONTCACHE]; ONCELOCK { for(int i = 0; i < FONTCACHE; i++) cache[i].font.Height(-30000); } HFontEntry be; be = cache[0]; for(int i = 0; i < FONTCACHE; i++) { HFontEntry e = cache[i]; if(i) cache[i] = be; if(e.font == fnt && e.angle == angle) { if(i) cache[0] = e; return e.hfont; } be = e; } LTIMING("GetWin32Font2"); if(be.hfont) DeleteObject(be.hfont); be.font = fnt; be.angle = angle; #ifdef PLATFORM_WINCE LOGFONT lfnt; Zero(lfnt); lfnt.lfHeight = fnt.GetHeight() ? -abs(fnt.GetHeight()) : -12; lfnt.lfWeight = fnt.IsBold() ? FW_BOLD : FW_NORMAL; lfnt.lfItalic = fnt.IsItalic(); lfnt.lfUnderline = fnt.IsUnderline(); lfnt.lfStrikeOut = fnt.IsStrikeout(); wcscpy(lfnt.lfFaceName, ToSystemCharset(fnt.GetFaceName())); be.hfont = CreateFontIndirect(&lfnt); #else be.hfont = CreateFont( fnt.GetHeight() ? -abs(fnt.GetHeight()) : -12, fnt.GetWidth(), angle, angle, fnt.IsBold() ? FW_BOLD : FW_NORMAL, fnt.IsItalic(), fnt.IsUnderline(), fnt.IsStrikeout(), fnt.GetFace() == Font::SYMBOL ? SYMBOL_CHARSET : DEFAULT_CHARSET, fnt.IsTrueTypeOnly() ? OUT_TT_ONLY_PRECIS : OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, fnt.IsNonAntiAliased() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, fnt.GetFaceName() ); #endif cache[0] = be; return be.hfont; }
bool DoQualify(ScopeInfo& nf, const String& type, const String& usings, String& qt) { LTIMING("Qualify"); int q = nf.cache.Find(type); if(q >= 0) { qt = nf.cache[q]; return true; } LTIMING("Qualify0"); if(!Qualify0(nf, type, usings, qt)) return false; nf.cache.Add(type, qt); return true; }
String GetIncludePath(const String& s, const String& filedir) { LTIMING("GetIncludePath"); String key; key << s << "#" << filedir; int q = sIncludePath.Find(key); if(q >= 0) return sIncludePath[q]; LTIMING("GetIncludePath 2"); String p = GetIncludePath0(s, filedir); sIncludePath.Add(key, p); LLOG("GetIncludePath " << s << " " << filedir << ": " << p); return p; }
Value Compiler::ExeLink::Eval(ExeContext& x) const { LTIMING("ExeLink"); Vector<Value> v; v.SetCount(arg.GetCount()); for(int i = 0; i < arg.GetCount(); i++) { LTIMING("arg eval"); v[i] = arg[i]->Eval(x); } StringBuffer r; r << "\""; MakeLink(r, *part, v); r << "\""; return Raw(r); }
void SDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, int n, const int *dx) { sMakeTextGlyph g; g.font = font; g.color = White(); g.angle = angle; g.draw = this; for(int i = 0; i < n; i++) { g.chr = text[i]; LTIMING("Paint glyph"); if(font.GetHeight() > 200) { int bn = font[g.chr] + font.GetLineHeight(); for(g.yy = 0; g.yy < bn; g.yy += 32) { Image m; if(paintonly) m = MakeImagePaintOnly(g); else m = MakeImage(g); Point h = m.GetHotSpot(); SysDrawImageOp(x - h.x, y + g.yy - h.y, m, m.GetSize(), ink); } } else { g.yy = Null; Image m; if(paintonly) m = MakeImagePaintOnly(g); else m = MakeImage(g); Point h = m.GetHotSpot(); SysDrawImageOp(x - h.x, y - h.y, m, m.GetSize(), ink); } x += dx ? *dx++ : font[g.chr]; } }
bool SystemDraw::ClipOp(const Rect& r) { GuiLock __; Begin(); LTIMING("Clip"); return IntersectClip(r); }
void Ctrl::ScrollView(const Rect& _r, int dx, int dy) { GuiLock __; LLOG("ScrollView " << _r << " " << dx << " " << dy); if(IsFullRefresh() || !IsVisible()) return; Size vsz = GetSize(); dx = sgn(dx) * min(abs(dx), vsz.cx); dy = sgn(dy) * min(abs(dy), vsz.cy); Rect r = _r & vsz; LLOG("ScrollView2 " << r << " " << dx << " " << dy); Ctrl *w; for(w = this; w->parent; w = w->parent) if(w->InFrame()) { Refresh(); return; } if(!w || !w->top) return; Rect view = InFrame() ? GetView() : GetClippedView(); Rect sr = (r + view.TopLeft()) & view; sr += GetScreenRect().TopLeft() - w->GetScreenRect().TopLeft(); if(w->AddScroll(sr, dx, dy)) Refresh(); else { LTIMING("ScrollCtrls1"); Top *top = GetTopCtrl()->top; for(Ctrl *q = GetFirstChild(); q; q = q->GetNext()) if(q->InView()) ScrollCtrl(top, q, r, q->GetRect(), dx, dy); if(parent) for(Ctrl *q = parent->GetFirstChild(); q; q = q->GetNext()) if(q->InView() && q != this) ScrollCtrl(top, q, r, q->GetScreenRect() - GetScreenView().TopLeft(), dx, dy); } }
bool IncludesFile(const String& parent_path, const String& header_path) { LTIMING("IncludesFile"); int pi = sSrcFile.Find(parent_path); int i = sSrcFile.Find(header_path); return pi >= 0 && i >= 0 && sIncludes.Find(MAKEQWORD(pi, i)) >= 0; }
void SDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, int n, const int *dx) { sMakeTextGlyph g; g.font = font; g.color = White(); g.angle = angle; g.draw = this; for(int i = 0; i < n; i++) { g.chr = text[i]; LTIMING("Paint glyph"); if(font.GetHeight() > 200) { Point at(font[g.chr], font.GetLineHeight()); int n = at.x + at.y; Size bandsz(2 * n, 32); for(int yy = 0; yy < n; yy += bandsz.cy) { Image m = RenderGlyph(Point(0, -yy), angle, g.chr, font, White(), bandsz); SysDrawImageOp(x, y + yy, m, m.GetSize(), ink); } } else { Image m = MakeImage(g); Point h = m.GetHotSpot(); SysDrawImageOp(x - h.x, y - h.y, m, m.GetSize(), ink); } x += dx ? *dx++ : font[g.chr]; } }
String GetIncludePath0(const char *s, const char *filedir) { LTIMING("GetIncludePath0"); while(IsSpace(*s)) s++; int type = *s; if(type == '<' || type == '\"' || type == '?') { s++; String name; if(type == '<') type = '>'; while(*s != '\r' && *s != '\n') { if(*s == type) { if(type == '\"') { String fn = NormalizeSourcePath(name, filedir); if(FileExists(fn)) return fn; } String p = GetFileOnPath(name, GetIncludePath(), false); if(p.GetCount()) return NormalizeSourcePath(p); return Null; } name.Cat(*s++); } } return Null; }
void Navigator::Scope() { LTIMING("FINALIZE"); litem.Clear(); nest_item.Clear(); linefo.Clear(); bool all = scope.GetCursor() <= 0; String sc = scope.GetKey(); for(int i = 0; i < gitem.GetCount(); i++) { String grp = gitem.GetKey(i); int kind = KIND_NEST; if(*grp == '\xff') kind = KIND_FILE; if(all) { NavItem& m = nest_item.Add(); m.kind = kind; m.type = FormatNest(grp); litem.Add(&m); } else if(grp != sc) continue; const Vector<NavItem *>& ia = gitem[i]; for(int i = 0; i < ia.GetCount(); i++) { NavItem *m = ia[i]; for(int j = 0; j < m->linefo.GetCount(); j++) linefo.GetAdd(m->linefo[j].file).Add(m->linefo[j].line, litem.GetCount()); litem.Add(m); } } list.Clear(); list.SetVirtualCount(litem.GetCount()); }
void SyncTopicFile(const RichText& text, const String& link, const String& path, const String& title) { LLOG("Scanning topic " << link); LTIMING("Scanning topic"); ClearLinkRef(link); ScanTopicIterator sti; sti.link = link; text.Iterate(sti); TopicInfo& ti = topic_info().GetPut(link); ti.title = title; ti.path = path; ti.time = FileGetTime(path); ti.words = sti.words.PickKeys(); FileOut out(TopicCacheName(path)); out << tdx_version << "\n"; out << title << '\n'; for(int i = 0; i < sti.ref.GetCount(); i++) out << sti.ref[i] << '\n'; out << '\n'; const Index<String>& ws = TopicWords(); for(int i = 0; i < ti.words.GetCount(); i++) out << ws[ti.words[i]] << '\n'; }
void Ctrl::GatherTransparentAreas(Vector<Rect>& area, SystemDraw& w, Rect r, const Rect& clip) { GuiLock __; LTIMING("GatherTransparentAreas"); Point off = r.TopLeft(); Point viewpos = off + GetView().TopLeft(); r.Inflate(overpaint); Rect notr = GetVoidRect(); if(notr.IsEmpty()) notr = GetOpaqueRect(); notr += viewpos; if(!IsShown() || r.IsEmpty() || !clip.Intersects(r) || !w.IsPainting(r)) return; if(notr.IsEmpty()) CombineArea(area, r & clip); else { if(notr != r) { CombineArea(area, clip & Rect(r.left, r.top, notr.left, r.bottom)); CombineArea(area, clip & Rect(notr.right, r.top, r.right, r.bottom)); CombineArea(area, clip & Rect(notr.left, r.top, notr.right, notr.top)); CombineArea(area, clip & Rect(notr.left, notr.bottom, notr.right, r.bottom)); } for(Ctrl *q = firstchild; q; q = q->next) { Point qoff = q->InView() ? viewpos : off; Rect qr = q->GetRect() + qoff; if(clip.Intersects(qr)) q->GatherTransparentAreas(area, w, qr, clip); } } }
Value Compiler::ExeFor::Eval(ExeContext& x) const { LTIMING("ExeFor"); Value array = value->Eval(x); LLOG("ExeFor array: " << array); if(array.GetCount() == 0 && onempty) return onempty->Eval(x); ValueMap m; bool map = array.Is<ValueMap>(); if(map) m = array; int q = x.stack.GetCount(); x.stack.Add(); x.stack.Add(); for(int i = 0; i < array.GetCount(); i++) { x.stack[q] = array[i]; LoopInfo f; f.first = i == 0; f.last = i == array.GetCount() - 1; f.index = i; f.key = map ? m.GetKeys()[i] : (Value)i; x.stack[q + 1] = RawToValue(f); sCatAsString(x.out, body->Eval(x)); } x.stack.SetCount(q); return Value(); }
void sOptimizedRectRenderer::Flush() { LTIMING("RectFlush"); if(!IsNull(cr)) { w.DrawRect(cr, color); cr = Null; } }
void sOptimizedTextRenderer::DrawChar(int _x, int _y, int chr, int width, Font _font, Color _color) { LTIMING("DrawChar"); if(y == _y && font == _font && color == _color && dx.GetCount() && _x >= xpos - dx.Top()) dx.Top() += _x - xpos; else { LTIMING("DrawChar flush"); Flush(); x = _x; y = _y; font = _font; color = _color; } dx.Add(width); text.Cat(chr); xpos = _x + width; }
String Render(const One<Exe>& exe, Renderer *r, Vector<Value>& var) { LTIMING("Render0"); ExeContext x(var, r); Value v = exe->Eval(x); x.out.Cat(AsString(v)); return x.out; }
void GLDraw::PutImage(Point p, const Image& img, const Rect& src) { LTIMING("PutImage"); FlushPutRect(); gl_image.Use(); Size isz = img.GetSize(); Rect s = src & isz; Rect r(p, s.GetSize()); PutImagePixels += isz.cx * isz.cy; GLshort vertex[] = { r.left, r.top, r.left, r.bottom, r.right, r.bottom, r.right, r.top, }; static GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; const float *tc; if(src == isz) { static float fixed[] = { 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, }; tc = fixed; } else { Sizef iszf = isz; Rectf h; h.left = s.left / iszf.cx; h.right = s.right / iszf.cx; h.top = s.top / iszf.cy; h.bottom = s.bottom / iszf.cy; float partial[] = { (float)h.left, (float)h.top, (float)h.left, (float)h.bottom, (float)h.right, (float)h.bottom, (float)h.right, (float)h.top, }; tc = partial; } glEnableVertexAttribArray(ATTRIB_TEXPOS); glVertexAttribPointer(ATTRIB_TEXPOS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), tc); glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_SHORT, GL_FALSE, 2 * sizeof(GLshort), vertex); glBindTexture(GL_TEXTURE_2D, GetTextureForImage(img)); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); glDisableVertexAttribArray(ATTRIB_TEXPOS); }
void SystemDraw::OffsetOp(Point p) { GuiLock __; Begin(); actual_offset += p; drawingclip -= p; LTIMING("Offset"); SetOrg(); }
String QualifyIds(ScopeInfo& nf, const String& k, const String& usings, bool all) { LTIMING("QualifyIds"); String r; const char *s = k; Vector<String> empty; while(*s) { int c = *s; if(c == ':') { const char *b = s++; while(*s == ':' || iscid(*s)) s++; /* if(all) { if(iscid(*r.Last())) r << ' '; ScopeInfo nnf(nf.GetScope(), nf.base); Qualify(r, nnf, b, s, usings); } else*/ r.Cat(b, s); } else if(iscid(c)) { if(iscid(*r.Last())) r << ' '; if(s[0] == 'c' && s[1] == 'o' && s[2] == 'n' && s[3] == 's' && s[4] == 't' && !iscid(s[5])) { r << s_const; s += 5; } else if(s[0] == 'm' && s[1] == 'u' && s[2] == 't' && s[3] == 'a' && s[4] == 'b' && s[5] == 'l' && s[6] == 'e' && !iscid(s[7])) { r << "mutable"; s += 7; } else if(s[0] == 'v' && s[1] == 'o' && s[2] == 'l' && s[3] == 'a' && s[4] == 't' && s[5] == 'i' && s[6] == 'l' && s[7] == 'e' && !iscid(s[8])) { r << "volatile"; s += 8; } else { const char *b = s++; while(*s == ':' || iscid(*s)) s++; if(all) Qualify(r, nf, b, s, usings); else r.Cat(b, s); } } else { if(c == '(') all = true; if(c != ' ') r.Cat(c); s++; } } return r; }
String NormalizeSourcePath(const String& path, const String& currdir) { LTIMING("NormalizeSourcePath"); #ifdef PLATFORM_WIN32 return ToLower(NormalizePath(path, currdir)); #else return NormalizePath(path, currdir); #endif }
void sOptimizedTextRenderer::DrawChar(int x, int _y, int chr, int width, Font font, Color color) { LTIMING("DrawChar"); if(y != _y) { Flush(); y = _y; } Chrs *c; { LTIMING("Map"); c = &cache.GetAdd(MakeTuple(font, color)); } if(c->x.GetCount() && c->x.Top() > x) { Flush(); c = &cache.GetAdd(MakeTuple(font, color)); } c->text.Cat(chr); c->x.Add(x); }
void Ctrl::SyncMousePos() { GuiLock __; LTIMING("XQueryPointer"); int x, y, xx, yy; Window dm1, dm2; Ctrl::mousePos = Null; if(XQueryPointer(Xdisplay, Xroot, &dm1, &dm2, &x, &y, &xx, &yy, &sKbdState)) Ctrl::mousePos = Point(x, y); }
void Ctrl::RefreshFrame(const Rect& r) { GuiLock __; if(!IsOpen() || !IsVisible() || r.IsEmpty()) return; LTIMING("RefreshFrame"); LLOG("RefreshRect " << Name() << ' ' << r); if(GuiPlatformRefreshFrameSpecial(r)) return; if(!top) { if(InFrame()) parent->RefreshFrame(r + GetRect().TopLeft()); else parent->Refresh(r + GetRect().TopLeft()); } else { LLOG("WndInvalidateRect: " << r << ' ' << Name()); LTIMING("RefreshFrame InvalidateRect"); WndInvalidateRect(r); } }
void CreatePalette(Raster& raster, RGBA *palette, int ncolors, PaletteCv& cv) { LTIMING("Palette+Cv"); ASSERT(ncolors <= 256); One<sPalMaker> m = new sPalMaker(raster, palette, ncolors); if(m->colorcount < 15000) // Is that right!? delete new sPalCv(palette, ncolors, cv, m->histogram); else CreatePaletteCv(palette, ncolors, cv); }
Time GetFileTimeCached(const String& p) { LTIMING("GetFileTimeCached"); int q = sPathFileTime.Find(p); if(q >= 0) return sPathFileTime[q]; Time m = FileGetTime(p); sPathFileTime.Put(p, m); return m; }
void sOptimizedTextRenderer::Flush() { if(text.GetCount() == 0) return; LTIMING("Flush"); w.DrawText(x, y, text, font, color, dx); y = Null; text.Clear(); dx.Clear(); }
void Ctrl::RefreshFrame(const Rect& r) { sCheckGuiLock(); GuiLock __; // Beware: Even if we have ThreadHasGuiLock ASSERT, we still can be the main thread! if(!IsOpen() || !IsVisible() || r.IsEmpty()) return; LTIMING("RefreshFrame"); LLOG("RefreshRect " << Name() << ' ' << r); if(GuiPlatformRefreshFrameSpecial(r)) return; if(!top) { if(InFrame()) parent->RefreshFrame(r + GetRect().TopLeft()); else parent->Refresh(r + GetRect().TopLeft()); } else { LLOG("WndInvalidateRect: " << r << ' ' << Name()); LTIMING("RefreshFrame InvalidateRect"); WndInvalidateRect(r); } }