Draw: Fast cached HasCodepoint for TTF (now used for character replacements), Diagram: Triangle, upptst

This commit is contained in:
Mirek Fidler 2025-07-22 09:27:44 +02:00
parent 001461ab0a
commit e0fdb0cd05
8 changed files with 135 additions and 3 deletions

View file

@ -38,8 +38,25 @@ ValueMaker`::Make to obtain the Value and stores it to the cache.
Note that this function allows full reentrancy (from various
threads as well as recursive calls (through Make method) in single
thread&]
[s2; &]
[s4;%- &]
[s5;:Upp`:`:MakeValue`(const K`&`,const M`&`):%- [@(0.0.255) template]
<[@(0.0.255) class] K, [@(0.0.255) class] M> Value [* MakeValue]([@(0.0.255) const]
K[@(0.0.255) `&] [*@3 k], [@(0.0.255) const] M[@(0.0.255) `&] [*@3 m])&]
[s2; This is similar to variant with ValueMaker, however virtual
methods Key and Make are substituted with lambdas [%-*@3 k] and
[%-*@3 m].&]
[s3; &]
[s4;%- &]
[s5;:Upp`:`:MakeValueTL`(const K`&`,const M`&`):%- [@(0.0.255) template]
<[@(0.0.255) class] K, [@(0.0.255) class] M> Value [* MakeValueTL]([@(0.0.255) const]
K[@(0.0.255) `&] [*@3 k], [@(0.0.255) const] M[@(0.0.255) `&] [*@3 m])&]
[s2; Similar to MakeValue([%-*@3 k], [%-*@3 m]) but adds smaller per`-thread
cache, which is then accessed without mutex, making the operation
faster. This can have speed advantage in very specific cases
`- use with caution and benchmark.&]
[s3;%- &]
[s4;%- &]
[s5;:Upp`:`:IsValueCacheActive`(`):%- [@(0.0.255) bool]_[* IsValueCacheActive]()&]
[s2; Returns true if it is still possible to use Value Cache. This
special function is intended to solve destruction conflicts at

View file

@ -992,6 +992,7 @@ enum {
bool ReadCmap(const char *ptr, int count, Event<int, int, int> range, dword flags = 0);
bool ReadCmap(Font font, Event<int, int, int> range, dword flags = 0);
bool GetPanoseNumber(Font font, byte *panose);
bool HasCodepoint(Font font, int c);
}

View file

@ -322,6 +322,33 @@ bool GetPanoseNumber(Font font, byte *panose)
return true;
}
bool HasCodepoint(Font font, int c)
{
Value v = MakeValue(
[&] {
StringBuffer h;
RawCat(h, font);
return (String)h;
},
[&](Value& v) {
Vector<Tuple<int, int>>& ranges = CreateRawValue<Vector<Tuple<int, int>>>(v);
ReadCmap(font, [&](int start, int end, int) {
if(ranges.GetCount() && ranges.Top().b + 1 == start) // often we get sequence like { 1, 2 }, { 3, 4 } - optimize by joining
ranges.Top().b = end;
else
ranges.Add({ start, end });
});
ranges.Shrink();
return ranges.GetCount() * sizeof(Tuple<int, int>);
}
);
const Vector<Tuple<int, int>>& ranges = v.To<Vector<Tuple<int, int>>>();
for(Tuple<int, int> r : ranges)
if(c >= r.a && c <= r.b)
return true;
return false;
}
struct sFontMetricsReplacement {
Font src;
Font dst;
@ -430,7 +457,8 @@ bool Replace(Font fnt, int chr, Font& rfnt)
StableIndexSort(distance, candidate);
for(int fi : candidate) {
f.Face(fi);
if(IsNormal_nc(f, chr)) {
if(HasCodepoint(f, chr)) {
// if(IsNormal_nc(f, chr)) {
int a = fnt.GetAscent();
int d = fnt.GetDescent();
static WString apple_kbd = "⌘⌃⇧⌥"; // do not make these smaller it looks ugly...

View file

@ -68,7 +68,8 @@ void ApproximateChar(LinearPathConsumer& t, Pointf at, int ch, Font fnt, double
gp.move = gp.pos = Null;
gp.tolerance = tolerance;
PaintCharacter(gp, Pointf(0, 0), ch, fnt);
int sz = gp.glyph.GetCount() * 4;
int sz = gp.glyph.GetCount() * sizeof(float);
gp.glyph.Shrink();
v = RawPickToValue(pick(gp.glyph));
return sz;
});

View file

@ -25,6 +25,8 @@ struct DiagramItem : Point2 {
SHAPE_DIAMOND,
SHAPE_OVAL,
SHAPE_PARALLELOGRAM,
SHAPE_TRIANGLE,
SHAPE_ITRIANGLE,
SHAPE_ARROWLEFT,
SHAPE_ARROWRIGHT,
SHAPE_ARROWHORZ,

View file

@ -4,6 +4,7 @@ namespace Upp {
Index<String> DiagramItem::Shape = { "line", "rect", "round_rect",
"ellipse", "diamond", "oval", "parallelogram",
"triangle1", "triangle2",
"arrow_left", "arrow_right", "arrow_horz",
"arrow_down", "arrow_up", "arrow_vert",
};
@ -174,7 +175,26 @@ void DiagramItem::Paint(Painter& w, dword style, const Index<Pointf> *conn) cons
w.Move(r.left + r.Width() / 6, r.top).Line(r.right, r.top)
.Line(r.right - r.Width() / 6, r.bottom).Line(r.left, r.bottom).Close();
break;
case SHAPE_ARROWLEFT: {
case SHAPE_TRIANGLE: {
text_rect.left += int(r.Width() / 4);
text_rect.right -= int(r.Width() / 4);
text_rect.top += int(r.Width() / 3);
w.Move(r.left + r.Width() / 2, r.top)
.Line(r.right, r.bottom)
.Line(r.left, r.bottom)
.Close();
}
break;
case SHAPE_ITRIANGLE: {
text_rect.left += int(r.Width() / 4);
text_rect.right -= int(r.Width() / 4);
text_rect.bottom -= int(r.Width() / 3);
w.Move(r.left + r.Width() / 2, r.bottom)
.Line(r.right, r.top)
.Line(r.left, r.top)
.Close();
}
break; case SHAPE_ARROWLEFT: {
double a = r.left + arrow_width;
text_rect.left += int(arrow_width / 3);
w.Move(r.left, r.top + r.Height() / 2)

View file

@ -0,0 +1,9 @@
uses
CtrlLib;
file
main.cpp;
mainconfig
"" = "GUI";

View file

@ -0,0 +1,54 @@
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
struct SymbolRanges {
int from;
int to;
const char *text;
} symbol_ranges[] = {
0x2190, 0x21FF, "Arrows",
0x2200, 0x22FF, "Mathematical Operators",
0x2300, 0x23FF, "Miscellaneous Technical",
0x2400, 0x243F, "Control Pictures",
0x2440, 0x245F, "Optical Character Recognition",
0x2460, 0x24FF, "Enclosed Alphanumerics",
0x2500, 0x257F, "Box Drawing",
0x2580, 0x259F, "Block Elements",
0x25A0, 0x25FF, "Geometric Shapes",
0x2600, 0x26FF, "Miscellaneous Symbols",
0x2700, 0x27BF, "Dingbats",
0x27C0, 0x27EF, "Miscellaneous Mathematical Symbols-A",
0x27F0, 0x27FF, "Supplemental Arrows-A",
0x2800, 0x28FF, "Braille Patterns",
0x2900, 0x297F, "Supplemental Arrows-B",
0x2980, 0x29FF, "Miscellaneous Mathematical Symbols-B",
0x2A00, 0x2AFF, "Supplemental Mathematical Operators",
0x2B00, 0x2BFF, "Miscellaneous Symbols and Arrows",
0x1F300, 0x1F5FF, "Miscellaneous Symbols and Pictographs",
0x1F600, 0x1F64F, "Emoticons",
0x1F650, 0x1F67F, "Ornamental Dingbats",
0x1F680, 0x1F6FF, "Transport and Map Symbols",
0x1F700, 0x1F77F, "Alchemical Symbols",
0x1F780, 0x1F7FF, "Geometric Shapes Extended",
0x1F800, 0x1F8FF, "Supplemental Arrows-C",
0x1F900, 0x1F9FF, "Supplemental Symbols and Pictographs",
0x1FA00, 0x1FA6F, "Chess Symbols",
0x1FA70, 0x1FAFF, "Symbols and Pictographs Extended-A",
0x1F000, 0x1F02F, "Mahjong Tiles",
0x1F030, 0x1F09F, "Domino Tiles",
0x1F0A0, 0x1F0FF, "Playing Cards",
};
GUI_APP_MAIN
{
String qtf;
for(auto& sr : symbol_ranges) {
qtf << sr.text << ":&[3 ";
for(int i = sr.from; i <= sr.to; i++) {
qtf << WString(i, 1) << " ";
}
qtf << "&&";
}
PromptOK(qtf);
}