-
Notifications
You must be signed in to change notification settings - Fork 0
/
precalculated.service.ts
147 lines (116 loc) · 5.02 KB
/
precalculated.service.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import { SkCanvas, SkColor, SkPaint, SkPath, Skia } from "@shopify/react-native-skia";
import { Platform } from "react-native";
const quran = require('./quran_pb.js');
import * as FileSystem from 'expo-file-system';
import { useEffect, useState } from "react";
interface GlyphOutline {
path: SkPath;
color?: SkColor;
}
export class PreCalulatedLayout {
private _font: proto.protobuf.Font;
private _layout: proto.protobuf.LayOut;
constructor(font: proto.protobuf.Font, layout: proto.protobuf.LayOut) {
this._font = font
this._layout = layout
}
getPage(pageIndex: number) {
return this._layout.getPagesList()[pageIndex]
}
getOutlines(codepoint: number, _lefttatweel: number, _righttatweel: number): GlyphOutline[] {
let outlines: GlyphOutline[] = []
const glyphInfo: proto.protobuf.Glyph = this._font.getGlyphsMap().get(codepoint)
const limits = glyphInfo.getLimitsList().length != 4 ? [0, 0, 0, 0] : glyphInfo.getLimitsList()
const lefttatweel = _lefttatweel < limits[0] ? limits[0] : (_lefttatweel > limits[1] ? limits[1] : _lefttatweel)
const righttatweel = _righttatweel < limits[2] ? limits[2] : (_righttatweel > limits[3] ? limits[3] : _righttatweel)
var leftScalar = 0.0;
if (lefttatweel < 0) {
leftScalar = lefttatweel / limits[0];
} else if (lefttatweel > 0) {
leftScalar = lefttatweel / limits[1];
}
var rightScalar = 0.0;
if (righttatweel < 0) {
rightScalar = righttatweel / limits[2];
} else if (righttatweel > 0) {
rightScalar = righttatweel / limits[3];
}
const interpolate = (value: number, i: number, j: number, k: number): number => {
var interpolatedValue = value;
if (lefttatweel < 0) {
interpolatedValue += (glyphInfo.getMinleftList()[i].getElemsList()[j].getPointsList()[k] - value) * leftScalar;
} else if (lefttatweel > 0) {
interpolatedValue += (glyphInfo.getMaxleftList()[i].getElemsList()[j].getPointsList()[k] - value) * leftScalar;
}
if (righttatweel < 0) {
interpolatedValue += (glyphInfo.getMinrightList()[i].getElemsList()[j].getPointsList()[k] - value) * rightScalar;
} else if (righttatweel > 0) {
interpolatedValue += (glyphInfo.getMaxrightList()[i].getElemsList()[j].getPointsList()[k] - value) * rightScalar;
}
return interpolatedValue
}
for (let i = 0; i < glyphInfo.getDefaultList().length; i++) {
const defaultPath = glyphInfo.getDefaultList()[i]
const path = Skia.Path.Make();
for (let j = 0; j < defaultPath.getElemsList().length; j++) {
const elems = defaultPath.getElemsList()[j]
const pointsList = elems.getPointsList()
if (pointsList.length === 2) {
path.moveTo(interpolate(pointsList[0], i, j, 0), interpolate(pointsList[1], i, j, 1));
} else if (pointsList.length === 6) {
path.cubicTo(interpolate(pointsList[0], i, j, 0), interpolate(pointsList[1], i, j, 1), interpolate(pointsList[2], i, j, 2),
interpolate(pointsList[3], i, j, 3), interpolate(pointsList[4], i, j, 4), interpolate(pointsList[5], i, j, 5));
}
}
var color: SkColor | undefined;
const colorList = defaultPath.getColorList()
if (colorList.length == 3) {
const red = colorList[0]
const green = colorList[1]
const blue = colorList[2]
color = Float32Array.from([red / 255, green / 255, blue / 255])
}
outlines.push({ path, color })
}
return outlines
}
}
let globalPreCalulatedLayout: PreCalulatedLayout | undefined
export const usePreCalulatedLayout = () => {
const [preCalulatedLayout, setPreCalulatedLayout] = useState<null | PreCalulatedLayout>(null);
useEffect(() => {
if (globalPreCalulatedLayout) {
setPreCalulatedLayout(globalPreCalulatedLayout)
return
}
let font: proto.protobuf.Font
let layout: proto.protobuf.LayOut;
fetch('./font.protobuf')
.then(response => response.blob())
.then(blob => {
let reader = new FileReader();
reader.addEventListener("loadend", () => {
font = proto.protobuf.Font.deserializeBinary(reader.result)
if (font && layout) {
globalPreCalulatedLayout = new PreCalulatedLayout(font, layout)
setPreCalulatedLayout(globalPreCalulatedLayout)
}
});
reader.readAsArrayBuffer(blob);
});
fetch('./layout.protobuf')
.then(response => response.blob())
.then(blob => {
let reader = new FileReader();
reader.addEventListener("loadend", () => {
layout = proto.protobuf.LayOut.deserializeBinary(reader.result)
if (font && layout) {
globalPreCalulatedLayout = new PreCalulatedLayout(font, layout)
setPreCalulatedLayout(globalPreCalulatedLayout)
}
});
reader.readAsArrayBuffer(blob);
});
}, []);
return preCalulatedLayout;
};