Cnass commited on
Commit
3c44be2
·
verified ·
1 Parent(s): c81773e

Update app/font_engine.py

Browse files
Files changed (1) hide show
  1. app/font_engine.py +59 -30
app/font_engine.py CHANGED
@@ -199,6 +199,36 @@ def contours_to_svg_path(contours: list[ContourOps]) -> str:
199
  # Aksan kaynağı bulma (standalone glyph / donor / synthetic)
200
  # --------------------------------------------------------------------------
201
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
  def _find_standalone_accent(font: TTFont, cmap: dict[int, str], accent: str) -> Optional[str]:
203
  for cp in R.ACCENT_UNICODE_CANDIDATES.get(accent, []):
204
  name = cmap.get(cp)
@@ -224,17 +254,8 @@ def _extract_donor_accent(font: TTFont, cmap: dict[int, str], accent: str) -> Op
224
  contours = decompose_glyph(font, name)
225
  if len(contours) < 2:
226
  continue # tek konturlu glyph'ten aksan ayıklanamaz
227
- picked = []
228
- for c in contours:
229
- b = contours_bounds([c])
230
- if not b:
231
- continue
232
- _, c_ymin, _, c_ymax = b
233
- if placement == "above" and c_ymin > xh * 0.72:
234
- picked.append(c)
235
- elif placement == "below" and c_ymax < upm * 0.08:
236
- picked.append(c)
237
- if picked:
238
  return donor_char, picked
239
  return None
240
 
@@ -246,25 +267,39 @@ def resolve_accent(font: TTFont, cmap: dict[int, str], accent: str, base_bounds:
246
  "contours": [...], "bounds": (xmin,ymin,xmax,ymax) | None,
247
  "warning": str | None}
248
  """
 
 
249
  standalone = _find_standalone_accent(font, cmap, accent)
250
  if standalone:
251
  contours = decompose_glyph(font, standalone)
252
- return {
253
- "kind": "glyph", "ref": standalone, "contours": contours,
254
- "bounds": contours_bounds(contours), "warning": None,
255
- }
 
 
 
 
 
 
 
 
 
 
 
256
 
257
  donor_result = _extract_donor_accent(font, cmap, accent)
258
  if donor_result:
259
  donor_char, contours = donor_result
 
 
 
260
  return {
261
  "kind": "donor", "ref": donor_char, "contours": contours,
262
- "bounds": contours_bounds(contours),
263
- "warning": f"Standalone '{accent}' glyph'i bulunamadı; şekil '{donor_char}' karakterinden otomatik ayıklandı.",
264
  }
265
 
266
  base_width = (base_bounds[2] - base_bounds[0]) if base_bounds else units_per_em(font) * 0.5
267
- upm = units_per_em(font)
268
  raw_contours = synthetic_accent_contours(accent, base_width, upm)
269
  contours: list[ContourOps] = []
270
  for poly in raw_contours:
@@ -273,10 +308,13 @@ def resolve_accent(font: TTFont, cmap: dict[int, str], accent: str, base_bounds:
273
  ops.append(("lineTo", (pt,)))
274
  ops.append(("closePath", ()))
275
  contours.append(ops)
 
 
 
276
  return {
277
  "kind": "synthetic", "ref": accent, "contours": contours,
278
  "bounds": contours_bounds(contours),
279
- "warning": f"Fontta '{accent}' için hiçbir bileşen bulunamadı; yerleşik basit bir vektör şekli kullanıldı. Görsel uyum için elle bir aksan glyph'i seçmeniz önerilir.",
280
  }
281
 
282
 
@@ -292,17 +330,8 @@ def resolve_accent_by_source(font: TTFont, cmap: dict[int, str], accent_source:
292
  xh = x_height(font)
293
  placement = "below" if accent_type == "cedilla" else "above"
294
  contours = decompose_glyph(font, name)
295
- picked = []
296
- for c in contours:
297
- b = contours_bounds([c])
298
- if not b:
299
- continue
300
- _, c_ymin, _, c_ymax = b
301
- if placement == "above" and c_ymin > xh * 0.72:
302
- picked.append(c)
303
- elif placement == "below" and c_ymax < upm * 0.08:
304
- picked.append(c)
305
- if picked:
306
  return {"kind": "donor", "ref": donor_char, "contours": picked, "bounds": contours_bounds(picked), "warning": None}
307
  return resolve_accent(font, cmap, accent_type, base_bounds)
308
  if accent_source.startswith(R.SYNTHETIC_PREFIX):
 
199
  # Aksan kaynağı bulma (standalone glyph / donor / synthetic)
200
  # --------------------------------------------------------------------------
201
 
202
+ def _is_plausible_accent_bounds(bounds: Optional[Bounds], upm: float) -> bool:
203
+ """Bir aksan işaretinin akla yatkın boyutta olup olmadığını kontrol eder.
204
+
205
+ Bazı fontlarda 'cedilla'/'dieresis' gibi standart aksan glyph adları
206
+ yanlışlıkla alakasız, tam boyutlu bir şekle (ör. hatalı bir precomposed
207
+ harfe) işaret edebiliyor. Gerçek aksan işaretleri her zaman harfe göre
208
+ küçüktür (en büyük gerçek örnekler bile ~%30 UPM civarında); bu yüzden
209
+ %45 UPM üzerindeki bir "aksan" güvenilmez kabul edilip yoksayılır."""
210
+ if not bounds:
211
+ return False
212
+ width = bounds[2] - bounds[0]
213
+ height = bounds[3] - bounds[1]
214
+ limit = upm * 0.45
215
+ return width <= limit and height <= limit
216
+
217
+
218
+ def _pick_accent_contours(contours: list[ContourOps], placement: str, upm: float, xh: float) -> list[ContourOps]:
219
+ picked = []
220
+ for c in contours:
221
+ b = contours_bounds([c])
222
+ if not b:
223
+ continue
224
+ _, c_ymin, _, c_ymax = b
225
+ if placement == "above" and c_ymin > xh * 0.72:
226
+ picked.append(c)
227
+ elif placement == "below" and c_ymax < upm * 0.08:
228
+ picked.append(c)
229
+ return picked
230
+
231
+
232
  def _find_standalone_accent(font: TTFont, cmap: dict[int, str], accent: str) -> Optional[str]:
233
  for cp in R.ACCENT_UNICODE_CANDIDATES.get(accent, []):
234
  name = cmap.get(cp)
 
254
  contours = decompose_glyph(font, name)
255
  if len(contours) < 2:
256
  continue # tek konturlu glyph'ten aksan ayıklanamaz
257
+ picked = _pick_accent_contours(contours, placement, upm, xh)
258
+ if picked and _is_plausible_accent_bounds(contours_bounds(picked), upm):
 
 
 
 
 
 
 
 
 
259
  return donor_char, picked
260
  return None
261
 
 
267
  "contours": [...], "bounds": (xmin,ymin,xmax,ymax) | None,
268
  "warning": str | None}
269
  """
