OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2000 Dirk Mueller (mueller@kde.org) | 4 * (C) 2000 Dirk Mueller (mueller@kde.org) |
5 * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved. | 5 * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved. |
6 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved. | 6 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved. |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
250 STACK_ALLOCATED() | 250 STACK_ALLOCATED() |
251 public: | 251 public: |
252 GlyphBufferBloberizer(const GlyphBuffer& buffer, | 252 GlyphBufferBloberizer(const GlyphBuffer& buffer, |
253 const Font* font, | 253 const Font* font, |
254 float deviceScaleFactor) | 254 float deviceScaleFactor) |
255 : m_buffer(buffer), | 255 : m_buffer(buffer), |
256 m_font(font), | 256 m_font(font), |
257 m_deviceScaleFactor(deviceScaleFactor), | 257 m_deviceScaleFactor(deviceScaleFactor), |
258 m_hasVerticalOffsets(buffer.hasVerticalOffsets()), | 258 m_hasVerticalOffsets(buffer.hasVerticalOffsets()), |
259 m_index(0), | 259 m_index(0), |
260 m_endIndex(m_buffer.size()), | |
260 m_blobCount(0), | 261 m_blobCount(0), |
261 m_rotation(buffer.isEmpty() ? NoRotation : computeBlobRotation( | 262 m_rotation(buffer.isEmpty() ? NoRotation : computeBlobRotation( |
262 buffer.fontDataAt(0))) {} | 263 buffer.fontDataAt(0))), |
264 m_skipGlyphs(nullptr) {} | |
263 | 265 |
264 bool done() const { return m_index >= m_buffer.size(); } | 266 bool done() const { return m_index >= m_endIndex; } |
265 unsigned blobCount() const { return m_blobCount; } | 267 unsigned blobCount() const { return m_blobCount; } |
266 | 268 |
267 std::pair<sk_sp<SkTextBlob>, BlobRotation> next() { | 269 std::pair<sk_sp<SkTextBlob>, BlobRotation> next() { |
268 ASSERT(!done()); | 270 ASSERT(!done()); |
269 const BlobRotation currentRotation = m_rotation; | 271 const BlobRotation currentRotation = m_rotation; |
270 | 272 |
271 while (m_index < m_buffer.size()) { | 273 while (m_index < m_endIndex) { |
274 if (m_skipGlyphs) { | |
275 while (m_index < m_endIndex && (*m_skipGlyphs)[m_index]) | |
276 m_index++; | |
277 } | |
278 | |
272 const SimpleFontData* fontData = m_buffer.fontDataAt(m_index); | 279 const SimpleFontData* fontData = m_buffer.fontDataAt(m_index); |
273 ASSERT(fontData); | 280 ASSERT(fontData); |
274 | 281 |
275 const BlobRotation newRotation = computeBlobRotation(fontData); | 282 const BlobRotation newRotation = computeBlobRotation(fontData); |
276 if (newRotation != m_rotation) { | 283 if (newRotation != m_rotation) { |
277 // We're switching to an orientation which requires a different rotation | 284 // We're switching to an orientation which requires a different rotation |
278 // => emit the pending blob (and start a new one with the new | 285 // => emit the pending blob (and start a new one with the new |
279 // rotation). | 286 // rotation). |
280 m_rotation = newRotation; | 287 m_rotation = newRotation; |
281 break; | 288 break; |
282 } | 289 } |
283 | 290 |
284 const unsigned start = m_index++; | 291 const unsigned start = m_index++; |
285 while (m_index < m_buffer.size() && | 292 while (m_index < m_endIndex && m_buffer.fontDataAt(m_index) == fontData && |
286 m_buffer.fontDataAt(m_index) == fontData) | 293 !(m_skipGlyphs && (*m_skipGlyphs)[m_index])) |
287 m_index++; | 294 m_index++; |
288 | 295 |
289 appendRun(start, m_index - start, fontData); | 296 appendRun(start, m_index - start, fontData); |
290 } | 297 } |
291 | 298 |
292 m_blobCount++; | 299 m_blobCount++; |
293 return std::make_pair(m_builder.make(), currentRotation); | 300 return std::make_pair(m_builder.make(), currentRotation); |
294 } | 301 } |
295 | 302 |
303 void setSkipGlyphs(const Vector<bool>* skipGlyphs) { | |
drott
2017/01/02 15:07:46
As mentioned below, I'd prefer if we use the glyph
| |
304 m_skipGlyphs = skipGlyphs; | |
305 m_endIndex = m_buffer.size(); | |
306 if (m_skipGlyphs) { | |
307 while (m_endIndex > 0 && (*m_skipGlyphs)[m_endIndex - 1]) | |
308 m_endIndex--; | |
309 } | |
310 } | |
311 | |
296 private: | 312 private: |
297 static BlobRotation computeBlobRotation(const SimpleFontData* font) { | 313 static BlobRotation computeBlobRotation(const SimpleFontData* font) { |
298 // For vertical upright text we need to compensate the inherited 90deg CW | 314 // For vertical upright text we need to compensate the inherited 90deg CW |
299 // rotation (using a 90deg CCW rotation). | 315 // rotation (using a 90deg CCW rotation). |
300 return (font->platformData().isVerticalAnyUpright() && font->verticalData()) | 316 return (font->platformData().isVerticalAnyUpright() && font->verticalData()) |
301 ? CCWRotation | 317 ? CCWRotation |
302 : NoRotation; | 318 : NoRotation; |
303 } | 319 } |
304 | 320 |
305 void appendRun(unsigned start, | 321 void appendRun(unsigned start, |
(...skipping 30 matching lines...) Expand all Loading... | |
336 } | 352 } |
337 } | 353 } |
338 | 354 |
339 const GlyphBuffer& m_buffer; | 355 const GlyphBuffer& m_buffer; |
340 const Font* m_font; | 356 const Font* m_font; |
341 const float m_deviceScaleFactor; | 357 const float m_deviceScaleFactor; |
342 const bool m_hasVerticalOffsets; | 358 const bool m_hasVerticalOffsets; |
343 | 359 |
344 SkTextBlobBuilder m_builder; | 360 SkTextBlobBuilder m_builder; |
345 unsigned m_index; | 361 unsigned m_index; |
362 unsigned m_endIndex; | |
346 unsigned m_blobCount; | 363 unsigned m_blobCount; |
347 BlobRotation m_rotation; | 364 BlobRotation m_rotation; |
365 const Vector<bool>* m_skipGlyphs; | |
drott
2017/01/02 15:07:46
I believe we can use this from m_buffer directly?
| |
348 }; | 366 }; |
349 | 367 |
350 } // anonymous namespace | 368 } // anonymous namespace |
351 | 369 |
352 void Font::drawGlyphBuffer(SkCanvas* canvas, | 370 void Font::drawGlyphBuffer(SkCanvas* canvas, |
353 const SkPaint& paint, | 371 const SkPaint& paint, |
354 const TextRunPaintInfo& runInfo, | 372 const TextRunPaintInfo& runInfo, |
355 const GlyphBuffer& glyphBuffer, | 373 const GlyphBuffer& glyphBuffer, |
356 const FloatPoint& point, | 374 const FloatPoint& point, |
357 float deviceScaleFactor) const { | 375 float deviceScaleFactor) const { |
(...skipping 26 matching lines...) Expand all Loading... | |
384 *runInfo.cachedTextBlob = std::move(blob.first); | 402 *runInfo.cachedTextBlob = std::move(blob.first); |
385 ASSERT(*runInfo.cachedTextBlob); | 403 ASSERT(*runInfo.cachedTextBlob); |
386 } | 404 } |
387 } | 405 } |
388 | 406 |
389 static int getInterceptsFromBloberizer(const GlyphBuffer& glyphBuffer, | 407 static int getInterceptsFromBloberizer(const GlyphBuffer& glyphBuffer, |
390 const Font* font, | 408 const Font* font, |
391 const SkPaint& paint, | 409 const SkPaint& paint, |
392 float deviceScaleFactor, | 410 float deviceScaleFactor, |
393 const std::tuple<float, float>& bounds, | 411 const std::tuple<float, float>& bounds, |
412 const Vector<bool>* skipGlyphs, | |
drott
2017/01/02 15:07:46
See below, I think we can remove this argument...
| |
394 SkScalar* interceptsBuffer) { | 413 SkScalar* interceptsBuffer) { |
395 SkScalar boundsArray[2] = {std::get<0>(bounds), std::get<1>(bounds)}; | 414 SkScalar boundsArray[2] = {std::get<0>(bounds), std::get<1>(bounds)}; |
396 GlyphBufferBloberizer bloberizer(glyphBuffer, font, deviceScaleFactor); | 415 GlyphBufferBloberizer bloberizer(glyphBuffer, font, deviceScaleFactor); |
416 bloberizer.setSkipGlyphs(skipGlyphs); | |
drott
2017/01/02 15:07:46
and this explicit transfer of the skipExceptions v
| |
397 std::pair<sk_sp<SkTextBlob>, BlobRotation> blob; | 417 std::pair<sk_sp<SkTextBlob>, BlobRotation> blob; |
398 | 418 |
399 int numIntervals = 0; | 419 int numIntervals = 0; |
400 while (!bloberizer.done()) { | 420 while (!bloberizer.done()) { |
401 blob = bloberizer.next(); | 421 blob = bloberizer.next(); |
402 DCHECK(blob.first); | 422 DCHECK(blob.first); |
403 | 423 |
404 // GlyphBufferBloberizer splits for a new blob rotation, but does not split | 424 // GlyphBufferBloberizer splits for a new blob rotation, but does not split |
405 // for a change in font. A TextBlob can contain runs with differing fonts | 425 // for a change in font. A TextBlob can contain runs with differing fonts |
406 // and the getTextBlobIntercepts method handles multiple fonts for us. For | 426 // and the getTextBlobIntercepts method handles multiple fonts for us. For |
(...skipping 25 matching lines...) Expand all Loading... | |
432 if (!numIntervals) | 452 if (!numIntervals) |
433 return; | 453 return; |
434 DCHECK_EQ(numIntervals % 2, 0); | 454 DCHECK_EQ(numIntervals % 2, 0); |
435 intercepts.resize(numIntervals / 2); | 455 intercepts.resize(numIntervals / 2); |
436 paint.getTextBlobIntercepts(runInfo.cachedTextBlob->get(), boundsArray, | 456 paint.getTextBlobIntercepts(runInfo.cachedTextBlob->get(), boundsArray, |
437 reinterpret_cast<SkScalar*>(intercepts.data())); | 457 reinterpret_cast<SkScalar*>(intercepts.data())); |
438 return; | 458 return; |
439 } | 459 } |
440 | 460 |
441 GlyphBuffer glyphBuffer; | 461 GlyphBuffer glyphBuffer; |
442 buildGlyphBuffer(runInfo, glyphBuffer); | 462 const Vector<bool>* skipGlyphs = nullptr; |
463 if (runInfo.run.is8Bit()) { | |
464 // All characters in Latin-1 should skip inks, so no skipInkExceptions. | |
465 buildGlyphBuffer(runInfo, glyphBuffer); | |
466 } else { | |
467 glyphBuffer.saveSkipInkExceptions(); | |
468 buildGlyphBuffer(runInfo, glyphBuffer); | |
469 skipGlyphs = &glyphBuffer.skipInkExceptions(); | |
drott
2017/01/02 15:07:46
Using state in the GlyphBuffer for shouldSaveSkipI
| |
470 } | |
443 | 471 |
444 // Get the number of intervals, without copying the actual values by | 472 // Get the number of intervals, without copying the actual values by |
445 // specifying nullptr for the buffer, following the Skia allocation model for | 473 // specifying nullptr for the buffer, following the Skia allocation model for |
446 // retrieving text intercepts. | 474 // retrieving text intercepts. |
447 int numIntervals = getInterceptsFromBloberizer( | 475 int numIntervals = getInterceptsFromBloberizer( |
448 glyphBuffer, this, paint, deviceScaleFactor, bounds, nullptr); | 476 glyphBuffer, this, paint, deviceScaleFactor, bounds, skipGlyphs, nullptr); |
449 if (!numIntervals) | 477 if (!numIntervals) |
450 return; | 478 return; |
451 DCHECK_EQ(numIntervals % 2, 0); | 479 DCHECK_EQ(numIntervals % 2, 0); |
452 intercepts.resize(numIntervals / 2); | 480 intercepts.resize(numIntervals / 2); |
453 | 481 |
454 getInterceptsFromBloberizer(glyphBuffer, this, paint, deviceScaleFactor, | 482 getInterceptsFromBloberizer(glyphBuffer, this, paint, deviceScaleFactor, |
455 bounds, | 483 bounds, skipGlyphs, |
456 reinterpret_cast<SkScalar*>(intercepts.data())); | 484 reinterpret_cast<SkScalar*>(intercepts.data())); |
457 } | 485 } |
458 | 486 |
459 static inline FloatRect pixelSnappedSelectionRect(FloatRect rect) { | 487 static inline FloatRect pixelSnappedSelectionRect(FloatRect rect) { |
460 // Using roundf() rather than ceilf() for the right edge as a compromise to | 488 // Using roundf() rather than ceilf() for the right edge as a compromise to |
461 // ensure correct caret positioning. | 489 // ensure correct caret positioning. |
462 float roundedX = roundf(rect.x()); | 490 float roundedX = roundf(rect.x()); |
463 return FloatRect(roundedX, rect.y(), roundf(rect.maxX() - roundedX), | 491 return FloatRect(roundedX, rect.y(), roundf(rect.maxX() - roundedX), |
464 rect.height()); | 492 rect.height()); |
465 } | 493 } |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
620 | 648 |
621 bool Font::loadingCustomFonts() const { | 649 bool Font::loadingCustomFonts() const { |
622 return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts(); | 650 return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts(); |
623 } | 651 } |
624 | 652 |
625 bool Font::isFallbackValid() const { | 653 bool Font::isFallbackValid() const { |
626 return !m_fontFallbackList || m_fontFallbackList->isValid(); | 654 return !m_fontFallbackList || m_fontFallbackList->isValid(); |
627 } | 655 } |
628 | 656 |
629 } // namespace blink | 657 } // namespace blink |
OLD | NEW |