2 #include"v_ft_raster.h"
3 #include"v_ft_stroker.h"
15 FTOutline(int points, int segments)
17 ft.points = new SW_FT_Vector[points + segments];
18 ft.tags = new char[points + segments];
19 ft.contours = new short[segments];
20 ft.n_points = ft.n_contours = 0;
23 void moveTo(const VPointF &pt);
24 void lineTo(const VPointF &pt);
25 void cubicTo(const VPointF &ctr1, const VPointF &ctr2, const VPointF end);
28 void transform(const VMatrix &m);
39 #define TO_FT_COORD(x) ((x) * 64) // to freetype 26.6 coordinate.
41 void FTOutline::transform(const VMatrix &m)
44 if (m.isIdentity()) return;
45 for (auto i = 0; i < ft.n_points; i++) {
46 pt = m.map(VPointF(ft.points[i].x/64.0, ft.points[i].y/64.0));
47 ft.points[i].x = TO_FT_COORD(pt.x());
48 ft.points[i].y = TO_FT_COORD(pt.y());
52 void FTOutline::moveTo(const VPointF &pt)
54 ft.points[ft.n_points].x = TO_FT_COORD(pt.x());
55 ft.points[ft.n_points].y = TO_FT_COORD(pt.y());
56 ft.tags[ft.n_points] = SW_FT_CURVE_TAG_ON;
58 ft.contours[ft.n_contours] = ft.n_points - 1;
65 void FTOutline::lineTo(const VPointF &pt)
67 ft.points[ft.n_points].x = TO_FT_COORD(pt.x());
68 ft.points[ft.n_points].y = TO_FT_COORD(pt.y());
69 ft.tags[ft.n_points] = SW_FT_CURVE_TAG_ON;
74 void FTOutline::cubicTo(const VPointF &cp1, const VPointF &cp2, const VPointF ep)
76 ft.points[ft.n_points].x = TO_FT_COORD(cp1.x());
77 ft.points[ft.n_points].y = TO_FT_COORD(cp1.y());
78 ft.tags[ft.n_points] = SW_FT_CURVE_TAG_CUBIC;
81 ft.points[ft.n_points].x = TO_FT_COORD(cp2.x());
82 ft.points[ft.n_points].y = TO_FT_COORD(cp2.y());
83 ft.tags[ft.n_points] = SW_FT_CURVE_TAG_CUBIC;
86 ft.points[ft.n_points].x = TO_FT_COORD(ep.x());
87 ft.points[ft.n_points].y = TO_FT_COORD(ep.y());
88 ft.tags[ft.n_points] = SW_FT_CURVE_TAG_ON;
92 void FTOutline::close()
96 index = ft.contours[ft.n_contours - 1] + 1;
101 // make sure atleast 1 point exists in the segment.
102 if (ft.n_points == index) {
107 ft.points[ft.n_points].x = ft.points[index].x;
108 ft.points[ft.n_points].y = ft.points[index].y;
109 ft.tags[ft.n_points] = SW_FT_CURVE_TAG_ON;
114 void FTOutline::end()
117 ft.contours[ft.n_contours] = ft.n_points - 1;
122 struct VRasterPrivate
125 VRle generateFillInfoAsync(const SW_FT_Outline *outline);
126 VRle generateStrokeInfoAsync(const SW_FT_Outline *outline, SW_FT_Stroker_LineCap cap,
127 SW_FT_Stroker_LineJoin join,
128 int width, int meterLimit,
131 std::mutex m_rasterAcess;
132 std::mutex m_strokerAcess;
133 SW_FT_Raster m_raster;
134 SW_FT_Stroker m_stroker;
144 rleGenerationCb( int count, const SW_FT_Span* spans,void *user)
146 VRle *rle = (VRle *) user;
147 VRle::Span *rleSpan = (VRle::Span *)spans;
148 rle->addSpan(rleSpan, count);
151 VRle VRasterPrivate::generateFillInfoAsync(const SW_FT_Outline *outline)
153 m_rasterAcess.lock();
155 SW_FT_Raster_Params params;
157 params.flags = SW_FT_RASTER_FLAG_DIRECT | SW_FT_RASTER_FLAG_AA ;
158 params.gray_spans = &rleGenerationCb;
160 params.source = outline;
162 sw_ft_grays_raster.raster_render(m_raster, ¶ms);
164 m_rasterAcess.unlock();
169 VRle VRasterPrivate::generateStrokeInfoAsync(const SW_FT_Outline *outline, SW_FT_Stroker_LineCap cap,
170 SW_FT_Stroker_LineJoin join,
171 int width, int meterLimit,
174 m_strokerAcess.lock();
176 SW_FT_Outline strokeOutline = { 0, 0, nullptr, nullptr, nullptr, SW_FT_OUTLINE_NONE };
178 SW_FT_Stroker_Set(m_stroker, width, cap, join, meterLimit);
179 SW_FT_Stroker_ParseOutline(m_stroker, outline, !closed);
180 SW_FT_Stroker_GetCounts(m_stroker,&points, &contors);
182 strokeOutline.points = (SW_FT_Vector *) calloc(points, sizeof(SW_FT_Vector));
183 strokeOutline.tags = (char *) calloc(points, sizeof(char));
184 strokeOutline.contours = (short *) calloc(contors, sizeof(short));
186 SW_FT_Stroker_Export(m_stroker, &strokeOutline);
188 m_strokerAcess.unlock();
190 VRle rle = generateFillInfoAsync(&strokeOutline);
192 // cleanup the outline data.
193 free(strokeOutline.points);
194 free(strokeOutline.tags);
195 free(strokeOutline.contours);
203 d = new VRasterPrivate;
204 sw_ft_grays_raster.raster_new(&d->m_raster);
205 SW_FT_Stroker_New(&d->m_stroker);
206 SW_FT_Stroker_Set(d->m_stroker, 1 << 6,
207 SW_FT_STROKER_LINECAP_BUTT, SW_FT_STROKER_LINEJOIN_MITER, 0);
212 sw_ft_grays_raster.raster_done(d->m_raster);
213 SW_FT_Stroker_Done(d->m_stroker);
216 void VRaster::deleteFTOutline(FTOutline *outline)
221 FTOutline *VRaster::toFTOutline(const VPath &path)
226 const std::vector<VPath::Element> &elements = path.elements();
227 const std::vector<VPointF> &points = path.points();
229 FTOutline *outline = new FTOutline(points.size(), path.segments());
232 for(auto element : elements) {
234 case VPath::Element::MoveTo:
235 outline->moveTo(points[index]);
238 case VPath::Element::LineTo:
239 outline->lineTo(points[index]);
242 case VPath::Element::CubicTo:
243 outline->cubicTo(points[index], points[index+1], points[index+2]);
246 case VPath::Element::Close:
257 VRle VRaster::generateFillInfo(const FTOutline *outline, FillRule fillRule)
259 int fillRuleFlag = SW_FT_OUTLINE_NONE;
261 case FillRule::EvenOdd:
262 fillRuleFlag = SW_FT_OUTLINE_EVEN_ODD_FILL;
265 fillRuleFlag = SW_FT_OUTLINE_NONE;
268 FTOutline *outlineRef = const_cast<FTOutline *>(outline);
269 outlineRef->ft.flags = fillRuleFlag;
270 return d->generateFillInfoAsync(&outlineRef->ft);
273 VRle VRaster::generateStrokeInfo(const FTOutline *outline, CapStyle cap, JoinStyle join,
274 float width, float meterLimit)
276 SW_FT_Stroker_LineCap ftCap;
277 SW_FT_Stroker_LineJoin ftJoin;
280 SW_FT_Bool ftbool = (SW_FT_Bool) outline->closed;
282 // map strokeWidth to freetype. It uses as the radius of the pen not the diameter
284 // convert to freetype co-ordinate
285 ftWidth = int(width * 64);
286 ftMeterLimit = int(meterLimit * 64);
288 // map to freetype capstyle
291 case CapStyle::Square:
292 ftCap = SW_FT_STROKER_LINECAP_SQUARE;
294 case CapStyle::Round:
295 ftCap = SW_FT_STROKER_LINECAP_ROUND;
298 ftCap = SW_FT_STROKER_LINECAP_BUTT;
303 case JoinStyle::Bevel:
304 ftJoin = SW_FT_STROKER_LINEJOIN_BEVEL;
306 case JoinStyle::Round:
307 ftJoin = SW_FT_STROKER_LINEJOIN_ROUND;
310 ftJoin = SW_FT_STROKER_LINEJOIN_MITER;
314 return d->generateStrokeInfoAsync(&outline->ft, ftCap, ftJoin,
315 ftWidth, ftMeterLimit, ftbool);