270
+ upm = units_per_em(font)
271
+ rejected_standalone: Optional[str] = None
272
  standalone = _find_standalone_accent(font, cmap, accent)
273
  if standalone:
274
  contours = decompose_glyph(font, standalone)
275
+ bounds = contours_bounds(contours)
276
+ if _is_plausible_accent_bounds(bounds, upm):
277
+ return {
278
+ "kind": "glyph", "ref": standalone, "contours": contours,
279
+ "bounds": bounds, "warning": None,
280
+ }
281
+ # Glyph var ama bir aksan işareti için mantıksız büyük (muhtemelen
282
+ # yanlış adlandırılmış/bozuk) - yoksay, donor/sentetik'e devam et.
283
+ rejected_standalone = standalone
284
+
285
+ size_note = (
286
+ f"Fontta '{accent}' adıyla bir glyph var ama boyutu bir aksan işareti için "
287
+ f"mantıksız derecede büyük (muhtemelen yanlış adlandırılmış/bozuk bir glyph), bu yüzden yoksayıldı. "
288
+ if rejected_standalone else ""
289
+ )
290
 
291
  donor_result = _extract_donor_accent(font, cmap, accent)
292
  if donor_result:
293
  donor_char, contours = donor_result
294
+ warning = size_note + f"'{donor_char}' karakterinden otomatik ayıklanan şekil kullanıldı."
295
+ if not size_note:
296
+ warning = f"Standalone '{accent}' glyph'i bulunamadı; şekil '{donor_char}' karakterinden otomatik ayıklandı."
297
  return {
298
  "kind": "donor", "ref": donor_char, "contours": contours,
299
+ "bounds": contours_bounds(contours), "warning": warning,
 
300
  }
301
 
302
  base_width = (base_bounds[2] - base_bounds[0]) if base_bounds else units_per_em(font) * 0.5
 
303
  raw_contours = synthetic_accent_contours(accent, base_width, upm)
304
  contours: list[ContourOps] = []
305
  for poly in raw_contours:
 
308
  ops.append(("lineTo", (pt,)))
309
  ops.append(("closePath", ()))
310
  contours.append(ops)
311
+ warning = size_note + "Fontta uygun bir bileşen bulunamadığından yerleşik basit bir vektör şekli kullanıldı. Görsel uyum için elle bir aksan glyph'i seçmeniz önerilir."
312
+ if not size_note:
313
+ warning = f"Fontta '{accent}' için hiçbir bileşen bulunamadı; yerleşik basit bir vektör şekli kullanıldı. Görsel uyum için elle bir aksan glyph'i seçmeniz önerilir."
314
  return {
315
  "kind": "synthetic", "ref": accent, "contours": contours,
316
  "bounds": contours_bounds(contours),
317
+ "warning": warning,
318
  }
319
 
320
 
 
330
  xh = x_height(font)
331
  placement = "below" if accent_type == "cedilla" else "above"
332
  contours = decompose_glyph(font, name)
333
+ picked = _pick_accent_contours(contours, placement, upm, xh)
334
+ if picked and _is_plausible_accent_bounds(contours_bounds(picked), upm):
 
 
 
 
 
 
 
 
 
335
  return {"kind": "donor", "ref": donor_char, "contours": picked, "bounds": contours_bounds(picked), "warning": None}
336
  return resolve_accent(font, cmap, accent_type, base_bounds)
337
  if accent_source.startswith(R.SYNTHETIC_PREFIX):