Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Side by Side Diff: src/core/SkDraw.cpp

Issue 1486723004: Revert of Simplify draw one glyph (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2006 The Android Open Source Project 2 * Copyright 2006 The Android Open Source Project
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 #define __STDC_LIMIT_MACROS 7 #define __STDC_LIMIT_MACROS
8 8
9 #include "SkDraw.h" 9 #include "SkDraw.h"
10 #include "SkBlitter.h" 10 #include "SkBlitter.h"
(...skipping 1405 matching lines...) Expand 10 before | Expand all | Expand 10 after
1416 } 1416 }
1417 } 1417 }
1418 1418
1419 // disable warning : local variable used without having been initialized 1419 // disable warning : local variable used without having been initialized
1420 #if defined _WIN32 && _MSC_VER >= 1300 1420 #if defined _WIN32 && _MSC_VER >= 1300
1421 #pragma warning ( push ) 1421 #pragma warning ( push )
1422 #pragma warning ( disable : 4701 ) 1422 #pragma warning ( disable : 4701 )
1423 #endif 1423 #endif
1424 1424
1425 //////////////////////////////////////////////////////////////////////////////// //////////////////// 1425 //////////////////////////////////////////////////////////////////////////////// ////////////////////
1426 struct SkDraw1Glyph {
1427 const SkDraw* fDraw;
1428 const SkRegion* fClip;
1429 const SkAAClip* fAAClip;
1430 SkBlitter* fBlitter;
1431 SkGlyphCache* fCache;
1432 const SkPaint* fPaint;
1433 SkIRect fClipBounds;
1434 /** Half the sampling frequency of the rasterized glyph in x. */
1435 SkScalar fHalfSampleX;
1436 /** Half the sampling frequency of the rasterized glyph in y. */
1437 SkScalar fHalfSampleY;
1426 1438
1427 class DrawOneGlyph { 1439 /** Draws one glyph.
1428 public: 1440 *
1429 DrawOneGlyph(const SkDraw& draw, const SkPaint& paint, SkGlyphCache* cache, SkBlitter* blitter) 1441 * The x and y are pre-biased, so implementations may just truncate them.
1430 : fUseRegionToDraw(UsingRegionToDraw(draw.fRC)) 1442 * i.e. half the sampling frequency has been added.
1431 , fGlyphCache(cache) 1443 * e.g. 1/2 or 1/(2^(SkGlyph::kSubBits+1)) has already been added.
1432 , fBlitter(blitter) 1444 * This added bias can be found in fHalfSampleX,Y.
1433 , fClip(fUseRegionToDraw ? &draw.fRC->bwRgn() : nullptr) 1445 */
1434 , fDraw(draw) 1446 typedef void (*Proc)(const SkDraw1Glyph&, Sk48Dot16 x, Sk48Dot16 y, const Sk Glyph&);
1435 , fPaint(paint)
1436 , fClipBounds(PickClipBounds(draw)) { }
1437 1447
1438 void operator()(const SkGlyph& glyph, SkPoint position, SkPoint rounding) { 1448 Proc init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache,
1439 position += rounding; 1449 const SkPaint&);
1440 Sk48Dot16 fx = SkScalarTo48Dot16(position.fX);
1441 Sk48Dot16 fy = SkScalarTo48Dot16(position.fY);
1442 // Prevent glyphs from being drawn outside of or straddling the edge of device space.
1443 if ((fx >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) ||
1444 (fx >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/) ||
1445 (fy >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) ||
1446 (fy >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)) {
1447 return;
1448 }
1449 1450
1450 int left = Sk48Dot16FloorToInt(fx); 1451 // call this instead of fBlitter->blitMask() since this wrapper will handle
1451 int top = Sk48Dot16FloorToInt(fy); 1452 // the case when the mask is ARGB32_Format
1452 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 1453 //
1453
1454 left += glyph.fLeft;
1455 top += glyph.fTop;
1456
1457 int right = left + glyph.fWidth;
1458 int bottom = top + glyph.fHeight;
1459
1460 SkMask mask;
1461 mask.fBounds.set(left, top, right, bottom);
1462
1463 if (fUseRegionToDraw) {
1464 SkRegion::Cliperator clipper(*fClip, mask.fBounds);
1465
1466 if (!clipper.done() && this->getImageData(glyph, &mask)) {
1467 const SkIRect& cr = clipper.rect();
1468 do {
1469 this->blitMask(mask, cr);
1470 clipper.next();
1471 } while (!clipper.done());
1472 }
1473 } else {
1474 SkIRect storage;
1475 SkIRect* bounds = &mask.fBounds;
1476
1477 // this extra test is worth it, assuming that most of the time it su cceeds
1478 // since we can avoid writing to storage
1479 if (!fClipBounds.containsNoEmptyCheck(mask.fBounds)) {
1480 if (!storage.intersectNoEmptyCheck(mask.fBounds, fClipBounds))
1481 return;
1482 bounds = &storage;
1483 }
1484
1485 if (this->getImageData(glyph, &mask)) {
1486 this->blitMask(mask, *bounds);
1487 }
1488 }
1489 }
1490
1491 private:
1492 static bool UsingRegionToDraw(const SkRasterClip* rClip) {
1493 return rClip->isBW() && !rClip->isRect();
1494 }
1495
1496 static SkIRect PickClipBounds(const SkDraw& draw) {
1497 const SkRasterClip& rasterClip = *draw.fRC;
1498
1499 if (rasterClip.isBW()) {
1500 return rasterClip.bwRgn().getBounds();
1501 } else {
1502 return rasterClip.aaRgn().getBounds();
1503 }
1504 }
1505
1506 bool getImageData(const SkGlyph& glyph, SkMask* mask) {
1507 uint8_t* bits = (uint8_t*)(fGlyphCache->findImage(glyph));
1508 if (nullptr == bits) {
1509 return false; // can't rasterize glyph
1510 }
1511 mask->fImage = bits;
1512 mask->fRowBytes = glyph.rowBytes();
1513 mask->fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1514 return true;
1515 }
1516
1517 void blitMask(const SkMask& mask, const SkIRect& clip) const { 1454 void blitMask(const SkMask& mask, const SkIRect& clip) const {
1518 if (SkMask::kARGB32_Format == mask.fFormat) { 1455 if (SkMask::kARGB32_Format == mask.fFormat) {
1519 SkBitmap bm; 1456 this->blitMaskAsSprite(mask);
1520 bm.installPixels(
1521 SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBounds.he ight()),
1522 (SkPMColor*)mask.fImage, mask.fRowBytes);
1523
1524 fDraw.drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), fPaint);
1525 } else { 1457 } else {
1526 fBlitter->blitMask(mask, clip); 1458 fBlitter->blitMask(mask, clip);
1527 } 1459 }
1528 } 1460 }
1529 1461
1530 const bool fUseRegionToDraw; 1462 // mask must be kARGB32_Format
1531 SkGlyphCache * const fGlyphCache; 1463 void blitMaskAsSprite(const SkMask& mask) const;
1532 SkBlitter * const fBlitter;
1533 const SkRegion* const fClip;
1534 const SkDraw& fDraw;
1535 const SkPaint& fPaint;
1536 const SkIRect fClipBounds;
1537 }; 1464 };
1538 1465
1539 //////////////////////////////////////////////////////////////////////////////// //////////////////// 1466 static void D1G_RectClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy,
1467 const SkGlyph& glyph) {
1468 // Prevent glyphs from being drawn outside of or straddling the edge of devi ce space.
1469 if ((fx >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) ||
1470 (fx >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/) ||
1471 (fy >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) ||
1472 (fy >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/))
1473 {
1474 return;
1475 }
1476
1477 int left = Sk48Dot16FloorToInt(fx);
1478 int top = Sk48Dot16FloorToInt(fy);
1479 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1480 SkASSERT((nullptr == state.fClip && state.fAAClip) ||
1481 (state.fClip && nullptr == state.fAAClip && state.fClip->isRect())) ;
1482
1483 left += glyph.fLeft;
1484 top += glyph.fTop;
1485
1486 int right = left + glyph.fWidth;
1487 int bottom = top + glyph.fHeight;
1488
1489 SkMask mask;
1490 SkIRect storage;
1491 SkIRect* bounds = &mask.fBounds;
1492
1493 mask.fBounds.set(left, top, right, bottom);
1494
1495 // this extra test is worth it, assuming that most of the time it succeeds
1496 // since we can avoid writing to storage
1497 if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) {
1498 if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds))
1499 return;
1500 bounds = &storage;
1501 }
1502
1503 uint8_t* aa = (uint8_t*)glyph.fImage;
1504 if (nullptr == aa) {
1505 aa = (uint8_t*)state.fCache->findImage(glyph);
1506 if (nullptr == aa) {
1507 return; // can't rasterize glyph
1508 }
1509 }
1510
1511 mask.fRowBytes = glyph.rowBytes();
1512 mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1513 mask.fImage = aa;
1514 state.blitMask(mask, *bounds);
1515 }
1516
1517 static void D1G_RgnClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy,
1518 const SkGlyph& glyph) {
1519 int left = Sk48Dot16FloorToInt(fx);
1520 int top = Sk48Dot16FloorToInt(fy);
1521 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1522 SkASSERT(!state.fClip->isRect());
1523
1524 SkMask mask;
1525
1526 left += glyph.fLeft;
1527 top += glyph.fTop;
1528
1529 mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1530 SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
1531
1532 if (!clipper.done()) {
1533 const SkIRect& cr = clipper.rect();
1534 const uint8_t* aa = (uint8_t*)state.fCache->findImage(glyph);
1535 if (nullptr == aa) {
1536 return;
1537 }
1538
1539 mask.fRowBytes = glyph.rowBytes();
1540 mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1541 mask.fImage = (uint8_t*)aa;
1542 do {
1543 state.blitMask(mask, cr);
1544 clipper.next();
1545 } while (!clipper.done());
1546 }
1547 }
1548
1549 SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, Sk GlyphCache* cache,
1550 const SkPaint& pnt) {
1551 fDraw = draw;
1552 fBlitter = blitter;
1553 fCache = cache;
1554 fPaint = &pnt;
1555
1556 if (cache->isSubpixel()) {
1557 fHalfSampleX = fHalfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound);
1558 } else {
1559 fHalfSampleX = fHalfSampleY = SK_ScalarHalf;
1560 }
1561
1562 if (draw->fRC->isBW()) {
1563 fAAClip = nullptr;
1564 fClip = &draw->fRC->bwRgn();
1565 fClipBounds = fClip->getBounds();
1566 if (fClip->isRect()) {
1567 return D1G_RectClip;
1568 } else {
1569 return D1G_RgnClip;
1570 }
1571 } else { // aaclip
1572 fAAClip = &draw->fRC->aaRgn();
1573 fClip = nullptr;
1574 fClipBounds = fAAClip->getBounds();
1575 return D1G_RectClip;
1576 }
1577 }
1578
1579 void SkDraw1Glyph::blitMaskAsSprite(const SkMask& mask) const {
1580 SkASSERT(SkMask::kARGB32_Format == mask.fFormat);
1581
1582 SkBitmap bm;
1583 bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBoun ds.height()),
1584 (SkPMColor*)mask.fImage, mask.fRowBytes);
1585
1586 fDraw->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), *fPaint);
1587 }
1588
1589 ///////////////////////////////////////////////////////////////////////////////
1540 1590
1541 void SkDraw::drawText(const char text[], size_t byteLength, 1591 void SkDraw::drawText(const char text[], size_t byteLength,
1542 SkScalar x, SkScalar y, const SkPaint& paint) const { 1592 SkScalar x, SkScalar y, const SkPaint& paint) const {
1543 SkASSERT(byteLength == 0 || text != nullptr); 1593 SkASSERT(byteLength == 0 || text != nullptr);
1544 1594
1545 SkDEBUGCODE(this->validate();) 1595 SkDEBUGCODE(this->validate();)
1546 1596
1547 // nothing to draw 1597 // nothing to draw
1548 if (text == nullptr || byteLength == 0 || fRC->isEmpty()) { 1598 if (text == nullptr || byteLength == 0 || fRC->isEmpty()) {
1549 return; 1599 return;
1550 } 1600 }
1551 1601
1552 // SkScalarRec doesn't currently have a way of representing hairline stroke and 1602 // SkScalarRec doesn't currently have a way of representing hairline stroke and
1553 // will fill if its frame-width is 0. 1603 // will fill if its frame-width is 0.
1554 if (ShouldDrawTextAsPaths(paint, *fMatrix)) { 1604 if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
1555 this->drawText_asPaths(text, byteLength, x, y, paint); 1605 this->drawText_asPaths(text, byteLength, x, y, paint);
1556 return; 1606 return;
1557 } 1607 }
1558 1608
1559 SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix); 1609 SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix);
1560 SkGlyphCache* cache = autoCache.getCache(); 1610 SkGlyphCache* cache = autoCache.getCache();
1611
1561 1612
1562 // The Blitter Choose needs to be live while using the blitter below. 1613 // The Blitter Choose needs to be live while using the blitter below.
1563 SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); 1614 SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint);
1564 SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get()); 1615 SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get());
1565 DrawOneGlyph drawOneGlyph(*this, paint, cache, wrapper.getBlitter( )); 1616
1617 SkDraw1Glyph d1g;
1618 SkDraw1Glyph::Proc proc = d1g.init(this, wrapper.getBlitter(), cache, paint );
1566 1619
1567 SkFindAndPlaceGlyph::ProcessText( 1620 SkFindAndPlaceGlyph::ProcessText(
1568 paint.getTextEncoding(), text, byteLength, 1621 paint.getTextEncoding(), text, byteLength,
1569 {x, y}, *fMatrix, paint.getTextAlign(), cache, drawOneGlyph); 1622 {x, y}, *fMatrix, paint.getTextAlign(), cache,
1623 [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
1624 position += rounding;
1625 proc(d1g, SkScalarTo48Dot16(position.fX), SkScalarTo48Dot16(position .fY), glyph);
1626 }
1627 );
1570 } 1628 }
1571 1629
1572 ////////////////////////////////////////////////////////////////////////////// 1630 //////////////////////////////////////////////////////////////////////////////
1573 1631
1574 void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength, 1632 void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength,
1575 const SkScalar pos[], int scalarsPerPosition, 1633 const SkScalar pos[], int scalarsPerPosition,
1576 const SkPoint& offset, const SkPaint& origPaint ) const { 1634 const SkPoint& offset, const SkPaint& origPaint ) const {
1577 // setup our std paint, in hopes of getting hits in the cache 1635 // setup our std paint, in hopes of getting hits in the cache
1578 SkPaint paint(origPaint); 1636 SkPaint paint(origPaint);
1579 SkScalar matrixScale = paint.setupForAsPaths(); 1637 SkScalar matrixScale = paint.setupForAsPaths();
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1631 // nothing to draw 1689 // nothing to draw
1632 if (text == nullptr || byteLength == 0 || fRC->isEmpty()) { 1690 if (text == nullptr || byteLength == 0 || fRC->isEmpty()) {
1633 return; 1691 return;
1634 } 1692 }
1635 1693
1636 if (ShouldDrawTextAsPaths(paint, *fMatrix)) { 1694 if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
1637 this->drawPosText_asPaths(text, byteLength, pos, scalarsPerPosition, off set, paint); 1695 this->drawPosText_asPaths(text, byteLength, pos, scalarsPerPosition, off set, paint);
1638 return; 1696 return;
1639 } 1697 }
1640 1698
1641 SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix);
1642 SkGlyphCache* cache = autoCache.getCache();
1643
1644 // The Blitter Choose needs to be live while using the blitter below. 1699 // The Blitter Choose needs to be live while using the blitter below.
1645 SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); 1700 SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint);
1646 SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get()); 1701 SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get());
1647 DrawOneGlyph drawOneGlyph(*this, paint, cache, wrapper.getBlitter( )); 1702
1648 SkPaint::Align textAlignment = paint.getTextAlign(); 1703 SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix);
1704 SkGlyphCache* cache = autoCache.getCache();
1705 SkDraw1Glyph d1g;
1706 SkDraw1Glyph::Proc proc = d1g.init(this, wrapper.getBlitter(), cache, paint) ;
1707 SkPaint::Align textAlignment = paint.getTextAlign();
1649 1708
1650 SkFindAndPlaceGlyph::ProcessPosText( 1709 SkFindAndPlaceGlyph::ProcessPosText(
1651 paint.getTextEncoding(), text, byteLength, 1710 paint.getTextEncoding(), text, byteLength,
1652 offset, *fMatrix, pos, scalarsPerPosition, textAlignment, cache, drawOne Glyph); 1711 offset, *fMatrix, pos, scalarsPerPosition, textAlignment, cache,
1712 [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
1713 position += rounding;
1714 proc(d1g, SkScalarTo48Dot16(position.fX), SkScalarTo48Dot16(position .fY), glyph);
1715 }
1716 );
1653 } 1717 }
1654 1718
1655 #if defined _WIN32 && _MSC_VER >= 1300 1719 #if defined _WIN32 && _MSC_VER >= 1300
1656 #pragma warning ( pop ) 1720 #pragma warning ( pop )
1657 #endif 1721 #endif
1658 1722
1659 /////////////////////////////////////////////////////////////////////////////// 1723 ///////////////////////////////////////////////////////////////////////////////
1660 1724
1661 static SkScan::HairRCProc ChooseHairProc(bool doAntiAlias) { 1725 static SkScan::HairRCProc ChooseHairProc(bool doAntiAlias) {
1662 return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine; 1726 return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine;
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
2045 mask->fImage = SkMask::AllocImage(size); 2109 mask->fImage = SkMask::AllocImage(size);
2046 memset(mask->fImage, 0, mask->computeImageSize()); 2110 memset(mask->fImage, 0, mask->computeImageSize());
2047 } 2111 }
2048 2112
2049 if (SkMask::kJustComputeBounds_CreateMode != mode) { 2113 if (SkMask::kJustComputeBounds_CreateMode != mode) {
2050 draw_into_mask(*mask, devPath, style); 2114 draw_into_mask(*mask, devPath, style);
2051 } 2115 }
2052 2116
2053 return true; 2117 return true;
2054 } 2118 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698