• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KHTML

  • khtml
  • svg
SVGFont.cpp
Go to the documentation of this file.
1
21#include "config.h"
22
23#if ENABLE(SVG_FONTS)
24#include "Font.h"
25
26#include "CSSFontSelector.h"
27#include "GraphicsContext.h"
28#include "RenderObject.h"
29#include "SimpleFontData.h"
30#include "SVGAltGlyphElement.h"
31#include "SVGFontData.h"
32#include "SVGGlyphElement.h"
33#include "SVGGlyphMap.h"
34#include "SVGFontElement.h"
35#include "SVGFontFaceElement.h"
36#include "SVGMissingGlyphElement.h"
37#include "SVGPaintServer.h"
38#include "SVGPaintServerSolid.h"
39#include "XMLNames.h"
40
41using namespace WTF::Unicode;
42
43namespace WebCore {
44
45static inline float convertEmUnitToPixel(float fontSize, float unitsPerEm, float value)
46{
47 if (unitsPerEm == 0.0f)
48 return 0.0f;
49
50 return value * fontSize / unitsPerEm;
51}
52
53static inline bool isVerticalWritingMode(const SVGRenderStyle* style)
54{
55 return style->writingMode() == WM_TBRL || style->writingMode() == WM_TB;
56}
57
58// Helper functions to determine the arabic character forms (initial, medial, terminal, isolated)
59enum ArabicCharShapingMode {
60 SNone = 0,
61 SRight = 1,
62 SDual = 2
63};
64
65static const ArabicCharShapingMode s_arabicCharShapingMode[222] = {
66 SRight, SRight, SRight, SRight, SDual , SRight, SDual , SRight, SDual , SDual , SDual , SDual , SDual , SRight, /* 0x0622 - 0x062F */
67 SRight, SRight, SRight, SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SNone , SNone , SNone , SNone , SNone , /* 0x0630 - 0x063F */
68 SNone , SDual , SDual , SDual , SDual , SDual , SDual , SRight, SDual , SDual , SNone , SNone , SNone , SNone , SNone , SNone , /* 0x0640 - 0x064F */
69 SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , /* 0x0650 - 0x065F */
70 SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , /* 0x0660 - 0x066F */
71 SNone , SRight, SRight, SRight, SNone , SRight, SRight, SRight, SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , /* 0x0670 - 0x067F */
72 SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, /* 0x0680 - 0x068F */
73 SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, SDual , SDual , SDual , SDual , SDual , SDual , /* 0x0690 - 0x069F */
74 SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , /* 0x06A0 - 0x06AF */
75 SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , /* 0x06B0 - 0x06BF */
76 SRight, SDual , SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, SDual , SRight, SDual , SRight, /* 0x06C0 - 0x06CF */
77 SDual , SDual , SRight, SRight, SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , /* 0x06D0 - 0x06DF */
78 SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , /* 0x06E0 - 0x06EF */
79 SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SDual , SDual , SDual , SNone , SNone , SNone /* 0x06F0 - 0x06FF */
80};
81
82static inline SVGGlyphIdentifier::ArabicForm processArabicFormDetection(const UChar& curChar, bool& lastCharShapesRight, SVGGlyphIdentifier::ArabicForm* prevForm)
83{
84 SVGGlyphIdentifier::ArabicForm curForm;
85
86 ArabicCharShapingMode shapingMode = SNone;
87 if (curChar >= 0x0622 && curChar <= 0x06FF)
88 shapingMode = s_arabicCharShapingMode[curChar - 0x0622];
89
90 // Use a simple state machine to identify the actual arabic form
91 // It depends on the order of the arabic form enum:
92 // enum ArabicForm { None = 0, Isolated, Terminal, Initial, Medial };
93
94 if (lastCharShapesRight && shapingMode == SDual) {
95 if (prevForm) {
96 int correctedForm = (int) *prevForm + 1;
97 ASSERT(correctedForm >= SVGGlyphIdentifier::None && correctedForm <= SVGGlyphIdentifier::Medial);
98 *prevForm = static_cast<SVGGlyphIdentifier::ArabicForm>(correctedForm);
99 }
100
101 curForm = SVGGlyphIdentifier::Initial;
102 } else
103 curForm = shapingMode == SNone ? SVGGlyphIdentifier::None : SVGGlyphIdentifier::Isolated;
104
105 lastCharShapesRight = shapingMode != SNone;
106 return curForm;
107}
108
109static Vector<SVGGlyphIdentifier::ArabicForm> charactersWithArabicForm(const String& input, bool rtl)
110{
111 Vector<SVGGlyphIdentifier::ArabicForm> forms;
112 unsigned int length = input.length();
113
114 bool containsArabic = false;
115 for (unsigned int i = 0; i < length; ++i) {
116 if (isArabicChar(input[i])) {
117 containsArabic = true;
118 break;
119 }
120 }
121
122 if (!containsArabic)
123 return forms;
124
125 bool lastCharShapesRight = false;
126
127 // Start identifying arabic forms
128 if (rtl)
129 for (int i = length - 1; i >= 0; --i)
130 forms.prepend(processArabicFormDetection(input[i], lastCharShapesRight, forms.isEmpty() ? 0 : &forms.first()));
131 else
132 for (unsigned int i = 0; i < length; ++i)
133 forms.append(processArabicFormDetection(input[i], lastCharShapesRight, forms.isEmpty() ? 0 : &forms.last()));
134
135 return forms;
136}
137
138static inline bool isCompatibleArabicForm(const SVGGlyphIdentifier& identifier, const Vector<SVGGlyphIdentifier::ArabicForm>& chars, unsigned int startPosition, unsigned int endPosition)
139{
140 if (chars.isEmpty())
141 return true;
142
143 Vector<SVGGlyphIdentifier::ArabicForm>::const_iterator it = chars.begin() + startPosition;
144 Vector<SVGGlyphIdentifier::ArabicForm>::const_iterator end = chars.begin() + endPosition;
145
146 ASSERT(end <= chars.end());
147 for (; it != end; ++it) {
148 if ((*it) != identifier.arabicForm && (*it) != SVGGlyphIdentifier::None)
149 return false;
150 }
151
152 return true;
153}
154
155static inline bool isCompatibleGlyph(const SVGGlyphIdentifier& identifier, bool isVerticalText, const String& language,
156 const Vector<SVGGlyphIdentifier::ArabicForm>& chars, unsigned int startPosition, unsigned int endPosition)
157{
158 bool valid = true;
159
160 // Check whether orientation if glyph fits within the request
161 switch (identifier.orientation) {
162 case SVGGlyphIdentifier::Vertical:
163 valid = isVerticalText;
164 break;
165 case SVGGlyphIdentifier::Horizontal:
166 valid = !isVerticalText;
167 break;
168 case SVGGlyphIdentifier::Both:
169 break;
170 }
171
172 if (!valid)
173 return false;
174
175 // Check whether languages are compatible
176 if (!identifier.languages.isEmpty()) {
177 // This glyph exists only in certain languages, if we're not specifying a
178 // language on the referencing element we're unable to use this glyph.
179 if (language.isEmpty())
180 return false;
181
182 // Split subcode from language, if existent.
183 String languagePrefix;
184
185 int subCodeSeparator = language.find('-');
186 if (subCodeSeparator != -1)
187 languagePrefix = language.left(subCodeSeparator);
188
189 Vector<String>::const_iterator it = identifier.languages.begin();
190 Vector<String>::const_iterator end = identifier.languages.end();
191
192 bool found = false;
193 for (; it != end; ++it) {
194 String cur = (*it);
195
196 if (cur == language || cur == languagePrefix) {
197 found = true;
198 break;
199 }
200 }
201
202 if (!found)
203 return false;
204 }
205
206 // Check whether arabic form is compatible
207 return isCompatibleArabicForm(identifier, chars, startPosition, endPosition);
208}
209
210static inline const SVGFontData* svgFontAndFontFaceElementForFontData(const SimpleFontData* fontData, SVGFontFaceElement*& fontFace, SVGFontElement*& font)
211{
212 ASSERT(fontData->isCustomFont());
213 ASSERT(fontData->isSVGFont());
214
215 const SVGFontData* svgFontData = static_cast<const SVGFontData*>(fontData->svgFontData());
216
217 fontFace = svgFontData->svgFontFaceElement();
218 ASSERT(fontFace);
219
220 font = fontFace->associatedFontElement();
221 return svgFontData;
222}
223
224// Helper class to walk a text run. Lookup a SVGGlyphIdentifier for each character
225// - also respecting possibly defined ligatures - and invoke a callback for each found glyph.
226template<typename SVGTextRunData>
227struct SVGTextRunWalker {
228 typedef bool (*SVGTextRunWalkerCallback)(const SVGGlyphIdentifier&, SVGTextRunData&);
229 typedef void (*SVGTextRunWalkerMissingGlyphCallback)(const TextRun&, SVGTextRunData&);
230
231 SVGTextRunWalker(const SVGFontData* fontData, SVGFontElement* fontElement, SVGTextRunData& data,
232 SVGTextRunWalkerCallback callback, SVGTextRunWalkerMissingGlyphCallback missingGlyphCallback)
233 : m_fontData(fontData)
234 , m_fontElement(fontElement)
235 , m_walkerData(data)
236 , m_walkerCallback(callback)
237 , m_walkerMissingGlyphCallback(missingGlyphCallback)
238 {
239 }
240
241 void walk(const TextRun& run, bool isVerticalText, const String& language, int from, int to)
242 {
243 // Should hold true for SVG text, otherwhise sth. is wrong
244 ASSERT(to - from == run.length());
245
246 Vector<SVGGlyphIdentifier::ArabicForm> chars(charactersWithArabicForm(String(run.data(from), run.length()), run.rtl()));
247
248 SVGGlyphIdentifier identifier;
249 bool foundGlyph = false;
250 int characterLookupRange;
251 int endOfScanRange = to + m_walkerData.extraCharsAvailable;
252
253 bool haveAltGlyph = false;
254 SVGGlyphIdentifier altGlyphIdentifier;
255 if (RenderObject* renderObject = run.referencingRenderObject()) {
256 if (renderObject->element() && renderObject->element()->hasTagName(SVGNames::altGlyphTag)) {
257 SVGGlyphElement* glyphElement = static_cast<SVGAltGlyphElement*>(renderObject->element())->glyphElement();
258 if (glyphElement) {
259 haveAltGlyph = true;
260 altGlyphIdentifier = glyphElement->buildGlyphIdentifier();
261 altGlyphIdentifier.isValid = true;
262 altGlyphIdentifier.nameLength = to - from;
263 }
264 }
265 }
266
267 for (int i = from; i < to; ++i) {
268 // If characterLookupRange is > 0, then the font defined ligatures (length of unicode property value > 1).
269 // We have to check whether the current character & the next character define a ligature. This needs to be
270 // extended to the n-th next character (where n is 'characterLookupRange'), to check for any possible ligature.
271 characterLookupRange = endOfScanRange - i;
272
273 String lookupString(run.data(i), characterLookupRange);
274 Vector<SVGGlyphIdentifier> glyphs;
275 if (haveAltGlyph)
276 glyphs.append(altGlyphIdentifier);
277 else
278 m_fontElement->getGlyphIdentifiersForString(lookupString, glyphs);
279
280 Vector<SVGGlyphIdentifier>::iterator it = glyphs.begin();
281 Vector<SVGGlyphIdentifier>::iterator end = glyphs.end();
282
283 for (; it != end; ++it) {
284 identifier = *it;
285 if (identifier.isValid && isCompatibleGlyph(identifier, isVerticalText, language, chars, i, i + identifier.nameLength)) {
286 ASSERT(characterLookupRange > 0);
287 i += identifier.nameLength - 1;
288 m_walkerData.charsConsumed += identifier.nameLength;
289 m_walkerData.glyphName = identifier.glyphName;
290
291 foundGlyph = true;
292 SVGGlyphElement::inheritUnspecifiedAttributes(identifier, m_fontData);
293 break;
294 }
295 }
296
297 if (!foundGlyph) {
298 ++m_walkerData.charsConsumed;
299 if (SVGMissingGlyphElement* element = m_fontElement->firstMissingGlyphElement()) {
300 // <missing-glyph> element support
301 identifier = SVGGlyphElement::buildGenericGlyphIdentifier(element);
302 SVGGlyphElement::inheritUnspecifiedAttributes(identifier, m_fontData);
303 identifier.isValid = true;
304 } else {
305 // Fallback to system font fallback
306 TextRun subRun(run);
307 subRun.setText(subRun.data(i), 1);
308
309 (*m_walkerMissingGlyphCallback)(subRun, m_walkerData);
310 continue;
311 }
312 }
313
314 if (!(*m_walkerCallback)(identifier, m_walkerData))
315 break;
316
317 foundGlyph = false;
318 }
319 }
320
321private:
322 const SVGFontData* m_fontData;
323 SVGFontElement* m_fontElement;
324 SVGTextRunData& m_walkerData;
325 SVGTextRunWalkerCallback m_walkerCallback;
326 SVGTextRunWalkerMissingGlyphCallback m_walkerMissingGlyphCallback;
327};
328
329// Callback & data structures to compute the width of text using SVG Fonts
330struct SVGTextRunWalkerMeasuredLengthData {
331 int at;
332 int from;
333 int to;
334 int extraCharsAvailable;
335 int charsConsumed;
336 String glyphName;
337
338 float scale;
339 float length;
340 const Font* font;
341};
342
343bool floatWidthUsingSVGFontCallback(const SVGGlyphIdentifier& identifier, SVGTextRunWalkerMeasuredLengthData& data)
344{
345 if (data.at >= data.from && data.at < data.to)
346 data.length += identifier.horizontalAdvanceX * data.scale;
347
348 data.at++;
349 return data.at < data.to;
350}
351
352void floatWidthMissingGlyphCallback(const TextRun& run, SVGTextRunWalkerMeasuredLengthData& data)
353{
354 // Handle system font fallback
355 FontDescription fontDescription(data.font->fontDescription());
356 fontDescription.setFamily(FontFamily());
357 Font font(fontDescription, 0, 0); // spacing handled by SVG text code.
358 font.update(data.font->fontSelector());
359
360 data.length += font.floatWidth(run);
361}
362
363
364SVGFontElement* Font::svgFont() const
365{
366 if (!isSVGFont())
367 return 0;
368
369 SVGFontElement* fontElement = 0;
370 SVGFontFaceElement* fontFaceElement = 0;
371 if (svgFontAndFontFaceElementForFontData(primaryFont(), fontFaceElement, fontElement))
372 return fontElement;
373
374 return 0;
375}
376
377static float floatWidthOfSubStringUsingSVGFont(const Font* font, const TextRun& run, int extraCharsAvailable, int from, int to, int& charsConsumed, String& glyphName)
378{
379 int newFrom = to > from ? from : to;
380 int newTo = to > from ? to : from;
381
382 from = newFrom;
383 to = newTo;
384
385 SVGFontElement* fontElement = 0;
386 SVGFontFaceElement* fontFaceElement = 0;
387
388 if (const SVGFontData* fontData = svgFontAndFontFaceElementForFontData(font->primaryFont(), fontFaceElement, fontElement)) {
389 if (!fontElement)
390 return 0.0f;
391
392 SVGTextRunWalkerMeasuredLengthData data;
393
394 data.font = font;
395 data.at = from;
396 data.from = from;
397 data.to = to;
398 data.extraCharsAvailable = extraCharsAvailable;
399 data.charsConsumed = 0;
400 data.scale = convertEmUnitToPixel(font->size(), fontFaceElement->unitsPerEm(), 1.0f);
401 data.length = 0.0f;
402
403 String language;
404 bool isVerticalText = false; // Holds true for HTML text
405
406 // TODO: language matching & svg glyphs should be possible for HTML text, too.
407 if (RenderObject* renderObject = run.referencingRenderObject()) {
408 isVerticalText = isVerticalWritingMode(renderObject->style()->svgStyle());
409
410 if (SVGElement* element = static_cast<SVGElement*>(renderObject->element()))
411 language = element->getAttribute(XMLNames::langAttr);
412 }
413
414 SVGTextRunWalker<SVGTextRunWalkerMeasuredLengthData> runWalker(fontData, fontElement, data, floatWidthUsingSVGFontCallback, floatWidthMissingGlyphCallback);
415 runWalker.walk(run, isVerticalText, language, 0, run.length());
416 charsConsumed = data.charsConsumed;
417 glyphName = data.glyphName;
418 return data.length;
419 }
420
421 return 0.0f;
422}
423
424float Font::floatWidthUsingSVGFont(const TextRun& run) const
425{
426 int charsConsumed;
427 String glyphName;
428 return floatWidthOfSubStringUsingSVGFont(this, run, 0, 0, run.length(), charsConsumed, glyphName);
429}
430
431float Font::floatWidthUsingSVGFont(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const
432{
433 return floatWidthOfSubStringUsingSVGFont(this, run, extraCharsAvailable, 0, run.length(), charsConsumed, glyphName);
434}
435
436// Callback & data structures to draw text using SVG Fonts
437struct SVGTextRunWalkerDrawTextData {
438 int extraCharsAvailable;
439 int charsConsumed;
440 String glyphName;
441 Vector<SVGGlyphIdentifier> glyphIdentifiers;
442 Vector<UChar> fallbackCharacters;
443};
444
445bool drawTextUsingSVGFontCallback(const SVGGlyphIdentifier& identifier, SVGTextRunWalkerDrawTextData& data)
446{
447 data.glyphIdentifiers.append(identifier);
448 return true;
449}
450
451void drawTextMissingGlyphCallback(const TextRun& run, SVGTextRunWalkerDrawTextData& data)
452{
453 ASSERT(run.length() == 1);
454 data.glyphIdentifiers.append(SVGGlyphIdentifier());
455 data.fallbackCharacters.append(run[0]);
456}
457
458void Font::drawTextUsingSVGFont(GraphicsContext* context, const TextRun& run,
459 const FloatPoint& point, int from, int to) const
460{
461 SVGFontElement* fontElement = 0;
462 SVGFontFaceElement* fontFaceElement = 0;
463
464 if (const SVGFontData* fontData = svgFontAndFontFaceElementForFontData(primaryFont(), fontFaceElement, fontElement)) {
465 if (!fontElement)
466 return;
467
468 SVGTextRunWalkerDrawTextData data;
469 FloatPoint currentPoint = point;
470 float scale = convertEmUnitToPixel(size(), fontFaceElement->unitsPerEm(), 1.0f);
471
472 SVGPaintServer* activePaintServer = run.activePaintServer();
473
474 // If renderObject is not set, we're dealing for HTML text rendered using SVG Fonts.
475 if (!run.referencingRenderObject()) {
476 ASSERT(!activePaintServer);
477
478 // TODO: We're only supporting simple filled HTML text so far.
479 SVGPaintServerSolid* solidPaintServer = SVGPaintServer::sharedSolidPaintServer();
480 solidPaintServer->setColor(context->fillColor());
481
482 activePaintServer = solidPaintServer;
483 }
484
485 ASSERT(activePaintServer);
486
487 int charsConsumed;
488 String glyphName;
489 bool isVerticalText = false;
490 float xStartOffset = floatWidthOfSubStringUsingSVGFont(this, run, 0, run.rtl() ? to : 0, run.rtl() ? run.length() : from, charsConsumed, glyphName);
491 FloatPoint glyphOrigin;
492
493 String language;
494
495 // TODO: language matching & svg glyphs should be possible for HTML text, too.
496 if (run.referencingRenderObject()) {
497 isVerticalText = isVerticalWritingMode(run.referencingRenderObject()->style()->svgStyle());
498
499 if (SVGElement* element = static_cast<SVGElement*>(run.referencingRenderObject()->element()))
500 language = element->getAttribute(XMLNames::langAttr);
501 }
502
503 if (!isVerticalText) {
504 glyphOrigin.setX(fontData->horizontalOriginX() * scale);
505 glyphOrigin.setY(fontData->horizontalOriginY() * scale);
506 }
507
508 data.extraCharsAvailable = 0;
509
510 SVGTextRunWalker<SVGTextRunWalkerDrawTextData> runWalker(fontData, fontElement, data, drawTextUsingSVGFontCallback, drawTextMissingGlyphCallback);
511 runWalker.walk(run, isVerticalText, language, from, to);
512
513 SVGPaintTargetType targetType = context->textDrawingMode() == cTextStroke ? ApplyToStrokeTargetType : ApplyToFillTargetType;
514
515 unsigned numGlyphs = data.glyphIdentifiers.size();
516 unsigned fallbackCharacterIndex = 0;
517 for (unsigned i = 0; i < numGlyphs; ++i) {
518 const SVGGlyphIdentifier& identifier = data.glyphIdentifiers[run.rtl() ? numGlyphs - i - 1 : i];
519 if (identifier.isValid) {
520 // FIXME: Support arbitrary SVG content as glyph (currently limited to <glyph d="..."> situations).
521 if (!identifier.pathData.isEmpty()) {
522 context->save();
523
524 if (isVerticalText) {
525 glyphOrigin.setX(identifier.verticalOriginX * scale);
526 glyphOrigin.setY(identifier.verticalOriginY * scale);
527 }
528
529 context->translate(xStartOffset + currentPoint.x() + glyphOrigin.x(), currentPoint.y() + glyphOrigin.y());
530 context->scale(FloatSize(scale, -scale));
531
532 context->beginPath();
533 context->addPath(identifier.pathData);
534
535 if (activePaintServer->setup(context, run.referencingRenderObject(), targetType)) {
536 // Spec: Any properties specified on a text elements which represents a length, such as the
537 // 'stroke-width' property, might produce surprising results since the length value will be
538 // processed in the coordinate system of the glyph. (TODO: What other lengths? miter-limit? dash-offset?)
539 if (targetType == ApplyToStrokeTargetType && scale != 0.0f)
540 context->setStrokeThickness(context->strokeThickness() / scale);
541
542 activePaintServer->renderPath(context, run.referencingRenderObject(), targetType);
543 activePaintServer->teardown(context, run.referencingRenderObject(), targetType);
544 }
545
546 context->restore();
547 }
548
549 if (isVerticalText)
550 currentPoint.move(0.0f, identifier.verticalAdvanceY * scale);
551 else
552 currentPoint.move(identifier.horizontalAdvanceX * scale, 0.0f);
553 } else {
554 // Handle system font fallback
555 FontDescription fontDescription(context->font().fontDescription());
556 fontDescription.setFamily(FontFamily());
557 Font font(fontDescription, 0, 0); // spacing handled by SVG text code.
558 font.update(context->font().fontSelector());
559
560 TextRun fallbackCharacterRun(run);
561 fallbackCharacterRun.setText(&data.fallbackCharacters[run.rtl() ? data.fallbackCharacters.size() - fallbackCharacterIndex - 1 : fallbackCharacterIndex], 1);
562 font.drawText(context, fallbackCharacterRun, currentPoint);
563
564 if (isVerticalText)
565 currentPoint.move(0.0f, font.floatWidth(fallbackCharacterRun));
566 else
567 currentPoint.move(font.floatWidth(fallbackCharacterRun), 0.0f);
568
569 fallbackCharacterIndex++;
570 }
571 }
572 }
573}
574
575FloatRect Font::selectionRectForTextUsingSVGFont(const TextRun& run, const IntPoint& point, int height, int from, int to) const
576{
577 int charsConsumed;
578 String glyphName;
579
580 return FloatRect(point.x() + floatWidthOfSubStringUsingSVGFont(this, run, 0, run.rtl() ? to : 0, run.rtl() ? run.length() : from, charsConsumed, glyphName),
581 point.y(), floatWidthOfSubStringUsingSVGFont(this, run, 0, from, to, charsConsumed, glyphName), height);
582}
583
584int Font::offsetForPositionForTextUsingSVGFont(const TextRun&, int position, bool includePartialGlyphs) const
585{
586 // TODO: Fix text selection when HTML text is drawn using a SVG Font
587 // We need to integrate the SVG text selection code in the offsetForPosition() framework.
588 // This will also fix a major issue, that SVG Text code can't select arabic strings properly.
589 return 0;
590}
591
592}
593
594#endif
RenderObject.h
SVGAltGlyphElement.h
SVGFontData.h
SVGFontElement.h
SVGFontFaceElement.h
SVGGlyphElement.h
SVGGlyphMap.h
SVGMissingGlyphElement.h
SVGPaintServerSolid.h
SVGPaintServer.h
DOM::DOMString::find
int find(const QChar c, int start=0) const
Definition: dom_string.cpp:154
run
bool run(const KUrl &_url, bool _is_local)
end
const KShortcut & end()
WebCore
Definition: CSSHelper.h:7
WebCore::String
DOM::DOMString String
Definition: PlatformString.h:8
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal